2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.h>
22 #include <dali/public-api/math/vector2.h>
23 #include <dali/public-api/math/vector4.h>
24 #include <dali/public-api/object/property-map.h>
25 #include <dali/public-api/object/type-registry-helper.h>
29 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
30 #include <dali-toolkit/devel-api/controls/control-devel.h>
31 #include <dali-toolkit/internal/helpers/color-conversion.h>
32 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
42 const Dali::Vector2 DEFAULT_SCROLL_BAR_PADDING(8.0f, 6.0f);
46 return Toolkit::TextSelectionToolbar::New();
49 // Setup properties, signals and actions using the type-registry.
51 DALI_TYPE_REGISTRATION_BEGIN(Toolkit::TextSelectionToolbar, Toolkit::Control, Create);
53 DALI_PROPERTY_REGISTRATION(Toolkit, TextSelectionToolbar, "maxSize", VECTOR2, MAX_SIZE)
54 DALI_PROPERTY_REGISTRATION(Toolkit, TextSelectionToolbar, "enableOvershoot", BOOLEAN, ENABLE_OVERSHOOT)
55 DALI_PROPERTY_REGISTRATION(Toolkit, TextSelectionToolbar, "enableScrollBar", BOOLEAN, ENABLE_SCROLL_BAR)
56 DALI_PROPERTY_REGISTRATION(Toolkit, TextSelectionToolbar, "scrollBarPadding", VECTOR2, SCROLL_BAR_PADDING)
57 DALI_PROPERTY_REGISTRATION(Toolkit, TextSelectionToolbar, "scrollView", MAP, SCROLL_VIEW)
59 DALI_TYPE_REGISTRATION_END()
63 Dali::Toolkit::TextSelectionToolbar TextSelectionToolbar::New()
65 // Create the implementation, temporarily owned by this handle on stack
66 IntrusivePtr<TextSelectionToolbar> impl = new TextSelectionToolbar();
68 // Pass ownership to CustomActor handle
69 Dali::Toolkit::TextSelectionToolbar handle(*impl);
71 // Second-phase init of the implementation
72 // This can only be done after the CustomActor connection has been made...
78 void TextSelectionToolbar::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
80 Toolkit::TextSelectionToolbar selectionPopup = Toolkit::TextSelectionToolbar::DownCast(Dali::BaseHandle(object));
84 TextSelectionToolbar& impl(GetImpl(selectionPopup));
88 case Toolkit::TextSelectionToolbar::Property::MAX_SIZE:
90 impl.SetPopupMaxSize(value.Get<Vector2>());
93 case Toolkit::TextSelectionToolbar::Property::ENABLE_OVERSHOOT:
97 impl.mScrollView = Toolkit::ScrollView::New();
99 impl.mScrollView.SetOvershootEnabled(value.Get<bool>());
102 case Toolkit::TextSelectionToolbar::Property::ENABLE_SCROLL_BAR:
104 impl.SetUpScrollBar(value.Get<bool>());
107 case Toolkit::TextSelectionToolbar::Property::SCROLL_BAR_PADDING:
109 impl.SetScrollBarPadding(value.Get<Vector2>());
112 case Toolkit::TextSelectionToolbar::Property::SCROLL_VIEW:
114 // Get a Property::Map from the property if possible.
115 Property::Map setPropertyMap;
116 if(value.Get(setPropertyMap))
118 impl.ConfigureScrollview(setPropertyMap);
123 } // TextSelectionToolbar
126 Property::Value TextSelectionToolbar::GetProperty(BaseObject* object, Property::Index index)
128 Property::Value value;
130 Toolkit::TextSelectionToolbar selectionPopup = Toolkit::TextSelectionToolbar::DownCast(Dali::BaseHandle(object));
134 TextSelectionToolbar& impl(GetImpl(selectionPopup));
138 case Toolkit::TextSelectionToolbar::Property::MAX_SIZE:
140 value = impl.GetPopupMaxSize();
143 case Toolkit::TextSelectionToolbar::Property::ENABLE_OVERSHOOT:
145 value = impl.mScrollView.IsOvershootEnabled();
148 case Toolkit::TextSelectionToolbar::Property::ENABLE_SCROLL_BAR:
150 value = impl.mScrollBar ? true : false;
153 case Toolkit::TextSelectionToolbar::Property::SCROLL_BAR_PADDING:
155 value = impl.GetScrollBarPadding();
163 void TextSelectionToolbar::OnInitialize()
167 DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
168 return std::make_unique<DevelControl::ControlAccessible>(actor, Dali::Accessibility::Role::TOOL_BAR);
172 void TextSelectionToolbar::OnRelayout(const Vector2& size, RelayoutContainer& container)
174 float width = std::max(mTableOfButtons.GetNaturalSize().width, size.width);
175 mRulerX->SetDomain(RulerDomain(0.0, width, true));
176 mScrollView.SetRulerX(mRulerX);
180 float barWidth = std::min(mTableOfButtons.GetNaturalSize().width, size.width) - 2.f * mScrollBarPadding.x;
181 mScrollBar.SetProperty(Actor::Property::SIZE, Vector2(0.0f, barWidth));
185 void TextSelectionToolbar::SetPopupMaxSize(const Size& maxSize)
188 if(mScrollView && mToolbarActor)
190 mScrollView.SetProperty(Actor::Property::MAXIMUM_SIZE, mMaxSize);
191 mToolbarActor.SetProperty(Actor::Property::MAXIMUM_SIZE, mMaxSize);
195 const Dali::Vector2& TextSelectionToolbar::GetPopupMaxSize() const
200 void TextSelectionToolbar::SetUpScrollView()
202 mScrollView.SetProperty(Dali::Actor::Property::NAME, "TextSelectionScrollView");
203 mScrollView.SetResizePolicy(ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS);
204 mScrollView.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER_LEFT);
205 mScrollView.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER_LEFT);
207 mScrollView.SetScrollingDirection(PanGestureDetector::DIRECTION_HORIZONTAL, Degree(40.0f));
208 mScrollView.SetAxisAutoLock(true);
209 mScrollView.ScrollStartedSignal().Connect(this, &TextSelectionToolbar::OnScrollStarted);
210 mScrollView.ScrollCompletedSignal().Connect(this, &TextSelectionToolbar::OnScrollCompleted);
211 mScrollView.SetProperty(Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_TO_BOUNDING_BOX); // In a new layer, so clip to scroll-view's bounding box
213 mRulerX = new DefaultRuler(); // IntrusivePtr which is unreferenced when ScrollView is destroyed.
215 RulerPtr rulerY = new DefaultRuler(); // IntrusivePtr which is unreferenced when ScrollView is destroyed.
217 mScrollView.SetRulerY(rulerY);
219 mScrollView.SetOvershootEnabled(true);
222 void TextSelectionToolbar::SetUp()
226 self.SetResizePolicy(ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS);
228 // Create Actor to house the toolbar.
229 mToolbarActor = Actor::New();
230 mToolbarActor.SetResizePolicy(ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS);
231 mToolbarActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
232 mToolbarActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
236 mScrollView = Toolkit::ScrollView::New();
240 // Toolbar must start with at least one option, adding further options with increase it's size
241 mTableOfButtons = Dali::Toolkit::TableView::New(1, 1);
242 mTableOfButtons.SetFitHeight(0);
243 mTableOfButtons.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER_LEFT);
244 mTableOfButtons.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER_LEFT);
246 mScrollView.Add(mTableOfButtons);
247 mToolbarActor.Add(mScrollView);
249 self.Add(mToolbarActor);
252 void TextSelectionToolbar::SetUpScrollBar(bool enable)
258 Toolkit::ImageView indicator = Toolkit::ImageView::New();
259 indicator.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
260 indicator.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
261 indicator.SetStyleName("TextSelectionScrollIndicator");
263 mScrollBar = Toolkit::ScrollBar::New(Toolkit::ScrollBar::HORIZONTAL);
264 mScrollBar.SetProperty(Dali::Actor::Property::NAME, "Text popup scroll bar");
265 mScrollBar.SetStyleName("TextSelectionScrollBar");
266 mScrollBar.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_LEFT);
267 mScrollBar.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
268 mScrollBar.SetProperty(Actor::Property::POSITION, Vector2(mScrollBarPadding.x, -mScrollBarPadding.y));
269 mScrollBar.SetResizePolicy(Dali::ResizePolicy::FIT_TO_CHILDREN, Dali::Dimension::WIDTH);
270 mScrollBar.SetProperty(Actor::Property::ORIENTATION, Quaternion(Quaternion(Radian(1.5f * Math::PI), Vector3::ZAXIS)));
271 mScrollBar.SetScrollIndicator(indicator);
272 mScrollBar.GetPanGestureDetector().DetachAll();
273 mScrollView.Add(mScrollBar);
278 UnparentAndReset(mScrollBar);
282 void TextSelectionToolbar::OnScrollStarted(const Vector2& position)
286 mScrollView.SetOvershootEnabled(true);
288 mTableOfButtons.SetProperty(Actor::Property::SENSITIVE, false);
291 void TextSelectionToolbar::OnScrollCompleted(const Vector2& position)
293 mFirstScrollEnd = true;
294 mTableOfButtons.SetProperty(Actor::Property::SENSITIVE, true);
297 void TextSelectionToolbar::AddOption(Actor& option)
299 mTableOfButtons.AddChild(option, Toolkit::TableView::CellPosition(0, mIndexInTable));
300 mTableOfButtons.SetFitWidth(mIndexInTable);
304 void TextSelectionToolbar::AddDivider(Actor& divider)
307 mDividerIndexes.PushBack(mIndexInTable - 1u);
310 void TextSelectionToolbar::ResizeDividers(Size& size)
312 for(unsigned int i = 0; i < mDividerIndexes.Count(); ++i)
314 Actor divider = mTableOfButtons.GetChildAt(Toolkit::TableView::CellPosition(0, mDividerIndexes[i]));
315 divider.SetProperty(Actor::Property::SIZE, size);
320 void TextSelectionToolbar::RaiseAbove(Actor target)
322 mToolbarActor.RaiseAbove(target);
325 void TextSelectionToolbar::SetScrollBarPadding(const Vector2& padding)
327 mScrollBarPadding = padding;
330 mScrollBar.SetProperty(Actor::Property::POSITION, Vector2(mScrollBarPadding.x, -mScrollBarPadding.y));
336 void TextSelectionToolbar::ScrollTo(const Vector2& position)
338 mFirstScrollEnd = false;
339 mScrollView.SetOvershootEnabled(false);
340 mScrollView.ScrollTo(position, 0.f);
343 void TextSelectionToolbar::ConfigureScrollview(const Property::Map& properties)
345 // Set any properties specified for the label by iterating through all property key-value pairs.
346 for(unsigned int i = 0, mapCount = properties.Count(); i < mapCount; ++i)
348 const StringValuePair& propertyPair(properties.GetPair(i));
350 // Convert the property string to a property index.
351 Property::Index setPropertyIndex = mScrollView.GetPropertyIndex(propertyPair.first);
352 if(setPropertyIndex != Property::INVALID_INDEX)
354 // Convert the string representation of a color into a Vector4
355 if(setPropertyIndex == Toolkit::Scrollable::Property::OVERSHOOT_EFFECT_COLOR)
358 if(ConvertPropertyToColor(propertyPair.second, color))
360 mScrollView.SetOvershootEffectColor(color);
365 // If the conversion worked, we have a valid property index,
366 // Set the property to the new value.
367 mScrollView.SetProperty(setPropertyIndex, propertyPair.second);
375 const Vector2& TextSelectionToolbar::GetScrollBarPadding() const
377 return mScrollBarPadding;
380 TextSelectionToolbar::TextSelectionToolbar()
381 : Control(ControlBehaviour(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT))),
383 mScrollBarPadding(DEFAULT_SCROLL_BAR_PADDING),
386 mFirstScrollEnd(false)
390 TextSelectionToolbar::~TextSelectionToolbar()
395 } // namespace Internal
397 } // namespace Toolkit