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::unique_ptr<Dali::Accessibility::Accessible>(
169 new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::TOOL_BAR));
173 void TextSelectionToolbar::OnRelayout(const Vector2& size, RelayoutContainer& container)
175 float width = std::max(mTableOfButtons.GetNaturalSize().width, size.width);
176 mRulerX->SetDomain(RulerDomain(0.0, width, true));
177 mScrollView.SetRulerX(mRulerX);
181 float barWidth = std::min(mTableOfButtons.GetNaturalSize().width, size.width) - 2.f * mScrollBarPadding.x;
182 mScrollBar.SetProperty(Actor::Property::SIZE, Vector2(0.0f, barWidth));
186 void TextSelectionToolbar::SetPopupMaxSize(const Size& maxSize)
189 if(mScrollView && mToolbarActor)
191 mScrollView.SetProperty(Actor::Property::MAXIMUM_SIZE, mMaxSize);
192 mToolbarActor.SetProperty(Actor::Property::MAXIMUM_SIZE, mMaxSize);
196 const Dali::Vector2& TextSelectionToolbar::GetPopupMaxSize() const
201 void TextSelectionToolbar::SetUpScrollView()
203 mScrollView.SetProperty(Dali::Actor::Property::NAME, "TextSelectionScrollView");
204 mScrollView.SetResizePolicy(ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS);
205 mScrollView.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER_LEFT);
206 mScrollView.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER_LEFT);
208 mScrollView.SetScrollingDirection(PanGestureDetector::DIRECTION_HORIZONTAL, Degree(40.0f));
209 mScrollView.SetAxisAutoLock(true);
210 mScrollView.ScrollStartedSignal().Connect(this, &TextSelectionToolbar::OnScrollStarted);
211 mScrollView.ScrollCompletedSignal().Connect(this, &TextSelectionToolbar::OnScrollCompleted);
212 mScrollView.SetProperty(Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_TO_BOUNDING_BOX); // In a new layer, so clip to scroll-view's bounding box
214 mRulerX = new DefaultRuler(); // IntrusivePtr which is unreferenced when ScrollView is destroyed.
216 RulerPtr rulerY = new DefaultRuler(); // IntrusivePtr which is unreferenced when ScrollView is destroyed.
218 mScrollView.SetRulerY(rulerY);
220 mScrollView.SetOvershootEnabled(true);
223 void TextSelectionToolbar::SetUp()
227 self.SetResizePolicy(ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS);
229 // Create Actor to house the toolbar.
230 mToolbarActor = Actor::New();
231 mToolbarActor.SetResizePolicy(ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS);
232 mToolbarActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
233 mToolbarActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
237 mScrollView = Toolkit::ScrollView::New();
241 // Toolbar must start with at least one option, adding further options with increase it's size
242 mTableOfButtons = Dali::Toolkit::TableView::New(1, 1);
243 mTableOfButtons.SetFitHeight(0);
244 mTableOfButtons.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER_LEFT);
245 mTableOfButtons.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER_LEFT);
247 mScrollView.Add(mTableOfButtons);
248 mToolbarActor.Add(mScrollView);
250 self.Add(mToolbarActor);
253 void TextSelectionToolbar::SetUpScrollBar(bool enable)
259 Toolkit::ImageView indicator = Toolkit::ImageView::New();
260 indicator.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
261 indicator.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
262 indicator.SetStyleName("TextSelectionScrollIndicator");
264 mScrollBar = Toolkit::ScrollBar::New(Toolkit::ScrollBar::HORIZONTAL);
265 mScrollBar.SetProperty(Dali::Actor::Property::NAME, "Text popup scroll bar");
266 mScrollBar.SetStyleName("TextSelectionScrollBar");
267 mScrollBar.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_LEFT);
268 mScrollBar.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
269 mScrollBar.SetProperty(Actor::Property::POSITION, Vector2(mScrollBarPadding.x, -mScrollBarPadding.y));
270 mScrollBar.SetResizePolicy(Dali::ResizePolicy::FIT_TO_CHILDREN, Dali::Dimension::WIDTH);
271 mScrollBar.SetProperty(Actor::Property::ORIENTATION, Quaternion(Quaternion(Radian(1.5f * Math::PI), Vector3::ZAXIS)));
272 mScrollBar.SetScrollIndicator(indicator);
273 mScrollBar.GetPanGestureDetector().DetachAll();
274 mScrollView.Add(mScrollBar);
279 UnparentAndReset(mScrollBar);
283 void TextSelectionToolbar::OnScrollStarted(const Vector2& position)
287 mScrollView.SetOvershootEnabled(true);
289 mTableOfButtons.SetProperty(Actor::Property::SENSITIVE, false);
292 void TextSelectionToolbar::OnScrollCompleted(const Vector2& position)
294 mFirstScrollEnd = true;
295 mTableOfButtons.SetProperty(Actor::Property::SENSITIVE, true);
298 void TextSelectionToolbar::AddOption(Actor& option)
300 mTableOfButtons.AddChild(option, Toolkit::TableView::CellPosition(0, mIndexInTable));
301 mTableOfButtons.SetFitWidth(mIndexInTable);
305 void TextSelectionToolbar::AddDivider(Actor& divider)
308 mDividerIndexes.PushBack(mIndexInTable - 1u);
311 void TextSelectionToolbar::ResizeDividers(Size& size)
313 for(unsigned int i = 0; i < mDividerIndexes.Count(); ++i)
315 Actor divider = mTableOfButtons.GetChildAt(Toolkit::TableView::CellPosition(0, mDividerIndexes[i]));
316 divider.SetProperty(Actor::Property::SIZE, size);
321 void TextSelectionToolbar::RaiseAbove(Actor target)
323 mToolbarActor.RaiseAbove(target);
326 void TextSelectionToolbar::SetScrollBarPadding(const Vector2& padding)
328 mScrollBarPadding = padding;
331 mScrollBar.SetProperty(Actor::Property::POSITION, Vector2(mScrollBarPadding.x, -mScrollBarPadding.y));
337 void TextSelectionToolbar::ScrollTo(const Vector2& position)
339 mFirstScrollEnd = false;
340 mScrollView.SetOvershootEnabled(false);
341 mScrollView.ScrollTo(position, 0.f);
344 void TextSelectionToolbar::ConfigureScrollview(const Property::Map& properties)
346 // Set any properties specified for the label by iterating through all property key-value pairs.
347 for(unsigned int i = 0, mapCount = properties.Count(); i < mapCount; ++i)
349 const StringValuePair& propertyPair(properties.GetPair(i));
351 // Convert the property string to a property index.
352 Property::Index setPropertyIndex = mScrollView.GetPropertyIndex(propertyPair.first);
353 if(setPropertyIndex != Property::INVALID_INDEX)
355 // Convert the string representation of a color into a Vector4
356 if(setPropertyIndex == Toolkit::Scrollable::Property::OVERSHOOT_EFFECT_COLOR)
359 if(ConvertPropertyToColor(propertyPair.second, color))
361 mScrollView.SetOvershootEffectColor(color);
366 // If the conversion worked, we have a valid property index,
367 // Set the property to the new value.
368 mScrollView.SetProperty(setPropertyIndex, propertyPair.second);
376 const Vector2& TextSelectionToolbar::GetScrollBarPadding() const
378 return mScrollBarPadding;
381 TextSelectionToolbar::TextSelectionToolbar()
382 : Control(ControlBehaviour(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT))),
384 mScrollBarPadding(DEFAULT_SCROLL_BAR_PADDING),
387 mFirstScrollEnd(false)
391 TextSelectionToolbar::~TextSelectionToolbar()
396 } // namespace Internal
398 } // namespace Toolkit