From: Adeel Kazmi Date: Fri, 19 Nov 2021 12:20:32 +0000 (+0000) Subject: (TextController/ScrollView) Reduced LOC X-Git-Tag: dali_2.1.0~10 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=3ce558ca09f928cb18cacfa80f52eb0c591181b9;hp=e0c063be9e7ecde0e5665079289489d456828abf (TextController/ScrollView) Reduced LOC - TextController - Moved some methods to the Impl class - TextControllerImpl - Moved a lot of functionality outside of the class - ScrollView - Added a class which handles the properties Change-Id: I69127a9bc3dbd3e892f1fe0019cac9ad41fc2f3e --- diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-property-handler.cpp b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-property-handler.cpp new file mode 100644 index 0000000..9c1272c --- /dev/null +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-property-handler.cpp @@ -0,0 +1,286 @@ +/* + * 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 + +// INTERNAL INCLUDES +#include +#include + +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()); + break; + } + case Toolkit::ScrollView::Property::PANNING_ENABLED: + { + scrollViewImpl.SetScrollSensitive(value.Get()); + break; + } + case Toolkit::ScrollView::Property::AXIS_AUTO_LOCK_ENABLED: + { + scrollViewImpl.SetAxisAutoLock(value.Get()); + break; + } + case Toolkit::ScrollView::Property::WHEEL_SCROLL_DISTANCE_STEP: + { + scrollViewImpl.SetWheelScrollDistanceStep(value.Get()); + 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 diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-property-handler.h b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-property-handler.h new file mode 100644 index 0000000..1923cfc --- /dev/null +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-property-handler.h @@ -0,0 +1,69 @@ +#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 +#include + +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 diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp index 86cfc56..712cb17 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -673,7 +674,7 @@ void ScrollView::OnInitialize() 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 @@ -794,7 +795,7 @@ void ScrollView::SetRulerX(RulerPtr ruler) { mRulerX = ruler; - UpdatePropertyDomain(); + ScrollViewPropertyHandler::UpdatePropertyDomain(*this); mConstraints.UpdateMainInternalConstraint(*this); } @@ -802,107 +803,10 @@ void ScrollView::SetRulerY(RulerPtr ruler) { 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(); @@ -1482,7 +1386,7 @@ bool ScrollView::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* 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) @@ -1497,7 +1401,7 @@ void ScrollView::OnSizeSet(const Vector3& size) mMaxOvershoot = mUserMaxOvershoot; } } - UpdatePropertyDomain(); + ScrollViewPropertyHandler::UpdatePropertyDomain(*this); mConstraints.UpdateMainInternalConstraint(*this); if(IsOvershootEnabled()) { @@ -2180,45 +2084,6 @@ void ScrollView::FinishTransform() } } -Vector2 ScrollView::GetOvershoot(Vector2& position) const -{ - Vector3 size = Self().GetCurrentProperty(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 @@ -2263,164 +2128,12 @@ void ScrollView::WrapPosition(Vector2& position) const 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()); - break; - } - case Toolkit::ScrollView::Property::PANNING_ENABLED: - { - scrollViewImpl.SetScrollSensitive(value.Get()); - break; - } - case Toolkit::ScrollView::Property::AXIS_AUTO_LOCK_ENABLED: - { - scrollViewImpl.SetAxisAutoLock(value.Get()); - break; - } - case Toolkit::ScrollView::Property::WHEEL_SCROLL_DISTANCE_STEP: - { - scrollViewImpl.SetWheelScrollDistanceStep(value.Get()); - 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) diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h index 4d871a7..4061727 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h @@ -47,6 +47,8 @@ typedef IntrusivePtr ScrollInternalConstraintsPtr; class ScrollOvershootIndicator; typedef IntrusivePtr ScrollOvershootIndicatorPtr; +class ScrollViewPropertyHandler; + /** * @copydoc Toolkit::ScrollView */ @@ -774,13 +776,6 @@ private: 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(); @@ -821,20 +816,6 @@ private: 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 @@ -924,13 +905,6 @@ private: */ 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&); @@ -1020,6 +994,7 @@ private: bool mTransientScrollBar : 1; ///< True if scroll-bar should be automatically show/hidden during/after panning friend ScrollViewConstraints; + friend ScrollViewPropertyHandler; }; /** diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index 591915d..855df54 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -93,6 +93,7 @@ SET( toolkit_src_files ${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 @@ -158,6 +159,7 @@ SET( toolkit_src_files ${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 diff --git a/dali-toolkit/internal/text/text-controller-impl-data-clearer.cpp b/dali-toolkit/internal/text/text-controller-impl-data-clearer.cpp new file mode 100644 index 0000000..87099da --- /dev/null +++ b/dali-toolkit/internal/text/text-controller-impl-data-clearer.cpp @@ -0,0 +1,320 @@ +/* + * 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 + +// INTERNAL INCLUDES +#include +#include + +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::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::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::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::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 diff --git a/dali-toolkit/internal/text/text-controller-impl-data-clearer.h b/dali-toolkit/internal/text/text-controller-impl-data-clearer.h new file mode 100644 index 0000000..87d6e24 --- /dev/null +++ b/dali-toolkit/internal/text/text-controller-impl-data-clearer.h @@ -0,0 +1,81 @@ +#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 + +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 diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index 4334f0e..8a1dd76 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -19,8 +19,10 @@ #include // EXTERNAL INCLUDES +#include #include #include +#include // INTERNAL INCLUDES #include @@ -28,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -129,6 +132,243 @@ void SetDefaultInputStyle(InputStyle& inputStyle, const FontDefaults* const font } } } + +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) @@ -268,6 +508,19 @@ void Controller::Impl::GetText(CharacterIndex index, std::string& text) const } } +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(DevelWindow::Get(actor).GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get()); + } + else + { + return static_cast(actor.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get()); + } +} + void Controller::Impl::CalculateTextUpdateIndices(Length& numberOfCharacters) { mTextUpdateInfo.mParagraphCharacterIndex = 0u; @@ -353,286 +606,9 @@ void Controller::Impl::CalculateTextUpdateIndices(Length& numberOfCharacters) 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::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::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::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::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) @@ -664,6 +640,32 @@ float Controller::Impl::GetDefaultFontLineHeight() 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) @@ -791,6 +793,21 @@ void Controller::Impl::SetEditable(bool editable) } } +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) @@ -1008,222 +1025,7 @@ void Controller::Impl::SetPopupButtons() 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, @@ -1843,4 +1645,197 @@ void Controller::Impl::CopyUnderlinedFromLogicalToVisualModels(bool shouldClearP } } +void Controller::Impl::SetAutoScrollEnabled(bool enable) +{ + if(mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX) + { + mOperationsPending = static_cast(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(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(LAYOUT | + UPDATE_LAYOUT_SIZE | + ALIGN | + REORDER); + + mTextUpdateInfo.mFullRelayoutNeeded = true; + mOperationsPending = static_cast(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(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(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(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(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(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(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 diff --git a/dali-toolkit/internal/text/text-controller-impl.h b/dali-toolkit/internal/text/text-controller-impl.h index 219ca72..23d5d86 100644 --- a/dali-toolkit/internal/text/text-controller-impl.h +++ b/dali-toolkit/internal/text/text-controller-impl.h @@ -545,6 +545,11 @@ struct Controller::Impl } /** + * @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. * @@ -553,36 +558,6 @@ struct Controller::Impl 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. @@ -620,6 +595,16 @@ struct Controller::Impl float GetDefaultFontLineHeight(); /** + * @copydoc Controller::SetDefaultLineSpacing + */ + bool SetDefaultLineSpacing(float lineSpacing); + + /** + * @copydoc Controller::SetDefaultLineSize + */ + bool SetDefaultLineSize(float lineSize); + + /** * @copydoc Text::Controller::GetPrimaryCursorPosition() */ CharacterIndex GetPrimaryCursorPosition() const; @@ -650,6 +635,11 @@ struct Controller::Impl 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. @@ -801,6 +791,55 @@ struct Controller::Impl */ 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: /** diff --git a/dali-toolkit/internal/text/text-controller-relayouter.cpp b/dali-toolkit/internal/text/text-controller-relayouter.cpp index 4c71934..d04483a 100644 --- a/dali-toolkit/internal/text/text-controller-relayouter.cpp +++ b/dali-toolkit/internal/text/text-controller-relayouter.cpp @@ -170,7 +170,7 @@ bool Controller::Relayouter::CheckForTextFit(Controller& controller, float point 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(CONVERT_TO_UTF32 | @@ -257,7 +257,7 @@ void Controller::Relayouter::FitPointSizeforLayout(Controller& controller, const model->mElideEnabled = actualellipsis; impl.mFontDefaults->mFitPointSize = pointSizeArray[bestSizeIndex]; impl.mFontDefaults->sizeDefined = true; - controller.ClearFontData(); + impl.ClearFontData(); } } @@ -561,7 +561,7 @@ bool Controller::Relayouter::DoRelayout(Controller& controller, const Size& size // Reset the scroll position in inactive state if(elideTextEnabled && (impl.mEventData->mState == EventData::INACTIVE)) { - controller.ResetScrollPosition(); + impl.ResetScrollPosition(); } } diff --git a/dali-toolkit/internal/text/text-controller-text-updater.cpp b/dali-toolkit/internal/text/text-controller-text-updater.cpp index 75ea73c..8a19786 100644 --- a/dali-toolkit/internal/text/text-controller-text-updater.cpp +++ b/dali-toolkit/internal/text/text-controller-text-updater.cpp @@ -55,7 +55,7 @@ void Controller::TextUpdater::SetText(Controller& controller, const std::string& ResetText(controller); // Remove the style. - controller.ClearStyleData(); + impl.ClearStyleData(); CharacterIndex lastCursorIndex = 0u; @@ -150,7 +150,7 @@ void Controller::TextUpdater::SetText(Controller& controller, const std::string& controller.ResetCursorPosition(lastCursorIndex); // Scrolls the text to make the cursor visible. - controller.ResetScrollPosition(); + impl.ResetScrollPosition(); impl.RequestRelayout(); diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 19af999..0262929 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -138,7 +138,7 @@ void Controller::SetGlyphType(TextAbstraction::GlyphType glyphType) mImpl->mMetrics->SetGlyphType(glyphType); // Clear the font-specific data - ClearFontData(); + mImpl->ClearFontData(); mImpl->RequestRelayout(); } @@ -170,39 +170,12 @@ bool Controller::HasAnchors() const 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(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(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; } @@ -272,17 +245,7 @@ int Controller::GetMaximumNumberOfCharacters() 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 @@ -292,27 +255,7 @@ 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(LAYOUT | - UPDATE_LAYOUT_SIZE | - ALIGN | - REORDER); - - mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true; - mImpl->mOperationsPending = static_cast(mImpl->mOperationsPending | layoutOperations); - - // Need to recalculate natural size - mImpl->mRecalculateNaturalSize = true; - - mImpl->RequestRelayout(); - } + mImpl->SetMultiLineEnabled(enable); } bool Controller::IsMultiLineEnabled() const @@ -322,28 +265,7 @@ 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(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 @@ -353,13 +275,7 @@ 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(mImpl->mOperationsPending | ALIGN); - mImpl->RequestRelayout(); - } + mImpl->SetVerticalAlignment(alignment); } VerticalAlignment::Type Controller::GetVerticalAlignment() const @@ -417,31 +333,7 @@ bool Controller::IsShowingRealText() const void Controller::SetLineWrapMode(Text::LineWrap::Mode lineWrapMode) { - if(lineWrapMode != mImpl->mModel->mLineWrapMode) - { - // Update Text layout for applying wrap mode - mImpl->mOperationsPending = static_cast(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(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 @@ -590,17 +482,7 @@ void Controller::GetPlaceholderText(PlaceholderType type, std::string& text) con 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 @@ -640,7 +522,7 @@ void Controller::SetDefaultFontFamily(const std::string& defaultFontFamily) UpdateCursorPosition(mImpl->mEventData); // Clear the font-specific data - ClearFontData(); + mImpl->ClearFontData(); mImpl->RequestRelayout(); } @@ -671,7 +553,7 @@ void Controller::SetDefaultFontWeight(FontWeight weight) UpdateCursorPosition(mImpl->mEventData); // Clear the font-specific data - ClearFontData(); + mImpl->ClearFontData(); mImpl->RequestRelayout(); } @@ -712,7 +594,7 @@ void Controller::SetDefaultFontWidth(FontWidth width) UpdateCursorPosition(mImpl->mEventData); // Clear the font-specific data - ClearFontData(); + mImpl->ClearFontData(); mImpl->RequestRelayout(); } @@ -753,7 +635,7 @@ void Controller::SetDefaultFontSlant(FontSlant slant) UpdateCursorPosition(mImpl->mEventData); // Clear the font-specific data - ClearFontData(); + mImpl->ClearFontData(); mImpl->RequestRelayout(); } @@ -791,7 +673,7 @@ void Controller::SetFontSizeScale(float scale) UpdateCursorPosition(mImpl->mEventData); // Clear the font-specific data - ClearFontData(); + mImpl->ClearFontData(); mImpl->RequestRelayout(); } @@ -812,7 +694,7 @@ void Controller::SetDefaultFontSize(float fontSize, FontSizeType type) UpdateCursorPosition(mImpl->mEventData); // Clear the font-specific data - ClearFontData(); + mImpl->ClearFontData(); mImpl->RequestRelayout(); } @@ -838,15 +720,7 @@ float Controller::GetPlaceholderTextFontSize(FontSizeType type) const 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(mImpl->mOperationsPending | COLOR); - mImpl->RequestRelayout(); - } + mImpl->SetDefaultColor(color); } const Vector4& Controller::GetDefaultColor() const @@ -1001,15 +875,7 @@ const std::string& Controller::GetDefaultOutlineProperties() 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 @@ -1019,15 +885,7 @@ 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 @@ -1731,39 +1589,6 @@ void Controller::ShowPlaceholderText() 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(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 @@ -1781,20 +1606,7 @@ void Controller::ResetCursorPosition(CharacterIndex cursorIndex) 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) diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h index ec3cbb9..85d78a3 100644 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -1881,21 +1881,6 @@ private: // Helpers. */ 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.