--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-property-handler.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h>
+#include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-mode.h>
+
+namespace Dali::Toolkit::Internal
+{
+
+void ScrollViewPropertyHandler::Set(BaseObject* object, Property::Index index, const Property::Value& value)
+{
+ Toolkit::ScrollView scrollView = Toolkit::ScrollView::DownCast(Dali::BaseHandle(object));
+
+ if(scrollView)
+ {
+ ScrollView& scrollViewImpl(GetImpl(scrollView));
+ switch(index)
+ {
+ case Toolkit::ScrollView::Property::WRAP_ENABLED:
+ {
+ scrollViewImpl.SetWrapMode(value.Get<bool>());
+ break;
+ }
+ case Toolkit::ScrollView::Property::PANNING_ENABLED:
+ {
+ scrollViewImpl.SetScrollSensitive(value.Get<bool>());
+ break;
+ }
+ case Toolkit::ScrollView::Property::AXIS_AUTO_LOCK_ENABLED:
+ {
+ scrollViewImpl.SetAxisAutoLock(value.Get<bool>());
+ break;
+ }
+ case Toolkit::ScrollView::Property::WHEEL_SCROLL_DISTANCE_STEP:
+ {
+ scrollViewImpl.SetWheelScrollDistanceStep(value.Get<Vector2>());
+ break;
+ }
+ case Toolkit::ScrollView::Property::SCROLL_MODE:
+ {
+ const Property::Map* map = value.GetMap();
+ if(map)
+ {
+ SetScrollMode(scrollViewImpl, *map);
+ }
+ }
+ }
+ }
+}
+
+Property::Value ScrollViewPropertyHandler::Get(BaseObject* object, Property::Index index)
+{
+ Property::Value value;
+
+ Toolkit::ScrollView scrollView = Toolkit::ScrollView::DownCast(Dali::BaseHandle(object));
+
+ if(scrollView)
+ {
+ ScrollView& scrollViewImpl(GetImpl(scrollView));
+ switch(index)
+ {
+ case Toolkit::ScrollView::Property::WRAP_ENABLED:
+ {
+ value = scrollViewImpl.GetWrapMode();
+ break;
+ }
+ case Toolkit::ScrollView::Property::PANNING_ENABLED:
+ {
+ value = scrollViewImpl.GetScrollSensitive();
+ break;
+ }
+ case Toolkit::ScrollView::Property::AXIS_AUTO_LOCK_ENABLED:
+ {
+ value = scrollViewImpl.GetAxisAutoLock();
+ break;
+ }
+ case Toolkit::ScrollView::Property::WHEEL_SCROLL_DISTANCE_STEP:
+ {
+ value = scrollViewImpl.GetWheelScrollDistanceStep();
+ break;
+ }
+ }
+ }
+
+ return value;
+}
+
+void ScrollViewPropertyHandler::SetScrollMode(ScrollView& scrollView, const Property::Map& scrollModeMap)
+{
+ Toolkit::RulerPtr rulerX, rulerY;
+
+ // Check the scroll mode in the X axis
+ bool xAxisScrollEnabled = true;
+ Property::Value* valuePtr = scrollModeMap.Find(Toolkit::ScrollMode::X_AXIS_SCROLL_ENABLED, "xAxisScrollEnabled");
+ if(valuePtr && valuePtr->GetType() == Property::BOOLEAN)
+ {
+ valuePtr->Get(xAxisScrollEnabled);
+ }
+
+ if(!xAxisScrollEnabled)
+ {
+ // Default ruler and disabled
+ rulerX = new Toolkit::DefaultRuler();
+ rulerX->Disable();
+ }
+ else
+ {
+ valuePtr = scrollModeMap.Find(Toolkit::ScrollMode::X_AXIS_SNAP_TO_INTERVAL, "xAxisSnapToInterval");
+ float xAxisSnapToInterval = 0.0f;
+ if(valuePtr && valuePtr->Get(xAxisSnapToInterval))
+ {
+ // Fixed ruler and enabled
+ rulerX = new Toolkit::FixedRuler(xAxisSnapToInterval);
+ }
+ else
+ {
+ // Default ruler and enabled
+ rulerX = new Toolkit::DefaultRuler();
+ }
+
+ valuePtr = scrollModeMap.Find(Toolkit::ScrollMode::X_AXIS_SCROLL_BOUNDARY, "xAxisScrollBoundary");
+ float xAxisScrollBoundary = 0.0f;
+ if(valuePtr && valuePtr->Get(xAxisScrollBoundary))
+ {
+ // By default ruler domain is disabled unless set
+ rulerX->SetDomain(Toolkit::RulerDomain(0, xAxisScrollBoundary, true));
+ }
+ }
+
+ // Check the scroll mode in the Y axis
+ bool yAxisScrollEnabled = true;
+ valuePtr = scrollModeMap.Find(Toolkit::ScrollMode::Y_AXIS_SCROLL_ENABLED, "yAxisScrollEnabled");
+ if(valuePtr && valuePtr->GetType() == Property::BOOLEAN)
+ {
+ valuePtr->Get(yAxisScrollEnabled);
+ }
+
+ if(!yAxisScrollEnabled)
+ {
+ // Default ruler and disabled
+ rulerY = new Toolkit::DefaultRuler();
+ rulerY->Disable();
+ }
+ else
+ {
+ valuePtr = scrollModeMap.Find(Toolkit::ScrollMode::Y_AXIS_SNAP_TO_INTERVAL, "yAxisSnapToInterval");
+ float yAxisSnapToInterval = 0.0f;
+ if(valuePtr && valuePtr->Get(yAxisSnapToInterval))
+ {
+ // Fixed ruler and enabled
+ rulerY = new Toolkit::FixedRuler(yAxisSnapToInterval);
+ }
+ else
+ {
+ // Default ruler and enabled
+ rulerY = new Toolkit::DefaultRuler();
+ }
+
+ valuePtr = scrollModeMap.Find(Toolkit::ScrollMode::Y_AXIS_SCROLL_BOUNDARY, "yAxisScrollBoundary");
+ float yAxisScrollBoundary = 0.0f;
+ if(valuePtr && valuePtr->Get(yAxisScrollBoundary))
+ {
+ // By default ruler domain is disabled unless set
+ rulerY->SetDomain(Toolkit::RulerDomain(0, yAxisScrollBoundary, true));
+ }
+ }
+
+ scrollView.SetRulerX(rulerX);
+ scrollView.SetRulerY(rulerY);
+}
+
+void ScrollViewPropertyHandler::UpdatePropertyDomain(ScrollView& scrollView)
+{
+ Actor self = scrollView.Self();
+ Vector3 size = self.GetTargetSize();
+ Vector2 min = scrollView.mMinScroll;
+ Vector2 max = scrollView.mMaxScroll;
+ bool scrollPositionChanged = false;
+ bool domainChanged = false;
+
+ bool canScrollVertical = false;
+ bool canScrollHorizontal = false;
+ scrollView.UpdateLocalScrollProperties();
+ if(scrollView.mRulerX->IsEnabled())
+ {
+ const Toolkit::RulerDomain& rulerDomain = scrollView.mRulerX->GetDomain();
+ if(fabsf(min.x - rulerDomain.min) > Math::MACHINE_EPSILON_100 || fabsf(max.x - rulerDomain.max) > Math::MACHINE_EPSILON_100)
+ {
+ domainChanged = true;
+ min.x = rulerDomain.min;
+ max.x = rulerDomain.max;
+
+ // make sure new scroll value is within new domain
+ if(scrollView.mScrollPrePosition.x < min.x || scrollView.mScrollPrePosition.x > max.x)
+ {
+ scrollPositionChanged = true;
+ scrollView.mScrollPrePosition.x = Clamp(scrollView.mScrollPrePosition.x, -(max.x - size.x), -min.x);
+ }
+ }
+ if((fabsf(rulerDomain.max - rulerDomain.min) - size.x) > Math::MACHINE_EPSILON_100)
+ {
+ canScrollHorizontal = true;
+ }
+ }
+ else if(fabs(min.x) > Math::MACHINE_EPSILON_100 || fabs(max.x) > Math::MACHINE_EPSILON_100)
+ {
+ // need to reset to 0
+ domainChanged = true;
+ min.x = 0.0f;
+ max.x = 0.0f;
+ canScrollHorizontal = false;
+ }
+
+ if(scrollView.mRulerY->IsEnabled())
+ {
+ const Toolkit::RulerDomain& rulerDomain = scrollView.mRulerY->GetDomain();
+ if(fabsf(min.y - rulerDomain.min) > Math::MACHINE_EPSILON_100 || fabsf(max.y - rulerDomain.max) > Math::MACHINE_EPSILON_100)
+ {
+ domainChanged = true;
+ min.y = rulerDomain.min;
+ max.y = rulerDomain.max;
+
+ // make sure new scroll value is within new domain
+ if(scrollView.mScrollPrePosition.y < min.y || scrollView.mScrollPrePosition.y > max.y)
+ {
+ scrollPositionChanged = true;
+ scrollView.mScrollPrePosition.y = Clamp(scrollView.mScrollPrePosition.y, -(max.y - size.y), -min.y);
+ }
+ }
+ if((fabsf(rulerDomain.max - rulerDomain.min) - size.y) > Math::MACHINE_EPSILON_100)
+ {
+ canScrollVertical = true;
+ }
+ }
+ else if(fabs(min.y) > Math::MACHINE_EPSILON_100 || fabs(max.y) > Math::MACHINE_EPSILON_100)
+ {
+ // need to reset to 0
+ domainChanged = true;
+ min.y = 0.0f;
+ max.y = 0.0f;
+ canScrollVertical = false;
+ }
+
+ // avoid setting properties if possible, otherwise this will cause an entire update as well as triggering constraints using each property we update
+ if(scrollView.mCanScrollVertical != canScrollVertical)
+ {
+ scrollView.mCanScrollVertical = canScrollVertical;
+ self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_VERTICAL, canScrollVertical);
+ }
+ if(scrollView.mCanScrollHorizontal != canScrollHorizontal)
+ {
+ scrollView.mCanScrollHorizontal = canScrollHorizontal;
+ self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL, canScrollHorizontal);
+ }
+ if(scrollPositionChanged)
+ {
+ self.SetProperty(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION, scrollView.mScrollPrePosition);
+ }
+ if(domainChanged)
+ {
+ scrollView.mMinScroll = min;
+ scrollView.mMaxScroll = max;
+ self.SetProperty(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN, scrollView.mMinScroll);
+ self.SetProperty(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX, scrollView.mMaxScroll);
+ }
+}
+
+} // namespace Dali::Toolkit::Internal
--- /dev/null
+#ifndef DALI_TOOLKIT_INTERNAL_SCROLL_VIEW_IMPL_PROPERTY_HANDLER_H
+#define DALI_TOOLKIT_INTERNAL_SCROLL_VIEW_IMPL_PROPERTY_HANDLER_H
+
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/base-object.h>
+#include <dali/public-api/object/property.h>
+
+namespace Dali::Toolkit::Internal
+{
+class ScrollView;
+
+/// Handles the properties in scroll view calling the appropriate scroll view methods
+struct ScrollViewPropertyHandler
+{
+ /**
+ * @brief Sets the property on the given scroll-view object.
+ *
+ * @param object The scrollview object
+ * @param index The index to set
+ * @param value The value to set
+ */
+ static void Set(BaseObject* object, Property::Index index, const Property::Value& value);
+
+ /**
+ * @brief Retrieves the value of a scroll-view property.
+ *
+ * @param object The scrollview object
+ * @param index The index whose value is to be retrieved
+ * @return
+ */
+ static Property::Value Get(BaseObject* object, Property::Index index);
+
+ /**
+ * Set up default rulers using a property map
+ * @param[in] scrollView The scroll view to apply this on
+ * @param[in] scrollModeMap A map defining the characteristics of X and Y scrolling
+ * using either FixedRuler or DefaultRuler.
+ */
+ static void SetScrollMode(ScrollView& scrollView, const Property::Map& scrollModeMap);
+
+ /**
+ * This is called whenever the Scroll Rulers are modified.
+ *
+ * This will update the properties: 'scrollPositionMin' * and 'scrollPositionMax' to reflect the changes.
+ * @param scrollView The Scroll View to modify
+ */
+ static void UpdatePropertyDomain(ScrollView& scrollView);
+};
+
+} // namespace Dali::Toolkit::Internal
+
+#endif // DALI_TOOLKIT_INTERNAL_SCROLL_VIEW_IMPL_PROPERTY_HANDLER_H
#include <dali-toolkit/devel-api/controls/scroll-bar/scroll-bar.h>
#include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-overshoot-indicator-impl.h>
#include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-effect-impl.h>
+#include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-property-handler.h>
#include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-mode.h>
#include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view-constraints.h>
#include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.h>
self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_VERTICAL, mCanScrollVertical);
self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL, mCanScrollHorizontal);
- UpdatePropertyDomain();
+ ScrollViewPropertyHandler::UpdatePropertyDomain(*this);
mConstraints.SetInternalConstraints(*this);
// Connect wheel event
{
mRulerX = ruler;
- UpdatePropertyDomain();
+ ScrollViewPropertyHandler::UpdatePropertyDomain(*this);
mConstraints.UpdateMainInternalConstraint(*this);
}
{
mRulerY = ruler;
- UpdatePropertyDomain();
+ ScrollViewPropertyHandler::UpdatePropertyDomain(*this);
mConstraints.UpdateMainInternalConstraint(*this);
}
-void ScrollView::UpdatePropertyDomain()
-{
- Actor self = Self();
- Vector3 size = self.GetTargetSize();
- Vector2 min = mMinScroll;
- Vector2 max = mMaxScroll;
- bool scrollPositionChanged = false;
- bool domainChanged = false;
-
- bool canScrollVertical = false;
- bool canScrollHorizontal = false;
- UpdateLocalScrollProperties();
- if(mRulerX->IsEnabled())
- {
- const Toolkit::RulerDomain& rulerDomain = mRulerX->GetDomain();
- if(fabsf(min.x - rulerDomain.min) > Math::MACHINE_EPSILON_100 || fabsf(max.x - rulerDomain.max) > Math::MACHINE_EPSILON_100)
- {
- domainChanged = true;
- min.x = rulerDomain.min;
- max.x = rulerDomain.max;
-
- // make sure new scroll value is within new domain
- if(mScrollPrePosition.x < min.x || mScrollPrePosition.x > max.x)
- {
- scrollPositionChanged = true;
- mScrollPrePosition.x = Clamp(mScrollPrePosition.x, -(max.x - size.x), -min.x);
- }
- }
- if((fabsf(rulerDomain.max - rulerDomain.min) - size.x) > Math::MACHINE_EPSILON_100)
- {
- canScrollHorizontal = true;
- }
- }
- else if(fabs(min.x) > Math::MACHINE_EPSILON_100 || fabs(max.x) > Math::MACHINE_EPSILON_100)
- {
- // need to reset to 0
- domainChanged = true;
- min.x = 0.0f;
- max.x = 0.0f;
- canScrollHorizontal = false;
- }
-
- if(mRulerY->IsEnabled())
- {
- const Toolkit::RulerDomain& rulerDomain = mRulerY->GetDomain();
- if(fabsf(min.y - rulerDomain.min) > Math::MACHINE_EPSILON_100 || fabsf(max.y - rulerDomain.max) > Math::MACHINE_EPSILON_100)
- {
- domainChanged = true;
- min.y = rulerDomain.min;
- max.y = rulerDomain.max;
-
- // make sure new scroll value is within new domain
- if(mScrollPrePosition.y < min.y || mScrollPrePosition.y > max.y)
- {
- scrollPositionChanged = true;
- mScrollPrePosition.y = Clamp(mScrollPrePosition.y, -(max.y - size.y), -min.y);
- }
- }
- if((fabsf(rulerDomain.max - rulerDomain.min) - size.y) > Math::MACHINE_EPSILON_100)
- {
- canScrollVertical = true;
- }
- }
- else if(fabs(min.y) > Math::MACHINE_EPSILON_100 || fabs(max.y) > Math::MACHINE_EPSILON_100)
- {
- // need to reset to 0
- domainChanged = true;
- min.y = 0.0f;
- max.y = 0.0f;
- canScrollVertical = false;
- }
-
- // avoid setting properties if possible, otherwise this will cause an entire update as well as triggering constraints using each property we update
- if(mCanScrollVertical != canScrollVertical)
- {
- mCanScrollVertical = canScrollVertical;
- self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_VERTICAL, canScrollVertical);
- }
- if(mCanScrollHorizontal != canScrollHorizontal)
- {
- mCanScrollHorizontal = canScrollHorizontal;
- self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL, canScrollHorizontal);
- }
- if(scrollPositionChanged)
- {
- DALI_LOG_SCROLL_STATE("[0x%X] Domain Changed, setting SCROLL_PRE_POSITION To[%.2f, %.2f]", this, mScrollPrePosition.x, mScrollPrePosition.y);
- self.SetProperty(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION, mScrollPrePosition);
- }
- if(domainChanged)
- {
- mMinScroll = min;
- mMaxScroll = max;
- self.SetProperty(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN, mMinScroll);
- self.SetProperty(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX, mMaxScroll);
- }
-}
-
void ScrollView::SetScrollSensitive(bool sensitive)
{
Actor self = Self();
void ScrollView::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
{
// need to update domain properties for new size
- UpdatePropertyDomain();
+ ScrollViewPropertyHandler::UpdatePropertyDomain(*this);
}
void ScrollView::OnSizeSet(const Vector3& size)
mMaxOvershoot = mUserMaxOvershoot;
}
}
- UpdatePropertyDomain();
+ ScrollViewPropertyHandler::UpdatePropertyDomain(*this);
mConstraints.UpdateMainInternalConstraint(*this);
if(IsOvershootEnabled())
{
}
}
-Vector2 ScrollView::GetOvershoot(Vector2& position) const
-{
- Vector3 size = Self().GetCurrentProperty<Vector3>(Actor::Property::SIZE);
- Vector2 overshoot;
-
- const RulerDomain rulerDomainX = mRulerX->GetDomain();
- const RulerDomain rulerDomainY = mRulerY->GetDomain();
-
- if(mRulerX->IsEnabled() && rulerDomainX.enabled)
- {
- const float left = rulerDomainX.min - position.x;
- const float right = size.width - rulerDomainX.max - position.x;
- if(left < 0)
- {
- overshoot.x = left;
- }
- else if(right > 0)
- {
- overshoot.x = right;
- }
- }
-
- if(mRulerY->IsEnabled() && rulerDomainY.enabled)
- {
- const float top = rulerDomainY.min - position.y;
- const float bottom = size.height - rulerDomainY.max - position.y;
- if(top < 0)
- {
- overshoot.y = top;
- }
- else if(bottom > 0)
- {
- overshoot.y = bottom;
- }
- }
-
- return overshoot;
-}
-
bool ScrollView::OnAccessibilityPan(PanGesture gesture)
{
// Keep track of whether this is an AccessibilityPan
void ScrollView::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
{
- Toolkit::ScrollView scrollView = Toolkit::ScrollView::DownCast(Dali::BaseHandle(object));
-
- if(scrollView)
- {
- ScrollView& scrollViewImpl(GetImpl(scrollView));
- switch(index)
- {
- case Toolkit::ScrollView::Property::WRAP_ENABLED:
- {
- scrollViewImpl.SetWrapMode(value.Get<bool>());
- break;
- }
- case Toolkit::ScrollView::Property::PANNING_ENABLED:
- {
- scrollViewImpl.SetScrollSensitive(value.Get<bool>());
- break;
- }
- case Toolkit::ScrollView::Property::AXIS_AUTO_LOCK_ENABLED:
- {
- scrollViewImpl.SetAxisAutoLock(value.Get<bool>());
- break;
- }
- case Toolkit::ScrollView::Property::WHEEL_SCROLL_DISTANCE_STEP:
- {
- scrollViewImpl.SetWheelScrollDistanceStep(value.Get<Vector2>());
- break;
- }
- case Toolkit::ScrollView::Property::SCROLL_MODE:
- {
- const Property::Map* map = value.GetMap();
- if(map)
- {
- scrollViewImpl.SetScrollMode(*map);
- }
- }
- }
- }
+ ScrollViewPropertyHandler::Set(object, index, value);
}
Property::Value ScrollView::GetProperty(BaseObject* object, Property::Index index)
{
- Property::Value value;
-
- Toolkit::ScrollView scrollView = Toolkit::ScrollView::DownCast(Dali::BaseHandle(object));
-
- if(scrollView)
- {
- ScrollView& scrollViewImpl(GetImpl(scrollView));
- switch(index)
- {
- case Toolkit::ScrollView::Property::WRAP_ENABLED:
- {
- value = scrollViewImpl.GetWrapMode();
- break;
- }
- case Toolkit::ScrollView::Property::PANNING_ENABLED:
- {
- value = scrollViewImpl.GetScrollSensitive();
- break;
- }
- case Toolkit::ScrollView::Property::AXIS_AUTO_LOCK_ENABLED:
- {
- value = scrollViewImpl.GetAxisAutoLock();
- break;
- }
- case Toolkit::ScrollView::Property::WHEEL_SCROLL_DISTANCE_STEP:
- {
- value = scrollViewImpl.GetWheelScrollDistanceStep();
- break;
- }
- }
- }
-
- return value;
-}
-
-void ScrollView::SetScrollMode(const Property::Map& scrollModeMap)
-{
- Toolkit::RulerPtr rulerX, rulerY;
-
- // Check the scroll mode in the X axis
- bool xAxisScrollEnabled = true;
- Property::Value* valuePtr = scrollModeMap.Find(Toolkit::ScrollMode::X_AXIS_SCROLL_ENABLED, "xAxisScrollEnabled");
- if(valuePtr && valuePtr->GetType() == Property::BOOLEAN)
- {
- valuePtr->Get(xAxisScrollEnabled);
- }
-
- if(!xAxisScrollEnabled)
- {
- // Default ruler and disabled
- rulerX = new Toolkit::DefaultRuler();
- rulerX->Disable();
- }
- else
- {
- valuePtr = scrollModeMap.Find(Toolkit::ScrollMode::X_AXIS_SNAP_TO_INTERVAL, "xAxisSnapToInterval");
- float xAxisSnapToInterval = 0.0f;
- if(valuePtr && valuePtr->Get(xAxisSnapToInterval))
- {
- // Fixed ruler and enabled
- rulerX = new Toolkit::FixedRuler(xAxisSnapToInterval);
- }
- else
- {
- // Default ruler and enabled
- rulerX = new Toolkit::DefaultRuler();
- }
-
- valuePtr = scrollModeMap.Find(Toolkit::ScrollMode::X_AXIS_SCROLL_BOUNDARY, "xAxisScrollBoundary");
- float xAxisScrollBoundary = 0.0f;
- if(valuePtr && valuePtr->Get(xAxisScrollBoundary))
- {
- // By default ruler domain is disabled unless set
- rulerX->SetDomain(Toolkit::RulerDomain(0, xAxisScrollBoundary, true));
- }
- }
-
- // Check the scroll mode in the Y axis
- bool yAxisScrollEnabled = true;
- valuePtr = scrollModeMap.Find(Toolkit::ScrollMode::Y_AXIS_SCROLL_ENABLED, "yAxisScrollEnabled");
- if(valuePtr && valuePtr->GetType() == Property::BOOLEAN)
- {
- valuePtr->Get(yAxisScrollEnabled);
- }
-
- if(!yAxisScrollEnabled)
- {
- // Default ruler and disabled
- rulerY = new Toolkit::DefaultRuler();
- rulerY->Disable();
- }
- else
- {
- valuePtr = scrollModeMap.Find(Toolkit::ScrollMode::Y_AXIS_SNAP_TO_INTERVAL, "yAxisSnapToInterval");
- float yAxisSnapToInterval = 0.0f;
- if(valuePtr && valuePtr->Get(yAxisSnapToInterval))
- {
- // Fixed ruler and enabled
- rulerY = new Toolkit::FixedRuler(yAxisSnapToInterval);
- }
- else
- {
- // Default ruler and enabled
- rulerY = new Toolkit::DefaultRuler();
- }
-
- valuePtr = scrollModeMap.Find(Toolkit::ScrollMode::Y_AXIS_SCROLL_BOUNDARY, "yAxisScrollBoundary");
- float yAxisScrollBoundary = 0.0f;
- if(valuePtr && valuePtr->Get(yAxisScrollBoundary))
- {
- // By default ruler domain is disabled unless set
- rulerY->SetDomain(Toolkit::RulerDomain(0, yAxisScrollBoundary, true));
- }
- }
-
- SetRulerX(rulerX);
- SetRulerY(rulerY);
+ return ScrollViewPropertyHandler::Get(object, index);
}
ScrollView::LockAxis GetLockAxis(const Vector2& panDelta, ScrollView::LockAxis currentLockAxis, float lockGradient)
class ScrollOvershootIndicator;
typedef IntrusivePtr<ScrollOvershootIndicator> ScrollOvershootIndicatorPtr;
+class ScrollViewPropertyHandler;
+
/**
* @copydoc Toolkit::ScrollView
*/
void SnapInternalYTo(float position);
/**
- * This is called internally whenever the Scroll Rulers are
- * modified. This will update the properties: 'scrollPositionMin'
- * and 'scrollPositionMax' to reflect the changes.
- */
- void UpdatePropertyDomain();
-
- /**
* Called when the gesture starts.
*/
void GestureStarted();
void FinishTransform();
/**
- * Returns overshoot vector based on current position
- *
- * Overshoot vector is defined as how far outside of bounds
- * the viewport is trying to view (prior to being clamped).
- *
- * an overshoot of (100,50), means user is in bottom right corner,
- * trying to pan +100 to the right, and +50 below. This can be used
- * to determine an effect, such as stretching.
- *
- * @param[in] position The position for which you wish to obtain overshoot vector
- */
- Vector2 GetOvershoot(Vector2& position) const;
-
- /**
* Clamps position within the domain set up by X/Y Rulers
*
* @param[in,out] position The position you wish to clamp
*/
void OnScrollUpdateNotification(Dali::PropertyNotification& source);
- /**
- * Set up default rulers using a property map
- * @param[in] scrollModeMap A map defining the characteristics of X and Y scrolling
- * using either FixedRuler or DefaultRuler.
- */
- void SetScrollMode(const Property::Map& scrollModeMap);
-
private:
// Undefined
ScrollView(const ScrollView&);
bool mTransientScrollBar : 1; ///< True if scroll-bar should be automatically show/hidden during/after panning
friend ScrollViewConstraints;
+ friend ScrollViewPropertyHandler;
};
/**
${toolkit_src_dir}/controls/scrollable/scroll-view/scroll-view-effect-impl.cpp
${toolkit_src_dir}/controls/scrollable/scroll-view/scroll-view-impl.cpp
${toolkit_src_dir}/controls/scrollable/scroll-view/scroll-view-impl-constraints.cpp
+ ${toolkit_src_dir}/controls/scrollable/scroll-view/scroll-view-impl-property-handler.cpp
${toolkit_src_dir}/controls/scrollable/scroll-view/scroll-view-page-path-effect-impl.cpp
${toolkit_src_dir}/controls/scene3d-view/scene3d-view-impl.cpp
${toolkit_src_dir}/controls/scene3d-view/gltf-loader.cpp
${toolkit_src_dir}/text/text-controller.cpp
${toolkit_src_dir}/text/text-controller-event-handler.cpp
${toolkit_src_dir}/text/text-controller-impl.cpp
+ ${toolkit_src_dir}/text/text-controller-impl-data-clearer.cpp
${toolkit_src_dir}/text/text-controller-impl-event-handler.cpp
${toolkit_src_dir}/text/text-controller-impl-model-updater.cpp
${toolkit_src_dir}/text/text-controller-input-font-handler.cpp
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/text/text-controller-impl-data-clearer.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/text-controller-impl.h>
+#include <dali-toolkit/internal/text/text-run-container.h>
+
+namespace Dali::Toolkit::Text
+{
+
+void ControllerImplDataClearer::ClearFullModelData(Controller::Impl& impl, Controller::OperationsMask operations)
+{
+ ModelPtr& model = impl.mModel;
+
+ if(Controller::NO_OPERATION != (Controller::GET_LINE_BREAKS & operations))
+ {
+ model->mLogicalModel->mLineBreakInfo.Clear();
+ model->mLogicalModel->mParagraphInfo.Clear();
+ }
+
+ if(Controller::NO_OPERATION != (Controller::GET_SCRIPTS & operations))
+ {
+ model->mLogicalModel->mScriptRuns.Clear();
+ }
+
+ if(Controller::NO_OPERATION != (Controller::VALIDATE_FONTS & operations))
+ {
+ model->mLogicalModel->mFontRuns.Clear();
+ }
+
+ if(0u != model->mLogicalModel->mBidirectionalParagraphInfo.Count())
+ {
+ if(Controller::NO_OPERATION != (Controller::BIDI_INFO & operations))
+ {
+ model->mLogicalModel->mBidirectionalParagraphInfo.Clear();
+ model->mLogicalModel->mCharacterDirections.Clear();
+ }
+
+ if(Controller::NO_OPERATION != (Controller::REORDER & operations))
+ {
+ // Free the allocated memory used to store the conversion table in the bidirectional line info run.
+ for(Vector<BidirectionalLineInfoRun>::Iterator it = model->mLogicalModel->mBidirectionalLineInfo.Begin(),
+ endIt = model->mLogicalModel->mBidirectionalLineInfo.End();
+ it != endIt;
+ ++it)
+ {
+ BidirectionalLineInfoRun& bidiLineInfo = *it;
+
+ free(bidiLineInfo.visualToLogicalMap);
+ bidiLineInfo.visualToLogicalMap = NULL;
+ }
+ model->mLogicalModel->mBidirectionalLineInfo.Clear();
+ }
+ }
+
+ if(Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations))
+ {
+ model->mVisualModel->mGlyphs.Clear();
+ model->mVisualModel->mGlyphsToCharacters.Clear();
+ model->mVisualModel->mCharactersToGlyph.Clear();
+ model->mVisualModel->mCharactersPerGlyph.Clear();
+ model->mVisualModel->mGlyphsPerCharacter.Clear();
+ model->mVisualModel->mGlyphPositions.Clear();
+ }
+
+ if(Controller::NO_OPERATION != (Controller::LAYOUT & operations))
+ {
+ model->mVisualModel->mLines.Clear();
+ }
+
+ if(Controller::NO_OPERATION != (Controller::COLOR & operations))
+ {
+ model->mVisualModel->mColorIndices.Clear();
+ model->mVisualModel->mBackgroundColorIndices.Clear();
+ }
+}
+
+void ControllerImplDataClearer::ClearCharacterModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations)
+{
+ const CharacterIndex endIndexPlusOne = endIndex + 1u;
+ ModelPtr& model = impl.mModel;
+
+ if(Controller::NO_OPERATION != (Controller::GET_LINE_BREAKS & operations))
+ {
+ // Clear the line break info.
+ LineBreakInfo* lineBreakInfoBuffer = model->mLogicalModel->mLineBreakInfo.Begin();
+
+ model->mLogicalModel->mLineBreakInfo.Erase(lineBreakInfoBuffer + startIndex,
+ lineBreakInfoBuffer + endIndexPlusOne);
+
+ // Clear the paragraphs.
+ ClearCharacterRuns(startIndex,
+ endIndex,
+ model->mLogicalModel->mParagraphInfo);
+ }
+
+ if(Controller::NO_OPERATION != (Controller::GET_SCRIPTS & operations))
+ {
+ // Clear the scripts.
+ ClearCharacterRuns(startIndex,
+ endIndex,
+ model->mLogicalModel->mScriptRuns);
+ }
+
+ if(Controller::NO_OPERATION != (Controller::VALIDATE_FONTS & operations))
+ {
+ // Clear the fonts.
+ ClearCharacterRuns(startIndex,
+ endIndex,
+ model->mLogicalModel->mFontRuns);
+ }
+
+ if(0u != model->mLogicalModel->mBidirectionalParagraphInfo.Count())
+ {
+ if(Controller::NO_OPERATION != (Controller::BIDI_INFO & operations))
+ {
+ // Clear the bidirectional paragraph info.
+ ClearCharacterRuns(startIndex,
+ endIndex,
+ model->mLogicalModel->mBidirectionalParagraphInfo);
+
+ // Clear the character's directions.
+ CharacterDirection* characterDirectionsBuffer = model->mLogicalModel->mCharacterDirections.Begin();
+
+ model->mLogicalModel->mCharacterDirections.Erase(characterDirectionsBuffer + startIndex,
+ characterDirectionsBuffer + endIndexPlusOne);
+ }
+
+ if(Controller::NO_OPERATION != (Controller::REORDER & operations))
+ {
+ uint32_t startRemoveIndex = model->mLogicalModel->mBidirectionalLineInfo.Count();
+ uint32_t endRemoveIndex = startRemoveIndex;
+ ClearCharacterRuns(startIndex,
+ endIndex,
+ model->mLogicalModel->mBidirectionalLineInfo,
+ startRemoveIndex,
+ endRemoveIndex);
+
+ BidirectionalLineInfoRun* bidirectionalLineInfoBuffer = model->mLogicalModel->mBidirectionalLineInfo.Begin();
+
+ // Free the allocated memory used to store the conversion table in the bidirectional line info run.
+ for(Vector<BidirectionalLineInfoRun>::Iterator it = bidirectionalLineInfoBuffer + startRemoveIndex,
+ endIt = bidirectionalLineInfoBuffer + endRemoveIndex;
+ it != endIt;
+ ++it)
+ {
+ BidirectionalLineInfoRun& bidiLineInfo = *it;
+
+ free(bidiLineInfo.visualToLogicalMap);
+ bidiLineInfo.visualToLogicalMap = NULL;
+ }
+
+ model->mLogicalModel->mBidirectionalLineInfo.Erase(bidirectionalLineInfoBuffer + startRemoveIndex,
+ bidirectionalLineInfoBuffer + endRemoveIndex);
+ }
+ }
+}
+
+void ControllerImplDataClearer::ClearGlyphModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations)
+{
+ const CharacterIndex endIndexPlusOne = endIndex + 1u;
+ const Length numberOfCharactersRemoved = endIndexPlusOne - startIndex;
+ ModelPtr& model = impl.mModel;
+ TextUpdateInfo& textUpdateInfo = impl.mTextUpdateInfo;
+
+
+ // Convert the character index to glyph index before deleting the character to glyph and the glyphs per character buffers.
+ GlyphIndex* charactersToGlyphBuffer = model->mVisualModel->mCharactersToGlyph.Begin();
+ Length* glyphsPerCharacterBuffer = model->mVisualModel->mGlyphsPerCharacter.Begin();
+
+ const GlyphIndex endGlyphIndexPlusOne = *(charactersToGlyphBuffer + endIndex) + *(glyphsPerCharacterBuffer + endIndex);
+ const Length numberOfGlyphsRemoved = endGlyphIndexPlusOne - textUpdateInfo.mStartGlyphIndex;
+
+ if(Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations))
+ {
+ // Update the character to glyph indices.
+ for(Vector<GlyphIndex>::Iterator it = charactersToGlyphBuffer + endIndexPlusOne,
+ endIt = charactersToGlyphBuffer + model->mVisualModel->mCharactersToGlyph.Count();
+ it != endIt;
+ ++it)
+ {
+ CharacterIndex& index = *it;
+ index -= numberOfGlyphsRemoved;
+ }
+
+ // Clear the character to glyph conversion table.
+ model->mVisualModel->mCharactersToGlyph.Erase(charactersToGlyphBuffer + startIndex,
+ charactersToGlyphBuffer + endIndexPlusOne);
+
+ // Clear the glyphs per character table.
+ model->mVisualModel->mGlyphsPerCharacter.Erase(glyphsPerCharacterBuffer + startIndex,
+ glyphsPerCharacterBuffer + endIndexPlusOne);
+
+ // Clear the glyphs buffer.
+ GlyphInfo* glyphsBuffer = model->mVisualModel->mGlyphs.Begin();
+ model->mVisualModel->mGlyphs.Erase(glyphsBuffer + textUpdateInfo.mStartGlyphIndex,
+ glyphsBuffer + endGlyphIndexPlusOne);
+
+ CharacterIndex* glyphsToCharactersBuffer = model->mVisualModel->mGlyphsToCharacters.Begin();
+
+ // Update the glyph to character indices.
+ for(Vector<CharacterIndex>::Iterator it = glyphsToCharactersBuffer + endGlyphIndexPlusOne,
+ endIt = glyphsToCharactersBuffer + model->mVisualModel->mGlyphsToCharacters.Count();
+ it != endIt;
+ ++it)
+ {
+ CharacterIndex& index = *it;
+ index -= numberOfCharactersRemoved;
+ }
+
+ // Clear the glyphs to characters buffer.
+ model->mVisualModel->mGlyphsToCharacters.Erase(glyphsToCharactersBuffer + textUpdateInfo.mStartGlyphIndex,
+ glyphsToCharactersBuffer + endGlyphIndexPlusOne);
+
+ // Clear the characters per glyph buffer.
+ Length* charactersPerGlyphBuffer = model->mVisualModel->mCharactersPerGlyph.Begin();
+ model->mVisualModel->mCharactersPerGlyph.Erase(charactersPerGlyphBuffer + textUpdateInfo.mStartGlyphIndex,
+ charactersPerGlyphBuffer + endGlyphIndexPlusOne);
+
+ // Should pass if mGlyphPositions has already been cleared in Controller::Relayouter::Relayout
+ if(0u != model->mVisualModel->mGlyphPositions.Count())
+ {
+ // Clear the positions buffer.
+ Vector2* positionsBuffer = model->mVisualModel->mGlyphPositions.Begin();
+ model->mVisualModel->mGlyphPositions.Erase(positionsBuffer + textUpdateInfo.mStartGlyphIndex,
+ positionsBuffer + endGlyphIndexPlusOne);
+ }
+ }
+
+ if(Controller::NO_OPERATION != (Controller::LAYOUT & operations))
+ {
+ // Clear the lines.
+ uint32_t startRemoveIndex = model->mVisualModel->mLines.Count();
+ uint32_t endRemoveIndex = startRemoveIndex;
+ ClearCharacterRuns(startIndex,
+ endIndex,
+ model->mVisualModel->mLines,
+ startRemoveIndex,
+ endRemoveIndex);
+
+ // Will update the glyph runs.
+ startRemoveIndex = model->mVisualModel->mLines.Count();
+ endRemoveIndex = startRemoveIndex;
+ ClearGlyphRuns(textUpdateInfo.mStartGlyphIndex,
+ endGlyphIndexPlusOne - 1u,
+ model->mVisualModel->mLines,
+ startRemoveIndex,
+ endRemoveIndex);
+
+ // Set the line index from where to insert the new laid-out lines.
+ textUpdateInfo.mStartLineIndex = startRemoveIndex;
+
+ LineRun* linesBuffer = model->mVisualModel->mLines.Begin();
+ model->mVisualModel->mLines.Erase(linesBuffer + startRemoveIndex,
+ linesBuffer + endRemoveIndex);
+ }
+
+ if(Controller::NO_OPERATION != (Controller::COLOR & operations))
+ {
+ if(0u != model->mVisualModel->mColorIndices.Count())
+ {
+ ColorIndex* colorIndexBuffer = model->mVisualModel->mColorIndices.Begin();
+ model->mVisualModel->mColorIndices.Erase(colorIndexBuffer + textUpdateInfo.mStartGlyphIndex,
+ colorIndexBuffer + endGlyphIndexPlusOne);
+ }
+
+ if(0u != model->mVisualModel->mBackgroundColorIndices.Count())
+ {
+ ColorIndex* backgroundColorIndexBuffer = model->mVisualModel->mBackgroundColorIndices.Begin();
+ model->mVisualModel->mBackgroundColorIndices.Erase(backgroundColorIndexBuffer + textUpdateInfo.mStartGlyphIndex,
+ backgroundColorIndexBuffer + endGlyphIndexPlusOne);
+ }
+ }
+}
+
+void ControllerImplDataClearer::ClearModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations)
+{
+ TextUpdateInfo& textUpdateInfo = impl.mTextUpdateInfo;
+
+ if(textUpdateInfo.mClearAll ||
+ ((0u == startIndex) &&
+ (textUpdateInfo.mPreviousNumberOfCharacters == endIndex + 1u)))
+ {
+ ClearFullModelData(impl, operations);
+ }
+ else
+ {
+ // Clear the model data related with characters.
+ ClearCharacterModelData(impl, startIndex, endIndex, operations);
+
+ // Clear the model data related with glyphs.
+ ClearGlyphModelData(impl, startIndex, endIndex, operations);
+ }
+
+ ModelPtr& model = impl.mModel;
+
+ // The estimated number of lines. Used to avoid reallocations when layouting.
+ textUpdateInfo.mEstimatedNumberOfLines = std::max(model->mVisualModel->mLines.Count(), model->mLogicalModel->mParagraphInfo.Count());
+
+ model->mVisualModel->ClearCaches();
+}
+
+} // namespace Dali::Toolkit::Text
--- /dev/null
+#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_DATA_CLEARER_H
+#define DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_DATA_CLEARER_H
+
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/text-controller.h>
+
+namespace Dali::Toolkit::Text
+{
+
+/// Provides methods to clear some of the model data in the Text::Controller::Impl
+struct ControllerImplDataClearer
+{
+
+ /**
+ * @brief Helper to clear completely the parts of the model specified by the given @p operations.
+ *
+ * @note It never clears the text stored in utf32.
+ *
+ * @param[in] impl The text controller impl.
+ * @param[in] operations The operations required.
+ */
+ static void ClearFullModelData(Controller::Impl& impl, Controller::OperationsMask operations);
+
+ /**
+ * @brief Helper to clear completely the parts of the model related with the characters specified by the given @p operations.
+ *
+ * @note It never clears the text stored in utf32.
+ *
+ * @param[in] impl The text controller impl.
+ * @param[in] startIndex Index to the first character to be cleared.
+ * @param[in] endIndex Index to the last character to be cleared.
+ * @param[in] operations The operations required.
+ */
+ static void ClearCharacterModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations);
+
+ /**
+ * @brief Helper to clear completely the parts of the model related with the glyphs specified by the given @p operations.
+ *
+ * @note It never clears the text stored in utf32.
+ * @note Character indices are transformed to glyph indices.
+ *
+ * @param[in] impl The text controller impl.
+ * @param[in] startIndex Index to the first character to be cleared.
+ * @param[in] endIndex Index to the last character to be cleared.
+ * @param[in] operations The operations required.
+ */
+ static void ClearGlyphModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations);
+
+ /**
+ * @brief Helper to clear the parts of the model specified by the given @p operations and from @p startIndex to @p endIndex.
+ *
+ * @note It never clears the text stored in utf32.
+ *
+ * @param[in] impl The text controller impl.
+ * @param[in] startIndex Index to the first character to be cleared.
+ * @param[in] endIndex Index to the last character to be cleared.
+ * @param[in] operations The operations required.
+ */
+ static void ClearModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations);
+};
+
+} // namespace Dali::Toolkit::Text
+
+#endif // DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_DATA_CLEARER_H
#include <dali-toolkit/internal/text/text-controller-impl.h>
// EXTERNAL INCLUDES
+#include <cmath>
#include <dali/integration-api/debug.h>
#include <dali/public-api/rendering/renderer.h>
+#include <dali/devel-api/adaptor-framework/window-devel.h>
// INTERNAL INCLUDES
#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
#include <dali-toolkit/internal/text/character-set-conversion.h>
#include <dali-toolkit/internal/text/cursor-helper-functions.h>
#include <dali-toolkit/internal/text/text-control-interface.h>
+#include <dali-toolkit/internal/text/text-controller-impl-data-clearer.h>
#include <dali-toolkit/internal/text/text-controller-impl-event-handler.h>
#include <dali-toolkit/internal/text/text-controller-impl-model-updater.h>
#include <dali-toolkit/internal/text/text-editable-control-interface.h>
}
}
}
+
+void ChangeTextControllerState(Controller::Impl& impl, EventData::State newState)
+{
+ EventData* eventData = impl.mEventData;
+
+ if(nullptr == eventData)
+ {
+ // Nothing to do if there is no text input.
+ return;
+ }
+
+ DecoratorPtr& decorator = eventData->mDecorator;
+ if(!decorator)
+ {
+ // Nothing to do if there is no decorator.
+ return;
+ }
+
+ DALI_LOG_INFO(gLogFilter, Debug::General, "ChangeState state:%d newstate:%d\n", eventData->mState, newState);
+
+ if(eventData->mState != newState)
+ {
+ eventData->mPreviousState = eventData->mState;
+ eventData->mState = newState;
+
+ switch(eventData->mState)
+ {
+ case EventData::INACTIVE:
+ {
+ decorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
+ decorator->StopCursorBlink();
+ decorator->SetHandleActive(GRAB_HANDLE, false);
+ decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
+ decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
+ decorator->SetHighlightActive(false);
+ decorator->SetPopupActive(false);
+ eventData->mDecoratorUpdated = true;
+ break;
+ }
+
+ case EventData::INTERRUPTED:
+ {
+ decorator->SetHandleActive(GRAB_HANDLE, false);
+ decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
+ decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
+ decorator->SetHighlightActive(false);
+ decorator->SetPopupActive(false);
+ eventData->mDecoratorUpdated = true;
+ break;
+ }
+
+ case EventData::SELECTING:
+ {
+ decorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
+ decorator->StopCursorBlink();
+ decorator->SetHandleActive(GRAB_HANDLE, false);
+ if(eventData->mGrabHandleEnabled)
+ {
+ decorator->SetHandleActive(LEFT_SELECTION_HANDLE, true);
+ decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, true);
+ }
+ decorator->SetHighlightActive(true);
+ if(eventData->mGrabHandlePopupEnabled)
+ {
+ impl.SetPopupButtons();
+ decorator->SetPopupActive(true);
+ }
+ eventData->mDecoratorUpdated = true;
+ break;
+ }
+
+ case EventData::EDITING:
+ {
+ decorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
+ if(eventData->mCursorBlinkEnabled)
+ {
+ decorator->StartCursorBlink();
+ }
+ // Grab handle is not shown until a tap is received whilst EDITING
+ decorator->SetHandleActive(GRAB_HANDLE, false);
+ decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
+ decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
+ decorator->SetHighlightActive(false);
+ if(eventData->mGrabHandlePopupEnabled)
+ {
+ decorator->SetPopupActive(false);
+ }
+ eventData->mDecoratorUpdated = true;
+ break;
+ }
+ case EventData::EDITING_WITH_POPUP:
+ {
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_POPUP \n", newState);
+
+ decorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
+ if(eventData->mCursorBlinkEnabled)
+ {
+ decorator->StartCursorBlink();
+ }
+ if(eventData->mSelectionEnabled)
+ {
+ decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
+ decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
+ decorator->SetHighlightActive(false);
+ }
+ else if(eventData->mGrabHandleEnabled)
+ {
+ decorator->SetHandleActive(GRAB_HANDLE, true);
+ }
+ if(eventData->mGrabHandlePopupEnabled)
+ {
+ impl.SetPopupButtons();
+ decorator->SetPopupActive(true);
+ }
+ eventData->mDecoratorUpdated = true;
+ break;
+ }
+ case EventData::EDITING_WITH_GRAB_HANDLE:
+ {
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_GRAB_HANDLE \n", newState);
+
+ decorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
+ if(eventData->mCursorBlinkEnabled)
+ {
+ decorator->StartCursorBlink();
+ }
+ // Grab handle is not shown until a tap is received whilst EDITING
+ if(eventData->mGrabHandleEnabled)
+ {
+ decorator->SetHandleActive(GRAB_HANDLE, true);
+ }
+ decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
+ decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
+ decorator->SetHighlightActive(false);
+ if(eventData->mGrabHandlePopupEnabled)
+ {
+ decorator->SetPopupActive(false);
+ }
+ eventData->mDecoratorUpdated = true;
+ break;
+ }
+
+ case EventData::SELECTION_HANDLE_PANNING:
+ {
+ decorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
+ decorator->StopCursorBlink();
+ decorator->SetHandleActive(GRAB_HANDLE, false);
+ if(eventData->mGrabHandleEnabled)
+ {
+ decorator->SetHandleActive(LEFT_SELECTION_HANDLE, true);
+ decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, true);
+ }
+ decorator->SetHighlightActive(true);
+ if(eventData->mGrabHandlePopupEnabled)
+ {
+ decorator->SetPopupActive(false);
+ }
+ eventData->mDecoratorUpdated = true;
+ break;
+ }
+
+ case EventData::GRAB_HANDLE_PANNING:
+ {
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "GRAB_HANDLE_PANNING \n", newState);
+
+ decorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
+ if(eventData->mCursorBlinkEnabled)
+ {
+ decorator->StartCursorBlink();
+ }
+ if(eventData->mGrabHandleEnabled)
+ {
+ decorator->SetHandleActive(GRAB_HANDLE, true);
+ }
+ decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
+ decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
+ decorator->SetHighlightActive(false);
+ if(eventData->mGrabHandlePopupEnabled)
+ {
+ decorator->SetPopupActive(false);
+ }
+ eventData->mDecoratorUpdated = true;
+ break;
+ }
+
+ case EventData::EDITING_WITH_PASTE_POPUP:
+ {
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_PASTE_POPUP \n", newState);
+
+ decorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
+ if(eventData->mCursorBlinkEnabled)
+ {
+ decorator->StartCursorBlink();
+ }
+
+ if(eventData->mGrabHandleEnabled)
+ {
+ decorator->SetHandleActive(GRAB_HANDLE, true);
+ }
+ decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
+ decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
+ decorator->SetHighlightActive(false);
+
+ if(eventData->mGrabHandlePopupEnabled)
+ {
+ impl.SetPopupButtons();
+ decorator->SetPopupActive(true);
+ }
+ eventData->mDecoratorUpdated = true;
+ break;
+ }
+
+ case EventData::TEXT_PANNING:
+ {
+ decorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
+ decorator->StopCursorBlink();
+ decorator->SetHandleActive(GRAB_HANDLE, false);
+ if(eventData->mDecorator->IsHandleActive(LEFT_SELECTION_HANDLE) ||
+ decorator->IsHandleActive(RIGHT_SELECTION_HANDLE))
+ {
+ decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
+ decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
+ decorator->SetHighlightActive(true);
+ }
+
+ if(eventData->mGrabHandlePopupEnabled)
+ {
+ decorator->SetPopupActive(false);
+ }
+
+ eventData->mDecoratorUpdated = true;
+ break;
+ }
+ }
+ }
+}
+
} // unnamed Namespace
EventData::EventData(DecoratorPtr decorator, InputMethodContext& inputMethodContext)
}
}
+Dali::LayoutDirection::Type Controller::Impl::GetLayoutDirection(Dali::Actor& actor) const
+{
+ if(mModel->mMatchLayoutDirection == DevelText::MatchLayoutDirection::LOCALE ||
+ (mModel->mMatchLayoutDirection == DevelText::MatchLayoutDirection::INHERIT && !mIsLayoutDirectionChanged))
+ {
+ return static_cast<Dali::LayoutDirection::Type>(DevelWindow::Get(actor).GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
+ }
+ else
+ {
+ return static_cast<Dali::LayoutDirection::Type>(actor.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
+ }
+}
+
void Controller::Impl::CalculateTextUpdateIndices(Length& numberOfCharacters)
{
mTextUpdateInfo.mParagraphCharacterIndex = 0u;
mTextUpdateInfo.mStartGlyphIndex = *(mModel->mVisualModel->mCharactersToGlyph.Begin() + mTextUpdateInfo.mParagraphCharacterIndex);
}
-void Controller::Impl::ClearFullModelData(OperationsMask operations)
-{
- if(NO_OPERATION != (GET_LINE_BREAKS & operations))
- {
- mModel->mLogicalModel->mLineBreakInfo.Clear();
- mModel->mLogicalModel->mParagraphInfo.Clear();
- }
-
- if(NO_OPERATION != (GET_SCRIPTS & operations))
- {
- mModel->mLogicalModel->mScriptRuns.Clear();
- }
-
- if(NO_OPERATION != (VALIDATE_FONTS & operations))
- {
- mModel->mLogicalModel->mFontRuns.Clear();
- }
-
- if(0u != mModel->mLogicalModel->mBidirectionalParagraphInfo.Count())
- {
- if(NO_OPERATION != (BIDI_INFO & operations))
- {
- mModel->mLogicalModel->mBidirectionalParagraphInfo.Clear();
- mModel->mLogicalModel->mCharacterDirections.Clear();
- }
-
- if(NO_OPERATION != (REORDER & operations))
- {
- // Free the allocated memory used to store the conversion table in the bidirectional line info run.
- for(Vector<BidirectionalLineInfoRun>::Iterator it = mModel->mLogicalModel->mBidirectionalLineInfo.Begin(),
- endIt = mModel->mLogicalModel->mBidirectionalLineInfo.End();
- it != endIt;
- ++it)
- {
- BidirectionalLineInfoRun& bidiLineInfo = *it;
-
- free(bidiLineInfo.visualToLogicalMap);
- bidiLineInfo.visualToLogicalMap = NULL;
- }
- mModel->mLogicalModel->mBidirectionalLineInfo.Clear();
- }
- }
-
- if(NO_OPERATION != (SHAPE_TEXT & operations))
- {
- mModel->mVisualModel->mGlyphs.Clear();
- mModel->mVisualModel->mGlyphsToCharacters.Clear();
- mModel->mVisualModel->mCharactersToGlyph.Clear();
- mModel->mVisualModel->mCharactersPerGlyph.Clear();
- mModel->mVisualModel->mGlyphsPerCharacter.Clear();
- mModel->mVisualModel->mGlyphPositions.Clear();
- }
-
- if(NO_OPERATION != (LAYOUT & operations))
- {
- mModel->mVisualModel->mLines.Clear();
- }
-
- if(NO_OPERATION != (COLOR & operations))
- {
- mModel->mVisualModel->mColorIndices.Clear();
- mModel->mVisualModel->mBackgroundColorIndices.Clear();
- }
-}
-
-void Controller::Impl::ClearCharacterModelData(CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations)
-{
- const CharacterIndex endIndexPlusOne = endIndex + 1u;
-
- if(NO_OPERATION != (GET_LINE_BREAKS & operations))
- {
- // Clear the line break info.
- LineBreakInfo* lineBreakInfoBuffer = mModel->mLogicalModel->mLineBreakInfo.Begin();
-
- mModel->mLogicalModel->mLineBreakInfo.Erase(lineBreakInfoBuffer + startIndex,
- lineBreakInfoBuffer + endIndexPlusOne);
-
- // Clear the paragraphs.
- ClearCharacterRuns(startIndex,
- endIndex,
- mModel->mLogicalModel->mParagraphInfo);
- }
-
- if(NO_OPERATION != (GET_SCRIPTS & operations))
- {
- // Clear the scripts.
- ClearCharacterRuns(startIndex,
- endIndex,
- mModel->mLogicalModel->mScriptRuns);
- }
-
- if(NO_OPERATION != (VALIDATE_FONTS & operations))
- {
- // Clear the fonts.
- ClearCharacterRuns(startIndex,
- endIndex,
- mModel->mLogicalModel->mFontRuns);
- }
-
- if(0u != mModel->mLogicalModel->mBidirectionalParagraphInfo.Count())
- {
- if(NO_OPERATION != (BIDI_INFO & operations))
- {
- // Clear the bidirectional paragraph info.
- ClearCharacterRuns(startIndex,
- endIndex,
- mModel->mLogicalModel->mBidirectionalParagraphInfo);
-
- // Clear the character's directions.
- CharacterDirection* characterDirectionsBuffer = mModel->mLogicalModel->mCharacterDirections.Begin();
-
- mModel->mLogicalModel->mCharacterDirections.Erase(characterDirectionsBuffer + startIndex,
- characterDirectionsBuffer + endIndexPlusOne);
- }
-
- if(NO_OPERATION != (REORDER & operations))
- {
- uint32_t startRemoveIndex = mModel->mLogicalModel->mBidirectionalLineInfo.Count();
- uint32_t endRemoveIndex = startRemoveIndex;
- ClearCharacterRuns(startIndex,
- endIndex,
- mModel->mLogicalModel->mBidirectionalLineInfo,
- startRemoveIndex,
- endRemoveIndex);
-
- BidirectionalLineInfoRun* bidirectionalLineInfoBuffer = mModel->mLogicalModel->mBidirectionalLineInfo.Begin();
-
- // Free the allocated memory used to store the conversion table in the bidirectional line info run.
- for(Vector<BidirectionalLineInfoRun>::Iterator it = bidirectionalLineInfoBuffer + startRemoveIndex,
- endIt = bidirectionalLineInfoBuffer + endRemoveIndex;
- it != endIt;
- ++it)
- {
- BidirectionalLineInfoRun& bidiLineInfo = *it;
-
- free(bidiLineInfo.visualToLogicalMap);
- bidiLineInfo.visualToLogicalMap = NULL;
- }
-
- mModel->mLogicalModel->mBidirectionalLineInfo.Erase(bidirectionalLineInfoBuffer + startRemoveIndex,
- bidirectionalLineInfoBuffer + endRemoveIndex);
- }
- }
-}
-
-void Controller::Impl::ClearGlyphModelData(CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations)
-{
- const CharacterIndex endIndexPlusOne = endIndex + 1u;
- const Length numberOfCharactersRemoved = endIndexPlusOne - startIndex;
-
- // Convert the character index to glyph index before deleting the character to glyph and the glyphs per character buffers.
- GlyphIndex* charactersToGlyphBuffer = mModel->mVisualModel->mCharactersToGlyph.Begin();
- Length* glyphsPerCharacterBuffer = mModel->mVisualModel->mGlyphsPerCharacter.Begin();
-
- const GlyphIndex endGlyphIndexPlusOne = *(charactersToGlyphBuffer + endIndex) + *(glyphsPerCharacterBuffer + endIndex);
- const Length numberOfGlyphsRemoved = endGlyphIndexPlusOne - mTextUpdateInfo.mStartGlyphIndex;
-
- if(NO_OPERATION != (SHAPE_TEXT & operations))
- {
- // Update the character to glyph indices.
- for(Vector<GlyphIndex>::Iterator it = charactersToGlyphBuffer + endIndexPlusOne,
- endIt = charactersToGlyphBuffer + mModel->mVisualModel->mCharactersToGlyph.Count();
- it != endIt;
- ++it)
- {
- CharacterIndex& index = *it;
- index -= numberOfGlyphsRemoved;
- }
-
- // Clear the character to glyph conversion table.
- mModel->mVisualModel->mCharactersToGlyph.Erase(charactersToGlyphBuffer + startIndex,
- charactersToGlyphBuffer + endIndexPlusOne);
-
- // Clear the glyphs per character table.
- mModel->mVisualModel->mGlyphsPerCharacter.Erase(glyphsPerCharacterBuffer + startIndex,
- glyphsPerCharacterBuffer + endIndexPlusOne);
-
- // Clear the glyphs buffer.
- GlyphInfo* glyphsBuffer = mModel->mVisualModel->mGlyphs.Begin();
- mModel->mVisualModel->mGlyphs.Erase(glyphsBuffer + mTextUpdateInfo.mStartGlyphIndex,
- glyphsBuffer + endGlyphIndexPlusOne);
-
- CharacterIndex* glyphsToCharactersBuffer = mModel->mVisualModel->mGlyphsToCharacters.Begin();
-
- // Update the glyph to character indices.
- for(Vector<CharacterIndex>::Iterator it = glyphsToCharactersBuffer + endGlyphIndexPlusOne,
- endIt = glyphsToCharactersBuffer + mModel->mVisualModel->mGlyphsToCharacters.Count();
- it != endIt;
- ++it)
- {
- CharacterIndex& index = *it;
- index -= numberOfCharactersRemoved;
- }
-
- // Clear the glyphs to characters buffer.
- mModel->mVisualModel->mGlyphsToCharacters.Erase(glyphsToCharactersBuffer + mTextUpdateInfo.mStartGlyphIndex,
- glyphsToCharactersBuffer + endGlyphIndexPlusOne);
-
- // Clear the characters per glyph buffer.
- Length* charactersPerGlyphBuffer = mModel->mVisualModel->mCharactersPerGlyph.Begin();
- mModel->mVisualModel->mCharactersPerGlyph.Erase(charactersPerGlyphBuffer + mTextUpdateInfo.mStartGlyphIndex,
- charactersPerGlyphBuffer + endGlyphIndexPlusOne);
-
- // Should pass if mGlyphPositions has already been cleared in Controller::Relayouter::Relayout
- if(0u != mModel->mVisualModel->mGlyphPositions.Count())
- {
- // Clear the positions buffer.
- Vector2* positionsBuffer = mModel->mVisualModel->mGlyphPositions.Begin();
- mModel->mVisualModel->mGlyphPositions.Erase(positionsBuffer + mTextUpdateInfo.mStartGlyphIndex,
- positionsBuffer + endGlyphIndexPlusOne);
- }
- }
-
- if(NO_OPERATION != (LAYOUT & operations))
- {
- // Clear the lines.
- uint32_t startRemoveIndex = mModel->mVisualModel->mLines.Count();
- uint32_t endRemoveIndex = startRemoveIndex;
- ClearCharacterRuns(startIndex,
- endIndex,
- mModel->mVisualModel->mLines,
- startRemoveIndex,
- endRemoveIndex);
-
- // Will update the glyph runs.
- startRemoveIndex = mModel->mVisualModel->mLines.Count();
- endRemoveIndex = startRemoveIndex;
- ClearGlyphRuns(mTextUpdateInfo.mStartGlyphIndex,
- endGlyphIndexPlusOne - 1u,
- mModel->mVisualModel->mLines,
- startRemoveIndex,
- endRemoveIndex);
-
- // Set the line index from where to insert the new laid-out lines.
- mTextUpdateInfo.mStartLineIndex = startRemoveIndex;
-
- LineRun* linesBuffer = mModel->mVisualModel->mLines.Begin();
- mModel->mVisualModel->mLines.Erase(linesBuffer + startRemoveIndex,
- linesBuffer + endRemoveIndex);
- }
-
- if(NO_OPERATION != (COLOR & operations))
- {
- if(0u != mModel->mVisualModel->mColorIndices.Count())
- {
- ColorIndex* colorIndexBuffer = mModel->mVisualModel->mColorIndices.Begin();
- mModel->mVisualModel->mColorIndices.Erase(colorIndexBuffer + mTextUpdateInfo.mStartGlyphIndex,
- colorIndexBuffer + endGlyphIndexPlusOne);
- }
-
- if(0u != mModel->mVisualModel->mBackgroundColorIndices.Count())
- {
- ColorIndex* backgroundColorIndexBuffer = mModel->mVisualModel->mBackgroundColorIndices.Begin();
- mModel->mVisualModel->mBackgroundColorIndices.Erase(backgroundColorIndexBuffer + mTextUpdateInfo.mStartGlyphIndex,
- backgroundColorIndexBuffer + endGlyphIndexPlusOne);
- }
- }
-}
-
void Controller::Impl::ClearModelData(CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations)
{
- if(mTextUpdateInfo.mClearAll ||
- ((0u == startIndex) &&
- (mTextUpdateInfo.mPreviousNumberOfCharacters == endIndex + 1u)))
- {
- ClearFullModelData(operations);
- }
- else
- {
- // Clear the model data related with characters.
- ClearCharacterModelData(startIndex, endIndex, operations);
-
- // Clear the model data related with glyphs.
- ClearGlyphModelData(startIndex, endIndex, operations);
- }
-
- // The estimated number of lines. Used to avoid reallocations when layouting.
- mTextUpdateInfo.mEstimatedNumberOfLines = std::max(mModel->mVisualModel->mLines.Count(), mModel->mLogicalModel->mParagraphInfo.Count());
-
- mModel->mVisualModel->ClearCaches();
+ ControllerImplDataClearer::ClearModelData(*this, startIndex, endIndex, operations);
}
bool Controller::Impl::UpdateModel(OperationsMask operationsRequired)
return (fontMetrics.ascender - fontMetrics.descender);
}
+bool Controller::Impl::SetDefaultLineSpacing(float lineSpacing)
+{
+ if(std::fabs(lineSpacing - mLayoutEngine.GetDefaultLineSpacing()) > Math::MACHINE_EPSILON_1000)
+ {
+ mLayoutEngine.SetDefaultLineSpacing(lineSpacing);
+ mRecalculateNaturalSize = true;
+
+ RelayoutForNewLineSize();
+ return true;
+ }
+ return false;
+}
+
+bool Controller::Impl::SetDefaultLineSize(float lineSize)
+{
+ if(std::fabs(lineSize - mLayoutEngine.GetDefaultLineSize()) > Math::MACHINE_EPSILON_1000)
+ {
+ mLayoutEngine.SetDefaultLineSize(lineSize);
+ mRecalculateNaturalSize = true;
+
+ RelayoutForNewLineSize();
+ return true;
+ }
+ return false;
+}
+
void Controller::Impl::SetTextSelectionRange(const uint32_t* pStart, const uint32_t* pEnd)
{
if(nullptr == mEventData)
}
}
+void Controller::Impl::UpdateAfterFontChange(const std::string& newDefaultFont)
+{
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::UpdateAfterFontChange\n");
+
+ if(!mFontDefaults->familyDefined) // If user defined font then should not update when system font changes
+ {
+ DALI_LOG_INFO(gLogFilter, Debug::Concise, "Controller::UpdateAfterFontChange newDefaultFont(%s)\n", newDefaultFont.c_str());
+ mFontDefaults->mFontDescription.family = newDefaultFont;
+
+ ClearFontData();
+
+ RequestRelayout();
+ }
+}
+
void Controller::Impl::RetrieveSelection(std::string& selectedText, bool deleteAfterRetrieval)
{
if(mEventData->mLeftSelectionPosition == mEventData->mRightSelectionPosition)
void Controller::Impl::ChangeState(EventData::State newState)
{
- if(nullptr == mEventData)
- {
- // Nothing to do if there is no text input.
- return;
- }
-
- DALI_LOG_INFO(gLogFilter, Debug::General, "ChangeState state:%d newstate:%d\n", mEventData->mState, newState);
-
- if(mEventData->mState != newState)
- {
- mEventData->mPreviousState = mEventData->mState;
- mEventData->mState = newState;
-
- switch(mEventData->mState)
- {
- case EventData::INACTIVE:
- {
- mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
- mEventData->mDecorator->StopCursorBlink();
- mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, false);
- mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
- mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
- mEventData->mDecorator->SetHighlightActive(false);
- mEventData->mDecorator->SetPopupActive(false);
- mEventData->mDecoratorUpdated = true;
- break;
- }
- case EventData::INTERRUPTED:
- {
- mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, false);
- mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
- mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
- mEventData->mDecorator->SetHighlightActive(false);
- mEventData->mDecorator->SetPopupActive(false);
- mEventData->mDecoratorUpdated = true;
- break;
- }
- case EventData::SELECTING:
- {
- mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
- mEventData->mDecorator->StopCursorBlink();
- mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, false);
- if(mEventData->mGrabHandleEnabled)
- {
- mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, true);
- mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, true);
- }
- mEventData->mDecorator->SetHighlightActive(true);
- if(mEventData->mGrabHandlePopupEnabled)
- {
- SetPopupButtons();
- mEventData->mDecorator->SetPopupActive(true);
- }
- mEventData->mDecoratorUpdated = true;
- break;
- }
- case EventData::EDITING:
- {
- mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
- if(mEventData->mCursorBlinkEnabled)
- {
- mEventData->mDecorator->StartCursorBlink();
- }
- // Grab handle is not shown until a tap is received whilst EDITING
- mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, false);
- mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
- mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
- mEventData->mDecorator->SetHighlightActive(false);
- if(mEventData->mGrabHandlePopupEnabled)
- {
- mEventData->mDecorator->SetPopupActive(false);
- }
- mEventData->mDecoratorUpdated = true;
- break;
- }
- case EventData::EDITING_WITH_POPUP:
- {
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_POPUP \n", newState);
-
- mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
- if(mEventData->mCursorBlinkEnabled)
- {
- mEventData->mDecorator->StartCursorBlink();
- }
- if(mEventData->mSelectionEnabled)
- {
- mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
- mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
- mEventData->mDecorator->SetHighlightActive(false);
- }
- else if(mEventData->mGrabHandleEnabled)
- {
- mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, true);
- }
- if(mEventData->mGrabHandlePopupEnabled)
- {
- SetPopupButtons();
- mEventData->mDecorator->SetPopupActive(true);
- }
- mEventData->mDecoratorUpdated = true;
- break;
- }
- case EventData::EDITING_WITH_GRAB_HANDLE:
- {
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_GRAB_HANDLE \n", newState);
-
- mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
- if(mEventData->mCursorBlinkEnabled)
- {
- mEventData->mDecorator->StartCursorBlink();
- }
- // Grab handle is not shown until a tap is received whilst EDITING
- if(mEventData->mGrabHandleEnabled)
- {
- mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, true);
- }
- mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
- mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
- mEventData->mDecorator->SetHighlightActive(false);
- if(mEventData->mGrabHandlePopupEnabled)
- {
- mEventData->mDecorator->SetPopupActive(false);
- }
- mEventData->mDecoratorUpdated = true;
- break;
- }
- case EventData::SELECTION_HANDLE_PANNING:
- {
- mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
- mEventData->mDecorator->StopCursorBlink();
- mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, false);
- if(mEventData->mGrabHandleEnabled)
- {
- mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, true);
- mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, true);
- }
- mEventData->mDecorator->SetHighlightActive(true);
- if(mEventData->mGrabHandlePopupEnabled)
- {
- mEventData->mDecorator->SetPopupActive(false);
- }
- mEventData->mDecoratorUpdated = true;
- break;
- }
- case EventData::GRAB_HANDLE_PANNING:
- {
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "GRAB_HANDLE_PANNING \n", newState);
-
- mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
- if(mEventData->mCursorBlinkEnabled)
- {
- mEventData->mDecorator->StartCursorBlink();
- }
- if(mEventData->mGrabHandleEnabled)
- {
- mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, true);
- }
- mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
- mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
- mEventData->mDecorator->SetHighlightActive(false);
- if(mEventData->mGrabHandlePopupEnabled)
- {
- mEventData->mDecorator->SetPopupActive(false);
- }
- mEventData->mDecoratorUpdated = true;
- break;
- }
- case EventData::EDITING_WITH_PASTE_POPUP:
- {
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_PASTE_POPUP \n", newState);
-
- mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
- if(mEventData->mCursorBlinkEnabled)
- {
- mEventData->mDecorator->StartCursorBlink();
- }
-
- if(mEventData->mGrabHandleEnabled)
- {
- mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, true);
- }
- mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
- mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
- mEventData->mDecorator->SetHighlightActive(false);
-
- if(mEventData->mGrabHandlePopupEnabled)
- {
- SetPopupButtons();
- mEventData->mDecorator->SetPopupActive(true);
- }
- mEventData->mDecoratorUpdated = true;
- break;
- }
- case EventData::TEXT_PANNING:
- {
- mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
- mEventData->mDecorator->StopCursorBlink();
- mEventData->mDecorator->SetHandleActive(GRAB_HANDLE, false);
- if(mEventData->mDecorator->IsHandleActive(LEFT_SELECTION_HANDLE) ||
- mEventData->mDecorator->IsHandleActive(RIGHT_SELECTION_HANDLE))
- {
- mEventData->mDecorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
- mEventData->mDecorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
- mEventData->mDecorator->SetHighlightActive(true);
- }
-
- if(mEventData->mGrabHandlePopupEnabled)
- {
- mEventData->mDecorator->SetPopupActive(false);
- }
-
- mEventData->mDecoratorUpdated = true;
- break;
- }
- }
- }
+ ChangeTextControllerState(*this, newState);
}
void Controller::Impl::GetCursorPosition(CharacterIndex logical,
}
}
+void Controller::Impl::SetAutoScrollEnabled(bool enable)
+{
+ if(mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX)
+ {
+ mOperationsPending = static_cast<OperationsMask>(mOperationsPending |
+ LAYOUT |
+ ALIGN |
+ UPDATE_LAYOUT_SIZE |
+ REORDER);
+
+ if(enable)
+ {
+ DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled for SINGLE_LINE_BOX\n");
+ mOperationsPending = static_cast<OperationsMask>(mOperationsPending | UPDATE_DIRECTION);
+ }
+ else
+ {
+ DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled Disabling autoscroll\n");
+ }
+
+ mIsAutoScrollEnabled = enable;
+ RequestRelayout();
+ }
+ else
+ {
+ DALI_LOG_WARNING("Attempted AutoScrolling on a non SINGLE_LINE_BOX, request ignored\n");
+ mIsAutoScrollEnabled = false;
+ }
+}
+
+void Controller::Impl::SetEnableCursorBlink(bool enable)
+{
+ DALI_ASSERT_DEBUG(NULL != mEventData && "TextInput disabled");
+
+ if(mEventData)
+ {
+ mEventData->mCursorBlinkEnabled = enable;
+
+ if(!enable && mEventData->mDecorator)
+ {
+ mEventData->mDecorator->StopCursorBlink();
+ }
+ }
+}
+
+void Controller::Impl::SetMultiLineEnabled(bool enable)
+{
+ const Layout::Engine::Type layout = enable ? Layout::Engine::MULTI_LINE_BOX : Layout::Engine::SINGLE_LINE_BOX;
+
+ if(layout != mLayoutEngine.GetLayout())
+ {
+ // Set the layout type.
+ mLayoutEngine.SetLayout(layout);
+
+ // Set the flags to redo the layout operations
+ const OperationsMask layoutOperations = static_cast<OperationsMask>(LAYOUT |
+ UPDATE_LAYOUT_SIZE |
+ ALIGN |
+ REORDER);
+
+ mTextUpdateInfo.mFullRelayoutNeeded = true;
+ mOperationsPending = static_cast<OperationsMask>(mOperationsPending | layoutOperations);
+
+ // Need to recalculate natural size
+ mRecalculateNaturalSize = true;
+
+ RequestRelayout();
+ }
+}
+
+void Controller::Impl::SetHorizontalAlignment(Text::HorizontalAlignment::Type alignment)
+{
+ if(alignment != mModel->mHorizontalAlignment)
+ {
+ // Set the alignment.
+ mModel->mHorizontalAlignment = alignment;
+
+ // Set the flag to redo the alignment operation.
+ mOperationsPending = static_cast<OperationsMask>(mOperationsPending | ALIGN);
+
+ if(mEventData)
+ {
+ mEventData->mUpdateAlignment = true;
+
+ // Update the cursor if it's in editing mode
+ if(EventData::IsEditingState(mEventData->mState))
+ {
+ ChangeState(EventData::EDITING);
+ mEventData->mUpdateCursorPosition = true;
+ }
+ }
+
+ RequestRelayout();
+ }
+}
+
+void Controller::Impl::SetVerticalAlignment(VerticalAlignment::Type alignment)
+{
+ if(alignment != mModel->mVerticalAlignment)
+ {
+ // Set the alignment.
+ mModel->mVerticalAlignment = alignment;
+ mOperationsPending = static_cast<OperationsMask>(mOperationsPending | ALIGN);
+ RequestRelayout();
+ }
+}
+
+void Controller::Impl::SetLineWrapMode(Text::LineWrap::Mode lineWrapMode)
+{
+ if(lineWrapMode != mModel->mLineWrapMode)
+ {
+ // Update Text layout for applying wrap mode
+ mOperationsPending = static_cast<OperationsMask>(mOperationsPending |
+ ALIGN |
+ LAYOUT |
+ UPDATE_LAYOUT_SIZE |
+ REORDER);
+
+ if((mModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) || (lineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) ||
+ (mModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::MIXED) || (lineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::MIXED)) // hyphen is treated as line break
+ {
+ mOperationsPending = static_cast<OperationsMask>(mOperationsPending | GET_LINE_BREAKS);
+ }
+
+ // Set the text wrap mode.
+ mModel->mLineWrapMode = lineWrapMode;
+
+ mTextUpdateInfo.mCharacterIndex = 0u;
+ mTextUpdateInfo.mNumberOfCharactersToRemove = mTextUpdateInfo.mPreviousNumberOfCharacters;
+ mTextUpdateInfo.mNumberOfCharactersToAdd = mModel->mLogicalModel->mText.Count();
+
+ // Request relayout
+ RequestRelayout();
+ }
+}
+
+void Controller::Impl::SetDefaultColor(const Vector4& color)
+{
+ mTextColor = color;
+
+ if(!IsShowingPlaceholderText())
+ {
+ mModel->mVisualModel->SetTextColor(color);
+ mModel->mLogicalModel->mColorRuns.Clear();
+ mOperationsPending = static_cast<OperationsMask>(mOperationsPending | COLOR);
+ RequestRelayout();
+ }
+}
+
+void Controller::Impl::ClearFontData()
+{
+ if(mFontDefaults)
+ {
+ mFontDefaults->mFontId = 0u; // Remove old font ID
+ }
+
+ // Set flags to update the model.
+ mTextUpdateInfo.mCharacterIndex = 0u;
+ mTextUpdateInfo.mNumberOfCharactersToRemove = mTextUpdateInfo.mPreviousNumberOfCharacters;
+ mTextUpdateInfo.mNumberOfCharactersToAdd = mModel->mLogicalModel->mText.Count();
+
+ mTextUpdateInfo.mClearAll = true;
+ mTextUpdateInfo.mFullRelayoutNeeded = true;
+ mRecalculateNaturalSize = true;
+
+ mOperationsPending = static_cast<OperationsMask>(mOperationsPending |
+ VALIDATE_FONTS |
+ SHAPE_TEXT |
+ BIDI_INFO |
+ GET_GLYPH_METRICS |
+ LAYOUT |
+ UPDATE_LAYOUT_SIZE |
+ REORDER |
+ ALIGN);
+}
+
+void Controller::Impl::ClearStyleData()
+{
+ mModel->mLogicalModel->mColorRuns.Clear();
+ mModel->mLogicalModel->ClearFontDescriptionRuns();
+}
+
+
+void Controller::Impl::ResetScrollPosition()
+{
+ if(mEventData)
+ {
+ // Reset the scroll position.
+ mModel->mScrollPosition = Vector2::ZERO;
+ mEventData->mScrollAfterUpdatePosition = true;
+ }
+}
+
} // namespace Dali::Toolkit::Text
}
/**
+ * @copydoc Controller::GetLayoutDirection()
+ */
+ Dali::LayoutDirection::Type GetLayoutDirection(Dali::Actor& actor) const;
+
+ /**
* @brief Calculates the start character index of the first paragraph to be updated and
* the end character index of the last paragraph to be updated.
*
void CalculateTextUpdateIndices(Length& numberOfCharacters);
/**
- * @brief Helper to clear completely the parts of the model specified by the given @p operations.
- *
- * @note It never clears the text stored in utf32.
- */
- void ClearFullModelData(OperationsMask operations);
-
- /**
- * @brief Helper to clear completely the parts of the model related with the characters specified by the given @p operations.
- *
- * @note It never clears the text stored in utf32.
- *
- * @param[in] startIndex Index to the first character to be cleared.
- * @param[in] endIndex Index to the last character to be cleared.
- * @param[in] operations The operations required.
- */
- void ClearCharacterModelData(CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations);
-
- /**
- * @brief Helper to clear completely the parts of the model related with the glyphs specified by the given @p operations.
- *
- * @note It never clears the text stored in utf32.
- * @note Character indices are transformed to glyph indices.
- *
- * @param[in] startIndex Index to the first character to be cleared.
- * @param[in] endIndex Index to the last character to be cleared.
- * @param[in] operations The operations required.
- */
- void ClearGlyphModelData(CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations);
-
- /**
* @brief Helper to clear the parts of the model specified by the given @p operations and from @p startIndex to @p endIndex.
*
* @note It never clears the text stored in utf32.
float GetDefaultFontLineHeight();
/**
+ * @copydoc Controller::SetDefaultLineSpacing
+ */
+ bool SetDefaultLineSpacing(float lineSpacing);
+
+ /**
+ * @copydoc Controller::SetDefaultLineSize
+ */
+ bool SetDefaultLineSize(float lineSize);
+
+ /**
* @copydoc Text::Controller::GetPrimaryCursorPosition()
*/
CharacterIndex GetPrimaryCursorPosition() const;
void SetEditable(bool editable);
/**
+ * @copydoc Controller::UpdateAfterFontChange
+ */
+ void UpdateAfterFontChange(const std::string& newDefaultFont);
+
+ /**
* @brief Retrieves the selected text. It removes the text if the @p deleteAfterRetrieval parameter is @e true.
*
* @param[out] selectedText The selected text encoded in utf8.
*/
float GetVerticalScrollPosition();
+ /**
+ * @copydoc Controller::SetAutoScrollEnabled()
+ */
+ void SetAutoScrollEnabled(bool enable);
+
+ /**
+ * @copydoc Controller::SetEnableCursorBlink()
+ */
+ void SetEnableCursorBlink(bool enable);
+
+ /**
+ * @copydoc Controller::SetMultiLineEnabled()
+ */
+ void SetMultiLineEnabled(bool enable);
+
+ /**
+ * @copydoc Controller::SetHorizontalAlignment()
+ */
+ void SetHorizontalAlignment(HorizontalAlignment::Type alignment);
+
+ /**
+ * @copydoc Controller::SetVerticalAlignment()
+ */
+ void SetVerticalAlignment(VerticalAlignment::Type alignment);
+
+ /**
+ * @copydoc Controller::SetLineWrapMode()
+ */
+ void SetLineWrapMode(Text::LineWrap::Mode textWarpMode);
+
+ /**
+ * @copydoc Controller::SetDefaultColor()
+ */
+ void SetDefaultColor(const Vector4& color);
+
+ /**
+ * @brief Helper to clear font-specific data (only).
+ */
+ void ClearFontData();
+
+ /**
+ * @brief Helper to clear text's style data.
+ */
+ void ClearStyleData();
+
+ /**
+ * @brief Used to reset the scroll position after setting a new text.
+ */
+ void ResetScrollPosition();
public:
/**
TextUpdateInfo& textUpdateInfo = impl.mTextUpdateInfo;
impl.mFontDefaults->mFitPointSize = pointSize;
impl.mFontDefaults->sizeDefined = true;
- controller.ClearFontData();
+ impl.ClearFontData();
// Operations that can be done only once until the text changes.
const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
model->mElideEnabled = actualellipsis;
impl.mFontDefaults->mFitPointSize = pointSizeArray[bestSizeIndex];
impl.mFontDefaults->sizeDefined = true;
- controller.ClearFontData();
+ impl.ClearFontData();
}
}
// Reset the scroll position in inactive state
if(elideTextEnabled && (impl.mEventData->mState == EventData::INACTIVE))
{
- controller.ResetScrollPosition();
+ impl.ResetScrollPosition();
}
}
ResetText(controller);
// Remove the style.
- controller.ClearStyleData();
+ impl.ClearStyleData();
CharacterIndex lastCursorIndex = 0u;
controller.ResetCursorPosition(lastCursorIndex);
// Scrolls the text to make the cursor visible.
- controller.ResetScrollPosition();
+ impl.ResetScrollPosition();
impl.RequestRelayout();
mImpl->mMetrics->SetGlyphType(glyphType);
// Clear the font-specific data
- ClearFontData();
+ mImpl->ClearFontData();
mImpl->RequestRelayout();
}
void Controller::SetAutoScrollEnabled(bool enable)
{
DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled[%s] SingleBox[%s]-> [%p]\n", (enable) ? "true" : "false", (mImpl->mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX) ? "true" : "false", this);
-
- if(mImpl->mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX)
- {
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
- LAYOUT |
- ALIGN |
- UPDATE_LAYOUT_SIZE |
- REORDER);
-
- if(enable)
- {
- DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled for SINGLE_LINE_BOX\n");
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | UPDATE_DIRECTION);
- }
- else
- {
- DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled Disabling autoscroll\n");
- }
-
- mImpl->mIsAutoScrollEnabled = enable;
- mImpl->RequestRelayout();
- }
- else
- {
- DALI_LOG_WARNING("Attempted AutoScrolling on a non SINGLE_LINE_BOX, request ignored\n");
- mImpl->mIsAutoScrollEnabled = false;
- }
+ mImpl->SetAutoScrollEnabled(enable);
}
bool Controller::IsAutoScrollEnabled() const
{
DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::IsAutoScrollEnabled[%s]\n", mImpl->mIsAutoScrollEnabled ? "true" : "false");
-
return mImpl->mIsAutoScrollEnabled;
}
void Controller::SetEnableCursorBlink(bool enable)
{
- DALI_ASSERT_DEBUG(NULL != mImpl->mEventData && "TextInput disabled");
-
- if(mImpl->mEventData)
- {
- mImpl->mEventData->mCursorBlinkEnabled = enable;
-
- if(!enable && mImpl->mEventData->mDecorator)
- {
- mImpl->mEventData->mDecorator->StopCursorBlink();
- }
- }
+ mImpl->SetEnableCursorBlink(enable);
}
bool Controller::GetEnableCursorBlink() const
void Controller::SetMultiLineEnabled(bool enable)
{
- const Layout::Engine::Type layout = enable ? Layout::Engine::MULTI_LINE_BOX : Layout::Engine::SINGLE_LINE_BOX;
-
- if(layout != mImpl->mLayoutEngine.GetLayout())
- {
- // Set the layout type.
- mImpl->mLayoutEngine.SetLayout(layout);
-
- // Set the flags to redo the layout operations
- const OperationsMask layoutOperations = static_cast<OperationsMask>(LAYOUT |
- UPDATE_LAYOUT_SIZE |
- ALIGN |
- REORDER);
-
- mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | layoutOperations);
-
- // Need to recalculate natural size
- mImpl->mRecalculateNaturalSize = true;
-
- mImpl->RequestRelayout();
- }
+ mImpl->SetMultiLineEnabled(enable);
}
bool Controller::IsMultiLineEnabled() const
void Controller::SetHorizontalAlignment(Text::HorizontalAlignment::Type alignment)
{
- if(alignment != mImpl->mModel->mHorizontalAlignment)
- {
- // Set the alignment.
- mImpl->mModel->mHorizontalAlignment = alignment;
-
- // Set the flag to redo the alignment operation.
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | ALIGN);
-
- if(mImpl->mEventData)
- {
- mImpl->mEventData->mUpdateAlignment = true;
-
- // Update the cursor if it's in editing mode
- if(EventData::IsEditingState(mImpl->mEventData->mState))
- {
- mImpl->ChangeState(EventData::EDITING);
- mImpl->mEventData->mUpdateCursorPosition = true;
- }
- }
-
- mImpl->RequestRelayout();
- }
+ mImpl->SetHorizontalAlignment(alignment);
}
Text::HorizontalAlignment::Type Controller::GetHorizontalAlignment() const
void Controller::SetVerticalAlignment(VerticalAlignment::Type alignment)
{
- if(alignment != mImpl->mModel->mVerticalAlignment)
- {
- // Set the alignment.
- mImpl->mModel->mVerticalAlignment = alignment;
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | ALIGN);
- mImpl->RequestRelayout();
- }
+ mImpl->SetVerticalAlignment(alignment);
}
VerticalAlignment::Type Controller::GetVerticalAlignment() const
void Controller::SetLineWrapMode(Text::LineWrap::Mode lineWrapMode)
{
- if(lineWrapMode != mImpl->mModel->mLineWrapMode)
- {
- // Update Text layout for applying wrap mode
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
- ALIGN |
- LAYOUT |
- UPDATE_LAYOUT_SIZE |
- REORDER);
-
- if((mImpl->mModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) || (lineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) ||
- (mImpl->mModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::MIXED) || (lineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::MIXED)) // hyphen is treated as line break
- {
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | GET_LINE_BREAKS);
- }
-
- // Set the text wrap mode.
- mImpl->mModel->mLineWrapMode = lineWrapMode;
-
- mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
- mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
- mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mModel->mLogicalModel->mText.Count();
-
- // Request relayout
- mImpl->RequestRelayout();
- }
+ mImpl->SetLineWrapMode(lineWrapMode);
}
Text::LineWrap::Mode Controller::GetLineWrapMode() const
void Controller::UpdateAfterFontChange(const std::string& newDefaultFont)
{
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::UpdateAfterFontChange\n");
-
- if(!mImpl->mFontDefaults->familyDefined) // If user defined font then should not update when system font changes
- {
- DALI_LOG_INFO(gLogFilter, Debug::Concise, "Controller::UpdateAfterFontChange newDefaultFont(%s)\n", newDefaultFont.c_str());
- mImpl->mFontDefaults->mFontDescription.family = newDefaultFont;
-
- ClearFontData();
-
- mImpl->RequestRelayout();
- }
+ mImpl->UpdateAfterFontChange(newDefaultFont);
}
void Controller::RetrieveSelection(std::string& selectedText) const
UpdateCursorPosition(mImpl->mEventData);
// Clear the font-specific data
- ClearFontData();
+ mImpl->ClearFontData();
mImpl->RequestRelayout();
}
UpdateCursorPosition(mImpl->mEventData);
// Clear the font-specific data
- ClearFontData();
+ mImpl->ClearFontData();
mImpl->RequestRelayout();
}
UpdateCursorPosition(mImpl->mEventData);
// Clear the font-specific data
- ClearFontData();
+ mImpl->ClearFontData();
mImpl->RequestRelayout();
}
UpdateCursorPosition(mImpl->mEventData);
// Clear the font-specific data
- ClearFontData();
+ mImpl->ClearFontData();
mImpl->RequestRelayout();
}
UpdateCursorPosition(mImpl->mEventData);
// Clear the font-specific data
- ClearFontData();
+ mImpl->ClearFontData();
mImpl->RequestRelayout();
}
UpdateCursorPosition(mImpl->mEventData);
// Clear the font-specific data
- ClearFontData();
+ mImpl->ClearFontData();
mImpl->RequestRelayout();
}
void Controller::SetDefaultColor(const Vector4& color)
{
- mImpl->mTextColor = color;
-
- if(!mImpl->IsShowingPlaceholderText())
- {
- mImpl->mModel->mVisualModel->SetTextColor(color);
- mImpl->mModel->mLogicalModel->mColorRuns.Clear();
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | COLOR);
- mImpl->RequestRelayout();
- }
+ mImpl->SetDefaultColor(color);
}
const Vector4& Controller::GetDefaultColor() const
bool Controller::SetDefaultLineSpacing(float lineSpacing)
{
- if(std::fabs(lineSpacing - mImpl->mLayoutEngine.GetDefaultLineSpacing()) > Math::MACHINE_EPSILON_1000)
- {
- mImpl->mLayoutEngine.SetDefaultLineSpacing(lineSpacing);
- mImpl->mRecalculateNaturalSize = true;
-
- mImpl->RelayoutForNewLineSize();
- return true;
- }
- return false;
+ return mImpl->SetDefaultLineSpacing(lineSpacing);
}
float Controller::GetDefaultLineSpacing() const
bool Controller::SetDefaultLineSize(float lineSize)
{
- if(std::fabs(lineSize - mImpl->mLayoutEngine.GetDefaultLineSize()) > Math::MACHINE_EPSILON_1000)
- {
- mImpl->mLayoutEngine.SetDefaultLineSize(lineSize);
- mImpl->mRecalculateNaturalSize = true;
-
- mImpl->RelayoutForNewLineSize();
- return true;
- }
- return false;
+ return mImpl->SetDefaultLineSize(lineSize);
}
float Controller::GetDefaultLineSize() const
PlaceholderHandler::ShowPlaceholderText(*this);
}
-void Controller::ClearFontData()
-{
- if(mImpl->mFontDefaults)
- {
- mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
- }
-
- // Set flags to update the model.
- mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
- mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
- mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mModel->mLogicalModel->mText.Count();
-
- mImpl->mTextUpdateInfo.mClearAll = true;
- mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
- mImpl->mRecalculateNaturalSize = true;
-
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
- VALIDATE_FONTS |
- SHAPE_TEXT |
- BIDI_INFO |
- GET_GLYPH_METRICS |
- LAYOUT |
- UPDATE_LAYOUT_SIZE |
- REORDER |
- ALIGN);
-}
-
-void Controller::ClearStyleData()
-{
- mImpl->mModel->mLogicalModel->mColorRuns.Clear();
- mImpl->mModel->mLogicalModel->ClearFontDescriptionRuns();
-}
-
void Controller::ResetCursorPosition(CharacterIndex cursorIndex)
{
// Reset the cursor position
CharacterIndex Controller::GetCursorPosition()
{
- if(!mImpl->mEventData)
- return 0;
-
- return mImpl->mEventData->mPrimaryCursorPosition;
-}
-
-void Controller::ResetScrollPosition()
-{
- if(mImpl->mEventData)
- {
- // Reset the scroll position.
- mImpl->mModel->mScrollPosition = Vector2::ZERO;
- mImpl->mEventData->mScrollAfterUpdatePosition = true;
- }
+ return mImpl->mEventData ? mImpl->mEventData->mPrimaryCursorPosition : 0;
}
void Controller::SetControlInterface(ControlInterface* controlInterface)
*/
void ShowPlaceholderText();
- /**
- * @brief Helper to clear font-specific data (only).
- */
- void ClearFontData();
-
- /**
- * @brief Helper to clear text's style data.
- */
- void ClearStyleData();
-
- /**
- * @brief Used to reset the scroll position after setting a new text.
- */
- void ResetScrollPosition();
-
private: // Private contructors & copy operator.
/**
* @brief Private constructor.