2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali-toolkit/internal/text/text-controller.h>
22 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
23 #include <dali/devel-api/adaptor-framework/window-devel.h>
24 #include <dali/integration-api/debug.h>
30 #include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
31 #include <dali-toolkit/internal/text/text-controller-event-handler.h>
32 #include <dali-toolkit/internal/text/text-controller-impl.h>
33 #include <dali-toolkit/internal/text/text-controller-input-font-handler.h>
34 #include <dali-toolkit/internal/text/text-controller-placeholder-handler.h>
35 #include <dali-toolkit/internal/text/text-controller-relayouter.h>
36 #include <dali-toolkit/internal/text/text-controller-text-updater.h>
37 #include <dali-toolkit/internal/text/text-editable-control-interface.h>
41 #if defined(DEBUG_ENABLED)
42 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
45 constexpr float MAX_FLOAT = std::numeric_limits<float>::max();
47 const std::string EMPTY_STRING("");
49 int ConvertPixelToPint(float pixel)
51 unsigned int horizontalDpi = 0u;
52 unsigned int verticalDpi = 0u;
53 Dali::TextAbstraction::FontClient fontClient = Dali::TextAbstraction::FontClient::Get();
54 fontClient.GetDpi(horizontalDpi, verticalDpi);
56 return (pixel * 72.f) / static_cast<float>(horizontalDpi);
67 // public : Constructor.
69 ControllerPtr Controller::New()
71 return ControllerPtr(new Controller());
74 ControllerPtr Controller::New(ControlInterface* controlInterface)
76 return ControllerPtr(new Controller(controlInterface));
79 ControllerPtr Controller::New(ControlInterface* controlInterface,
80 EditableControlInterface* editableControlInterface,
81 SelectableControlInterface* selectableControlInterface,
82 AnchorControlInterface* anchorControlInterface)
84 return ControllerPtr(new Controller(controlInterface,
85 editableControlInterface,
86 selectableControlInterface,
87 anchorControlInterface));
90 // public : Configure the text controller.
92 void Controller::EnableTextInput(DecoratorPtr decorator, InputMethodContext& inputMethodContext)
96 delete mImpl->mEventData;
97 mImpl->mEventData = NULL;
99 // Nothing else to do.
103 if(NULL == mImpl->mEventData)
105 mImpl->mEventData = new EventData(decorator, inputMethodContext);
109 void Controller::SetGlyphType(TextAbstraction::GlyphType glyphType)
111 // Metrics for bitmap & vector based glyphs are different
112 mImpl->mMetrics->SetGlyphType(glyphType);
114 // Clear the font-specific data
117 mImpl->RequestRelayout();
120 void Controller::SetMarkupProcessorEnabled(bool enable)
122 if(enable != mImpl->mMarkupProcessorEnabled)
124 //If Text was already set, call the SetText again for enabling or disabling markup
125 mImpl->mMarkupProcessorEnabled = enable;
131 mImpl->mModel->mVisualModel->SetMarkupProcessorEnabled(enable);
134 bool Controller::IsMarkupProcessorEnabled() const
136 return mImpl->mMarkupProcessorEnabled;
139 bool Controller::HasAnchors() const
141 return (mImpl->mMarkupProcessorEnabled && mImpl->mModel->mLogicalModel->mAnchors.Count() && mImpl->IsShowingRealText());
144 void Controller::SetAutoScrollEnabled(bool enable)
146 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);
148 if(mImpl->mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX)
152 DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled for SINGLE_LINE_BOX\n");
153 mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
162 DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled Disabling autoscroll\n");
163 mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
170 mImpl->mIsAutoScrollEnabled = enable;
171 mImpl->RequestRelayout();
175 DALI_LOG_WARNING("Attempted AutoScrolling on a non SINGLE_LINE_BOX, request ignored\n");
176 mImpl->mIsAutoScrollEnabled = false;
180 bool Controller::IsAutoScrollEnabled() const
182 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::IsAutoScrollEnabled[%s]\n", mImpl->mIsAutoScrollEnabled ? "true" : "false");
184 return mImpl->mIsAutoScrollEnabled;
187 CharacterDirection Controller::GetAutoScrollDirection() const
189 return mImpl->mIsTextDirectionRTL;
192 float Controller::GetAutoScrollLineAlignment() const
196 if(mImpl->mModel->mVisualModel &&
197 (0u != mImpl->mModel->mVisualModel->mLines.Count()))
199 offset = (*mImpl->mModel->mVisualModel->mLines.Begin()).alignmentOffset;
205 void Controller::SetHorizontalScrollEnabled(bool enable)
207 if((NULL != mImpl->mEventData) &&
208 mImpl->mEventData->mDecorator)
210 mImpl->mEventData->mDecorator->SetHorizontalScrollEnabled(enable);
213 bool Controller::IsHorizontalScrollEnabled() const
215 if((NULL != mImpl->mEventData) &&
216 mImpl->mEventData->mDecorator)
218 return mImpl->mEventData->mDecorator->IsHorizontalScrollEnabled();
224 void Controller::SetVerticalScrollEnabled(bool enable)
226 if((NULL != mImpl->mEventData) &&
227 mImpl->mEventData->mDecorator)
229 if(mImpl->mEventData->mDecorator)
231 mImpl->mEventData->mDecorator->SetVerticalScrollEnabled(enable);
236 bool Controller::IsVerticalScrollEnabled() const
238 if((NULL != mImpl->mEventData) &&
239 mImpl->mEventData->mDecorator)
241 return mImpl->mEventData->mDecorator->IsVerticalScrollEnabled();
247 void Controller::SetSmoothHandlePanEnabled(bool enable)
249 if((NULL != mImpl->mEventData) &&
250 mImpl->mEventData->mDecorator)
252 mImpl->mEventData->mDecorator->SetSmoothHandlePanEnabled(enable);
256 bool Controller::IsSmoothHandlePanEnabled() const
258 if((NULL != mImpl->mEventData) &&
259 mImpl->mEventData->mDecorator)
261 return mImpl->mEventData->mDecorator->IsSmoothHandlePanEnabled();
267 void Controller::SetMaximumNumberOfCharacters(Length maxCharacters)
269 mImpl->mMaximumNumberOfCharacters = maxCharacters;
272 int Controller::GetMaximumNumberOfCharacters()
274 return mImpl->mMaximumNumberOfCharacters;
277 void Controller::SetEnableCursorBlink(bool enable)
279 DALI_ASSERT_DEBUG(NULL != mImpl->mEventData && "TextInput disabled");
281 if(NULL != mImpl->mEventData)
283 mImpl->mEventData->mCursorBlinkEnabled = enable;
286 mImpl->mEventData->mDecorator)
288 mImpl->mEventData->mDecorator->StopCursorBlink();
293 bool Controller::GetEnableCursorBlink() const
295 if(NULL != mImpl->mEventData)
297 return mImpl->mEventData->mCursorBlinkEnabled;
303 void Controller::SetMultiLineEnabled(bool enable)
305 const Layout::Engine::Type layout = enable ? Layout::Engine::MULTI_LINE_BOX : Layout::Engine::SINGLE_LINE_BOX;
307 if(layout != mImpl->mLayoutEngine.GetLayout())
309 // Set the layout type.
310 mImpl->mLayoutEngine.SetLayout(layout);
312 // Set the flags to redo the layout operations
313 const OperationsMask layoutOperations = static_cast<OperationsMask>(LAYOUT |
318 mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
319 mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | layoutOperations);
321 // Need to recalculate natural size
322 mImpl->mRecalculateNaturalSize = true;
324 mImpl->RequestRelayout();
328 bool Controller::IsMultiLineEnabled() const
330 return Layout::Engine::MULTI_LINE_BOX == mImpl->mLayoutEngine.GetLayout();
333 void Controller::SetHorizontalAlignment(Text::HorizontalAlignment::Type alignment)
335 if(alignment != mImpl->mModel->mHorizontalAlignment)
337 // Set the alignment.
338 mImpl->mModel->mHorizontalAlignment = alignment;
340 // Set the flag to redo the alignment operation.
341 mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | ALIGN);
343 if(mImpl->mEventData)
345 mImpl->mEventData->mUpdateAlignment = true;
347 // Update the cursor if it's in editing mode
348 if(EventData::IsEditingState(mImpl->mEventData->mState))
350 mImpl->ChangeState(EventData::EDITING);
351 mImpl->mEventData->mUpdateCursorPosition = true;
355 mImpl->RequestRelayout();
359 Text::HorizontalAlignment::Type Controller::GetHorizontalAlignment() const
361 return mImpl->mModel->mHorizontalAlignment;
364 void Controller::SetVerticalAlignment(VerticalAlignment::Type alignment)
366 if(alignment != mImpl->mModel->mVerticalAlignment)
368 // Set the alignment.
369 mImpl->mModel->mVerticalAlignment = alignment;
371 mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | ALIGN);
373 mImpl->RequestRelayout();
377 VerticalAlignment::Type Controller::GetVerticalAlignment() const
379 return mImpl->mModel->mVerticalAlignment;
382 bool Controller::IsIgnoreSpacesAfterText() const
384 return mImpl->mModel->mIgnoreSpacesAfterText;
387 void Controller::SetIgnoreSpacesAfterText(bool ignore)
389 mImpl->mModel->mIgnoreSpacesAfterText = ignore;
392 void Controller::ChangedLayoutDirection()
394 mImpl->mIsLayoutDirectionChanged = true;
397 void Controller::SetMatchLayoutDirection(DevelText::MatchLayoutDirection type)
399 mImpl->mModel->mMatchLayoutDirection = type;
402 DevelText::MatchLayoutDirection Controller::GetMatchLayoutDirection() const
404 return mImpl->mModel->mMatchLayoutDirection;
407 void Controller::SetLayoutDirection(Dali::LayoutDirection::Type layoutDirection)
409 mImpl->mLayoutDirection = layoutDirection;
412 Dali::LayoutDirection::Type Controller::GetLayoutDirection(Dali::Actor& actor) const
414 if(mImpl->mModel->mMatchLayoutDirection == DevelText::MatchLayoutDirection::LOCALE ||
415 (mImpl->mModel->mMatchLayoutDirection == DevelText::MatchLayoutDirection::INHERIT && !mImpl->mIsLayoutDirectionChanged))
417 return static_cast<Dali::LayoutDirection::Type>(DevelWindow::Get(actor).GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
421 return static_cast<Dali::LayoutDirection::Type>(actor.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
425 bool Controller::IsShowingRealText() const
427 return mImpl->IsShowingRealText();
430 void Controller::SetLineWrapMode(Text::LineWrap::Mode lineWrapMode)
432 if(lineWrapMode != mImpl->mModel->mLineWrapMode)
434 // Update Text layout for applying wrap mode
435 mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
441 if((mImpl->mModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) || (lineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) ||
442 (mImpl->mModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::MIXED) || (lineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::MIXED)) // hyphen is treated as line break
444 mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | GET_LINE_BREAKS);
447 // Set the text wrap mode.
448 mImpl->mModel->mLineWrapMode = lineWrapMode;
450 mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
451 mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
452 mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mModel->mLogicalModel->mText.Count();
455 mImpl->RequestRelayout();
459 Text::LineWrap::Mode Controller::GetLineWrapMode() const
461 return mImpl->mModel->mLineWrapMode;
464 void Controller::SetTextElideEnabled(bool enabled)
466 mImpl->mModel->mElideEnabled = enabled;
467 mImpl->mModel->mVisualModel->SetTextElideEnabled(enabled);
470 bool Controller::IsTextElideEnabled() const
472 return mImpl->mModel->mElideEnabled;
475 void Controller::SetTextFitEnabled(bool enabled)
477 mImpl->mTextFitEnabled = enabled;
480 bool Controller::IsTextFitEnabled() const
482 return mImpl->mTextFitEnabled;
485 void Controller::SetTextFitMinSize(float minSize, FontSizeType type)
491 mImpl->mTextFitMinSize = minSize;
496 mImpl->mTextFitMinSize = ConvertPixelToPint(minSize);
502 float Controller::GetTextFitMinSize() const
504 return mImpl->mTextFitMinSize;
507 void Controller::SetTextFitMaxSize(float maxSize, FontSizeType type)
513 mImpl->mTextFitMaxSize = maxSize;
518 mImpl->mTextFitMaxSize = ConvertPixelToPint(maxSize);
524 float Controller::GetTextFitMaxSize() const
526 return mImpl->mTextFitMaxSize;
529 void Controller::SetTextFitStepSize(float step, FontSizeType type)
535 mImpl->mTextFitStepSize = step;
540 mImpl->mTextFitStepSize = ConvertPixelToPint(step);
546 float Controller::GetTextFitStepSize() const
548 return mImpl->mTextFitStepSize;
551 void Controller::SetTextFitContentSize(Vector2 size)
553 mImpl->mTextFitContentSize = size;
556 Vector2 Controller::GetTextFitContentSize() const
558 return mImpl->mTextFitContentSize;
561 void Controller::SetPlaceholderTextElideEnabled(bool enabled)
563 PlaceholderHandler::SetPlaceholderTextElideEnabled(*this, enabled);
566 bool Controller::IsPlaceholderTextElideEnabled() const
568 return PlaceholderHandler::IsPlaceholderTextElideEnabled(*this);
571 void Controller::SetSelectionEnabled(bool enabled)
573 mImpl->mEventData->mSelectionEnabled = enabled;
576 bool Controller::IsSelectionEnabled() const
578 return mImpl->mEventData->mSelectionEnabled;
581 void Controller::SetShiftSelectionEnabled(bool enabled)
583 mImpl->mEventData->mShiftSelectionFlag = enabled;
586 bool Controller::IsShiftSelectionEnabled() const
588 return mImpl->mEventData->mShiftSelectionFlag;
591 void Controller::SetGrabHandleEnabled(bool enabled)
593 mImpl->mEventData->mGrabHandleEnabled = enabled;
596 bool Controller::IsGrabHandleEnabled() const
598 return mImpl->mEventData->mGrabHandleEnabled;
601 void Controller::SetGrabHandlePopupEnabled(bool enabled)
603 mImpl->mEventData->mGrabHandlePopupEnabled = enabled;
606 bool Controller::IsGrabHandlePopupEnabled() const
608 return mImpl->mEventData->mGrabHandlePopupEnabled;
613 void Controller::SetText(const std::string& text)
615 TextUpdater::SetText(*this, text);
618 void Controller::GetText(std::string& text) const
620 if(!mImpl->IsShowingPlaceholderText())
622 // Retrieves the text string.
623 mImpl->GetText(0u, text);
627 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::GetText %p empty (but showing placeholder)\n", this);
631 void Controller::SetPlaceholderText(PlaceholderType type, const std::string& text)
633 PlaceholderHandler::SetPlaceholderText(*this, type, text);
636 void Controller::GetPlaceholderText(PlaceholderType type, std::string& text) const
638 PlaceholderHandler::GetPlaceholderText(*this, type, text);
641 void Controller::UpdateAfterFontChange(const std::string& newDefaultFont)
643 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::UpdateAfterFontChange\n");
645 if(!mImpl->mFontDefaults->familyDefined) // If user defined font then should not update when system font changes
647 DALI_LOG_INFO(gLogFilter, Debug::Concise, "Controller::UpdateAfterFontChange newDefaultFont(%s)\n", newDefaultFont.c_str());
648 mImpl->mFontDefaults->mFontDescription.family = newDefaultFont;
652 mImpl->RequestRelayout();
656 void Controller::RetrieveSelection(std::string& selectedText) const
658 mImpl->RetrieveSelection(selectedText, false);
661 void Controller::SetSelection(int start, int end)
663 mImpl->SetSelection(start, end);
666 std::pair<int, int> Controller::GetSelectionIndexes() const
668 return mImpl->GetSelectionIndexes();
671 void Controller::CopyStringToClipboard(const std::string& source)
673 mImpl->CopyStringToClipboard(source);
676 void Controller::SendSelectionToClipboard(bool deleteAfterSending)
678 mImpl->SendSelectionToClipboard(deleteAfterSending);
681 // public : Default style & Input style
683 void Controller::SetDefaultFontFamily(const std::string& defaultFontFamily)
685 if(NULL == mImpl->mFontDefaults)
687 mImpl->mFontDefaults = new FontDefaults();
690 mImpl->mFontDefaults->mFontDescription.family = defaultFontFamily;
691 DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetDefaultFontFamily %s\n", defaultFontFamily.c_str());
692 mImpl->mFontDefaults->familyDefined = !defaultFontFamily.empty();
694 if(mImpl->mEventData)
696 // Update the cursor position if it's in editing mode
697 if(EventData::IsEditingState(mImpl->mEventData->mState))
699 mImpl->mEventData->mDecoratorUpdated = true;
700 mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font family is updated.
704 // Clear the font-specific data
707 mImpl->RequestRelayout();
710 const std::string& Controller::GetDefaultFontFamily() const
712 if(NULL != mImpl->mFontDefaults)
714 return mImpl->mFontDefaults->mFontDescription.family;
720 void Controller::SetPlaceholderFontFamily(const std::string& placeholderTextFontFamily)
722 PlaceholderHandler::SetPlaceholderFontFamily(*this, placeholderTextFontFamily);
725 const std::string& Controller::GetPlaceholderFontFamily() const
727 return PlaceholderHandler::GetPlaceholderFontFamily(*this);
730 void Controller::SetDefaultFontWeight(FontWeight weight)
732 if(NULL == mImpl->mFontDefaults)
734 mImpl->mFontDefaults = new FontDefaults();
737 mImpl->mFontDefaults->mFontDescription.weight = weight;
738 mImpl->mFontDefaults->weightDefined = true;
740 if(mImpl->mEventData)
742 // Update the cursor position if it's in editing mode
743 if(EventData::IsEditingState(mImpl->mEventData->mState))
745 mImpl->mEventData->mDecoratorUpdated = true;
746 mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font weight is updated.
750 // Clear the font-specific data
753 mImpl->RequestRelayout();
756 bool Controller::IsDefaultFontWeightDefined() const
758 if(NULL != mImpl->mFontDefaults)
760 return mImpl->mFontDefaults->weightDefined;
766 FontWeight Controller::GetDefaultFontWeight() const
768 if(NULL != mImpl->mFontDefaults)
770 return mImpl->mFontDefaults->mFontDescription.weight;
773 return TextAbstraction::FontWeight::NORMAL;
776 void Controller::SetPlaceholderTextFontWeight(FontWeight weight)
778 PlaceholderHandler::SetPlaceholderTextFontWeight(*this, weight);
781 bool Controller::IsPlaceholderTextFontWeightDefined() const
783 return PlaceholderHandler::IsPlaceholderTextFontWeightDefined(*this);
787 FontWeight Controller::GetPlaceholderTextFontWeight() const
789 return PlaceholderHandler::GetPlaceholderTextFontWeight(*this);
792 void Controller::SetDefaultFontWidth(FontWidth width)
794 if(NULL == mImpl->mFontDefaults)
796 mImpl->mFontDefaults = new FontDefaults();
799 mImpl->mFontDefaults->mFontDescription.width = width;
800 mImpl->mFontDefaults->widthDefined = true;
802 if(mImpl->mEventData)
804 // Update the cursor position if it's in editing mode
805 if(EventData::IsEditingState(mImpl->mEventData->mState))
807 mImpl->mEventData->mDecoratorUpdated = true;
808 mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font width is updated.
812 // Clear the font-specific data
815 mImpl->RequestRelayout();
818 bool Controller::IsDefaultFontWidthDefined() const
820 if(NULL != mImpl->mFontDefaults)
822 return mImpl->mFontDefaults->widthDefined;
828 FontWidth Controller::GetDefaultFontWidth() const
830 if(NULL != mImpl->mFontDefaults)
832 return mImpl->mFontDefaults->mFontDescription.width;
835 return TextAbstraction::FontWidth::NORMAL;
838 void Controller::SetPlaceholderTextFontWidth(FontWidth width)
840 PlaceholderHandler::SetPlaceholderTextFontWidth(*this, width);
843 bool Controller::IsPlaceholderTextFontWidthDefined() const
845 return PlaceholderHandler::IsPlaceholderTextFontWidthDefined(*this);
848 FontWidth Controller::GetPlaceholderTextFontWidth() const
850 return PlaceholderHandler::GetPlaceholderTextFontWidth(*this);
853 void Controller::SetDefaultFontSlant(FontSlant slant)
855 if(NULL == mImpl->mFontDefaults)
857 mImpl->mFontDefaults = new FontDefaults();
860 mImpl->mFontDefaults->mFontDescription.slant = slant;
861 mImpl->mFontDefaults->slantDefined = true;
863 if(mImpl->mEventData)
865 // Update the cursor position if it's in editing mode
866 if(EventData::IsEditingState(mImpl->mEventData->mState))
868 mImpl->mEventData->mDecoratorUpdated = true;
869 mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font slant is updated.
873 // Clear the font-specific data
876 mImpl->RequestRelayout();
879 bool Controller::IsDefaultFontSlantDefined() const
881 if(NULL != mImpl->mFontDefaults)
883 return mImpl->mFontDefaults->slantDefined;
888 FontSlant Controller::GetDefaultFontSlant() const
890 if(NULL != mImpl->mFontDefaults)
892 return mImpl->mFontDefaults->mFontDescription.slant;
895 return TextAbstraction::FontSlant::NORMAL;
898 void Controller::SetPlaceholderTextFontSlant(FontSlant slant)
900 PlaceholderHandler::SetPlaceholderTextFontSlant(*this, slant);
903 bool Controller::IsPlaceholderTextFontSlantDefined() const
905 return PlaceholderHandler::IsPlaceholderTextFontSlantDefined(*this);
908 FontSlant Controller::GetPlaceholderTextFontSlant() const
910 return PlaceholderHandler::GetPlaceholderTextFontSlant(*this);
913 void Controller::SetFontSizeScale(float scale)
915 mImpl->mFontSizeScale = scale;
917 if(mImpl->mEventData)
919 // Update the cursor position if it's in editing mode
920 if(EventData::IsEditingState(mImpl->mEventData->mState))
922 mImpl->mEventData->mDecoratorUpdated = true;
923 mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font size is updated.
927 // Clear the font-specific data
930 mImpl->RequestRelayout();
933 float Controller::GetFontSizeScale() const
935 if(nullptr != mImpl->mFontDefaults)
937 return mImpl->mFontSizeScale;
943 void Controller::SetDefaultFontSize(float fontSize, FontSizeType type)
945 if(NULL == mImpl->mFontDefaults)
947 mImpl->mFontDefaults = new FontDefaults();
954 mImpl->mFontDefaults->mDefaultPointSize = fontSize;
955 mImpl->mFontDefaults->sizeDefined = true;
960 // Point size = Pixel size * 72.f / DPI
961 unsigned int horizontalDpi = 0u;
962 unsigned int verticalDpi = 0u;
963 TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
964 fontClient.GetDpi(horizontalDpi, verticalDpi);
966 mImpl->mFontDefaults->mDefaultPointSize = (fontSize * 72.f) / static_cast<float>(horizontalDpi);
967 mImpl->mFontDefaults->sizeDefined = true;
972 if(mImpl->mEventData)
974 // Update the cursor position if it's in editing mode
975 if(EventData::IsEditingState(mImpl->mEventData->mState))
977 mImpl->mEventData->mDecoratorUpdated = true;
978 mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font size is updated.
982 // Clear the font-specific data
985 mImpl->RequestRelayout();
988 float Controller::GetDefaultFontSize(FontSizeType type) const
991 if(NULL != mImpl->mFontDefaults)
997 value = mImpl->mFontDefaults->mDefaultPointSize;
1002 // Pixel size = Point size * DPI / 72.f
1003 unsigned int horizontalDpi = 0u;
1004 unsigned int verticalDpi = 0u;
1005 TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
1006 fontClient.GetDpi(horizontalDpi, verticalDpi);
1008 value = mImpl->mFontDefaults->mDefaultPointSize * static_cast<float>(horizontalDpi) / 72.f;
1018 void Controller::SetPlaceholderTextFontSize(float fontSize, FontSizeType type)
1020 PlaceholderHandler::SetPlaceholderTextFontSize(*this, fontSize, type);
1023 float Controller::GetPlaceholderTextFontSize(FontSizeType type) const
1025 return PlaceholderHandler::GetPlaceholderTextFontSize(*this, type);
1028 void Controller::SetDefaultColor(const Vector4& color)
1030 mImpl->mTextColor = color;
1032 if(!mImpl->IsShowingPlaceholderText())
1034 mImpl->mModel->mVisualModel->SetTextColor(color);
1036 mImpl->mModel->mLogicalModel->mColorRuns.Clear();
1038 mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | COLOR);
1040 mImpl->RequestRelayout();
1044 const Vector4& Controller::GetDefaultColor() const
1046 return mImpl->mTextColor;
1049 void Controller::SetPlaceholderTextColor(const Vector4& textColor)
1051 PlaceholderHandler::SetPlaceholderTextColor(*this, textColor);
1054 const Vector4& Controller::GetPlaceholderTextColor() const
1056 return PlaceholderHandler::GetPlaceholderTextColor(*this);
1059 void Controller::SetShadowOffset(const Vector2& shadowOffset)
1061 mImpl->mModel->mVisualModel->SetShadowOffset(shadowOffset);
1063 mImpl->RequestRelayout();
1066 const Vector2& Controller::GetShadowOffset() const
1068 return mImpl->mModel->mVisualModel->GetShadowOffset();
1071 void Controller::SetShadowColor(const Vector4& shadowColor)
1073 mImpl->mModel->mVisualModel->SetShadowColor(shadowColor);
1075 mImpl->RequestRelayout();
1078 const Vector4& Controller::GetShadowColor() const
1080 return mImpl->mModel->mVisualModel->GetShadowColor();
1083 void Controller::SetShadowBlurRadius(const float& shadowBlurRadius)
1085 if(fabsf(GetShadowBlurRadius() - shadowBlurRadius) > Math::MACHINE_EPSILON_1)
1087 mImpl->mModel->mVisualModel->SetShadowBlurRadius(shadowBlurRadius);
1089 mImpl->RequestRelayout();
1093 const float& Controller::GetShadowBlurRadius() const
1095 return mImpl->mModel->mVisualModel->GetShadowBlurRadius();
1098 void Controller::SetUnderlineColor(const Vector4& color)
1100 mImpl->mModel->mVisualModel->SetUnderlineColor(color);
1102 mImpl->RequestRelayout();
1105 const Vector4& Controller::GetUnderlineColor() const
1107 return mImpl->mModel->mVisualModel->GetUnderlineColor();
1110 void Controller::SetUnderlineEnabled(bool enabled)
1112 mImpl->mModel->mVisualModel->SetUnderlineEnabled(enabled);
1114 mImpl->RequestRelayout();
1117 bool Controller::IsUnderlineEnabled() const
1119 return mImpl->mModel->mVisualModel->IsUnderlineEnabled();
1122 void Controller::SetUnderlineHeight(float height)
1124 mImpl->mModel->mVisualModel->SetUnderlineHeight(height);
1126 mImpl->RequestRelayout();
1129 float Controller::GetUnderlineHeight() const
1131 return mImpl->mModel->mVisualModel->GetUnderlineHeight();
1134 void Controller::SetOutlineColor(const Vector4& color)
1136 mImpl->mModel->mVisualModel->SetOutlineColor(color);
1138 mImpl->RequestRelayout();
1141 const Vector4& Controller::GetOutlineColor() const
1143 return mImpl->mModel->mVisualModel->GetOutlineColor();
1146 void Controller::SetOutlineWidth(uint16_t width)
1148 mImpl->mModel->mVisualModel->SetOutlineWidth(width);
1150 mImpl->RequestRelayout();
1153 uint16_t Controller::GetOutlineWidth() const
1155 return mImpl->mModel->mVisualModel->GetOutlineWidth();
1158 void Controller::SetBackgroundColor(const Vector4& color)
1160 mImpl->mModel->mVisualModel->SetBackgroundColor(color);
1162 mImpl->RequestRelayout();
1165 const Vector4& Controller::GetBackgroundColor() const
1167 return mImpl->mModel->mVisualModel->GetBackgroundColor();
1170 void Controller::SetBackgroundEnabled(bool enabled)
1172 mImpl->mModel->mVisualModel->SetBackgroundEnabled(enabled);
1174 mImpl->RequestRelayout();
1177 bool Controller::IsBackgroundEnabled() const
1179 return mImpl->mModel->mVisualModel->IsBackgroundEnabled();
1182 void Controller::SetDefaultEmbossProperties(const std::string& embossProperties)
1184 if(NULL == mImpl->mEmbossDefaults)
1186 mImpl->mEmbossDefaults = new EmbossDefaults();
1189 mImpl->mEmbossDefaults->properties = embossProperties;
1192 const std::string& Controller::GetDefaultEmbossProperties() const
1194 if(NULL != mImpl->mEmbossDefaults)
1196 return mImpl->mEmbossDefaults->properties;
1199 return EMPTY_STRING;
1202 void Controller::SetDefaultOutlineProperties(const std::string& outlineProperties)
1204 if(NULL == mImpl->mOutlineDefaults)
1206 mImpl->mOutlineDefaults = new OutlineDefaults();
1209 mImpl->mOutlineDefaults->properties = outlineProperties;
1212 const std::string& Controller::GetDefaultOutlineProperties() const
1214 if(NULL != mImpl->mOutlineDefaults)
1216 return mImpl->mOutlineDefaults->properties;
1219 return EMPTY_STRING;
1222 bool Controller::SetDefaultLineSpacing(float lineSpacing)
1224 if(std::fabs(lineSpacing - mImpl->mLayoutEngine.GetDefaultLineSpacing()) > Math::MACHINE_EPSILON_1000)
1226 mImpl->mLayoutEngine.SetDefaultLineSpacing(lineSpacing);
1227 mImpl->mRecalculateNaturalSize = true;
1233 float Controller::GetDefaultLineSpacing() const
1235 return mImpl->mLayoutEngine.GetDefaultLineSpacing();
1238 bool Controller::SetDefaultLineSize(float lineSize)
1240 if(std::fabs(lineSize - mImpl->mLayoutEngine.GetDefaultLineSize()) > Math::MACHINE_EPSILON_1000)
1242 mImpl->mLayoutEngine.SetDefaultLineSize(lineSize);
1243 mImpl->mRecalculateNaturalSize = true;
1249 float Controller::GetDefaultLineSize() const
1251 return mImpl->mLayoutEngine.GetDefaultLineSize();
1254 void Controller::SetInputColor(const Vector4& color)
1256 if(NULL != mImpl->mEventData)
1258 mImpl->mEventData->mInputStyle.textColor = color;
1259 mImpl->mEventData->mInputStyle.isDefaultColor = false;
1261 if(EventData::SELECTING == mImpl->mEventData->mState || EventData::EDITING == mImpl->mEventData->mState || EventData::INACTIVE == mImpl->mEventData->mState)
1263 if(EventData::SELECTING == mImpl->mEventData->mState)
1265 const bool handlesCrossed = mImpl->mEventData->mLeftSelectionPosition > mImpl->mEventData->mRightSelectionPosition;
1267 // Get start and end position of selection
1268 const CharacterIndex startOfSelectedText = handlesCrossed ? mImpl->mEventData->mRightSelectionPosition : mImpl->mEventData->mLeftSelectionPosition;
1269 const Length lengthOfSelectedText = (handlesCrossed ? mImpl->mEventData->mLeftSelectionPosition : mImpl->mEventData->mRightSelectionPosition) - startOfSelectedText;
1271 // Add the color run.
1272 const VectorBase::SizeType numberOfRuns = mImpl->mModel->mLogicalModel->mColorRuns.Count();
1273 mImpl->mModel->mLogicalModel->mColorRuns.Resize(numberOfRuns + 1u);
1275 ColorRun& colorRun = *(mImpl->mModel->mLogicalModel->mColorRuns.Begin() + numberOfRuns);
1276 colorRun.color = color;
1277 colorRun.characterRun.characterIndex = startOfSelectedText;
1278 colorRun.characterRun.numberOfCharacters = lengthOfSelectedText;
1280 mImpl->mTextUpdateInfo.mCharacterIndex = startOfSelectedText;
1281 mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
1282 mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = lengthOfSelectedText;
1286 mImpl->mTextUpdateInfo.mCharacterIndex = 0;
1287 mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
1288 mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mModel->mLogicalModel->mText.Count();
1291 // Request to relayout.
1292 mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | COLOR);
1293 mImpl->RequestRelayout();
1298 const Vector4& Controller::GetInputColor() const
1300 if(NULL != mImpl->mEventData)
1302 return mImpl->mEventData->mInputStyle.textColor;
1305 // Return the default text's color if there is no EventData.
1306 return mImpl->mTextColor;
1309 void Controller::SetInputFontFamily(const std::string& fontFamily)
1311 InputFontHandler::SetInputFontFamily(*this, fontFamily);
1314 const std::string& Controller::GetInputFontFamily() const
1316 return InputFontHandler::GetInputFontFamily(*this);
1319 void Controller::SetInputFontWeight(FontWeight weight)
1321 InputFontHandler::SetInputFontWeight(*this, weight);
1324 bool Controller::IsInputFontWeightDefined() const
1326 return InputFontHandler::IsInputFontWeightDefined(*this);
1329 FontWeight Controller::GetInputFontWeight() const
1331 return InputFontHandler::GetInputFontWeight(*this);
1334 void Controller::SetInputFontWidth(FontWidth width)
1336 InputFontHandler::SetInputFontWidth(*this, width);
1339 bool Controller::IsInputFontWidthDefined() const
1341 return InputFontHandler::IsInputFontWidthDefined(*this);
1344 FontWidth Controller::GetInputFontWidth() const
1346 return InputFontHandler::GetInputFontWidth(*this);
1349 void Controller::SetInputFontSlant(FontSlant slant)
1351 InputFontHandler::SetInputFontSlant(*this, slant);
1354 bool Controller::IsInputFontSlantDefined() const
1356 return InputFontHandler::IsInputFontSlantDefined(*this);
1359 FontSlant Controller::GetInputFontSlant() const
1361 return InputFontHandler::GetInputFontSlant(*this);
1364 void Controller::SetInputFontPointSize(float size)
1366 InputFontHandler::SetInputFontPointSize(*this, size);
1369 float Controller::GetInputFontPointSize() const
1371 return InputFontHandler::GetInputFontPointSize(*this);
1374 void Controller::SetInputLineSpacing(float lineSpacing)
1376 if(NULL != mImpl->mEventData)
1378 mImpl->mEventData->mInputStyle.lineSpacing = lineSpacing;
1379 mImpl->mEventData->mInputStyle.isLineSpacingDefined = true;
1383 float Controller::GetInputLineSpacing() const
1385 if(NULL != mImpl->mEventData)
1387 return mImpl->mEventData->mInputStyle.lineSpacing;
1393 void Controller::SetInputShadowProperties(const std::string& shadowProperties)
1395 if(NULL != mImpl->mEventData)
1397 mImpl->mEventData->mInputStyle.shadowProperties = shadowProperties;
1401 const std::string& Controller::GetInputShadowProperties() const
1403 if(NULL != mImpl->mEventData)
1405 return mImpl->mEventData->mInputStyle.shadowProperties;
1408 return EMPTY_STRING;
1411 void Controller::SetInputUnderlineProperties(const std::string& underlineProperties)
1413 if(NULL != mImpl->mEventData)
1415 mImpl->mEventData->mInputStyle.underlineProperties = underlineProperties;
1419 const std::string& Controller::GetInputUnderlineProperties() const
1421 if(NULL != mImpl->mEventData)
1423 return mImpl->mEventData->mInputStyle.underlineProperties;
1426 return EMPTY_STRING;
1429 void Controller::SetInputEmbossProperties(const std::string& embossProperties)
1431 if(NULL != mImpl->mEventData)
1433 mImpl->mEventData->mInputStyle.embossProperties = embossProperties;
1437 const std::string& Controller::GetInputEmbossProperties() const
1439 if(NULL != mImpl->mEventData)
1441 return mImpl->mEventData->mInputStyle.embossProperties;
1444 return GetDefaultEmbossProperties();
1447 void Controller::SetInputOutlineProperties(const std::string& outlineProperties)
1449 if(NULL != mImpl->mEventData)
1451 mImpl->mEventData->mInputStyle.outlineProperties = outlineProperties;
1455 const std::string& Controller::GetInputOutlineProperties() const
1457 if(NULL != mImpl->mEventData)
1459 return mImpl->mEventData->mInputStyle.outlineProperties;
1462 return GetDefaultOutlineProperties();
1465 void Controller::SetInputModePassword(bool passwordInput)
1467 if(NULL != mImpl->mEventData)
1469 mImpl->mEventData->mPasswordInput = passwordInput;
1473 bool Controller::IsInputModePassword()
1475 if(NULL != mImpl->mEventData)
1477 return mImpl->mEventData->mPasswordInput;
1482 void Controller::SetNoTextDoubleTapAction(NoTextTap::Action action)
1484 if(NULL != mImpl->mEventData)
1486 mImpl->mEventData->mDoubleTapAction = action;
1490 Controller::NoTextTap::Action Controller::GetNoTextDoubleTapAction() const
1492 NoTextTap::Action action = NoTextTap::NO_ACTION;
1494 if(NULL != mImpl->mEventData)
1496 action = mImpl->mEventData->mDoubleTapAction;
1502 void Controller::SetNoTextLongPressAction(NoTextTap::Action action)
1504 if(NULL != mImpl->mEventData)
1506 mImpl->mEventData->mLongPressAction = action;
1510 Controller::NoTextTap::Action Controller::GetNoTextLongPressAction() const
1512 NoTextTap::Action action = NoTextTap::NO_ACTION;
1514 if(NULL != mImpl->mEventData)
1516 action = mImpl->mEventData->mLongPressAction;
1522 bool Controller::IsUnderlineSetByString()
1524 return mImpl->mUnderlineSetByString;
1527 void Controller::UnderlineSetByString(bool setByString)
1529 mImpl->mUnderlineSetByString = setByString;
1532 bool Controller::IsShadowSetByString()
1534 return mImpl->mShadowSetByString;
1537 void Controller::ShadowSetByString(bool setByString)
1539 mImpl->mShadowSetByString = setByString;
1542 bool Controller::IsOutlineSetByString()
1544 return mImpl->mOutlineSetByString;
1547 void Controller::OutlineSetByString(bool setByString)
1549 mImpl->mOutlineSetByString = setByString;
1552 bool Controller::IsFontStyleSetByString()
1554 return mImpl->mFontStyleSetByString;
1557 void Controller::FontStyleSetByString(bool setByString)
1559 mImpl->mFontStyleSetByString = setByString;
1562 // public : Queries & retrieves.
1564 Layout::Engine& Controller::GetLayoutEngine()
1566 return mImpl->mLayoutEngine;
1569 View& Controller::GetView()
1571 return mImpl->mView;
1574 Vector3 Controller::GetNaturalSize()
1576 return Relayouter::GetNaturalSize(*this);
1579 bool Controller::CheckForTextFit(float pointSize, Size& layoutSize)
1581 return Relayouter::CheckForTextFit(*this, pointSize, layoutSize);
1584 void Controller::FitPointSizeforLayout(Size layoutSize)
1586 Relayouter::FitPointSizeforLayout(*this, layoutSize);
1589 float Controller::GetHeightForWidth(float width)
1591 return Relayouter::GetHeightForWidth(*this, width);
1594 int Controller::GetLineCount(float width)
1596 GetHeightForWidth(width);
1597 int numberofLines = mImpl->mModel->GetNumberOfLines();
1598 return numberofLines;
1601 const ModelInterface* const Controller::GetTextModel() const
1603 return mImpl->mModel.Get();
1606 float Controller::GetScrollAmountByUserInput()
1608 float scrollAmount = 0.0f;
1610 if(NULL != mImpl->mEventData && mImpl->mEventData->mCheckScrollAmount)
1612 scrollAmount = mImpl->mModel->mScrollPosition.y - mImpl->mModel->mScrollPositionLast.y;
1613 mImpl->mEventData->mCheckScrollAmount = false;
1615 return scrollAmount;
1618 bool Controller::GetTextScrollInfo(float& scrollPosition, float& controlHeight, float& layoutHeight)
1620 const Vector2& layout = mImpl->mModel->mVisualModel->GetLayoutSize();
1623 controlHeight = mImpl->mModel->mVisualModel->mControlSize.height;
1624 layoutHeight = layout.height;
1625 scrollPosition = mImpl->mModel->mScrollPosition.y;
1626 isScrolled = !Equals(mImpl->mModel->mScrollPosition.y, mImpl->mModel->mScrollPositionLast.y, Math::MACHINE_EPSILON_1);
1630 void Controller::SetHiddenInputOption(const Property::Map& options)
1632 if(NULL == mImpl->mHiddenInput)
1634 mImpl->mHiddenInput = new HiddenText(this);
1636 mImpl->mHiddenInput->SetProperties(options);
1639 void Controller::GetHiddenInputOption(Property::Map& options)
1641 if(NULL != mImpl->mHiddenInput)
1643 mImpl->mHiddenInput->GetProperties(options);
1647 void Controller::SetInputFilterOption(const Property::Map& options)
1649 if(!mImpl->mInputFilter)
1651 mImpl->mInputFilter = std::unique_ptr<InputFilter>(new InputFilter());
1653 mImpl->mInputFilter->SetProperties(options);
1656 void Controller::GetInputFilterOption(Property::Map& options)
1658 if(NULL != mImpl->mInputFilter)
1660 mImpl->mInputFilter->GetProperties(options);
1664 void Controller::SetPlaceholderProperty(const Property::Map& map)
1666 PlaceholderHandler::SetPlaceholderProperty(*this, map);
1669 void Controller::GetPlaceholderProperty(Property::Map& map)
1671 PlaceholderHandler::GetPlaceholderProperty(*this, map);
1674 Toolkit::DevelText::TextDirection::Type Controller::GetTextDirection()
1676 // Make sure the model is up-to-date before layouting
1677 ProcessModifyEvents();
1679 if(mImpl->mUpdateTextDirection)
1681 // Operations that can be done only once until the text changes.
1682 const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
1690 // Set the update info to relayout the whole text.
1691 mImpl->mTextUpdateInfo.mParagraphCharacterIndex = 0u;
1692 mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters = mImpl->mModel->mLogicalModel->mText.Count();
1694 // Make sure the model is up-to-date before layouting
1695 mImpl->UpdateModel(onlyOnceOperations);
1697 Vector3 naturalSize;
1698 DoRelayout(Size(MAX_FLOAT, MAX_FLOAT),
1699 static_cast<OperationsMask>(onlyOnceOperations |
1700 LAYOUT | REORDER | UPDATE_DIRECTION),
1701 naturalSize.GetVectorXY());
1703 // Do not do again the only once operations.
1704 mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending & ~onlyOnceOperations);
1706 // Clear the update info. This info will be set the next time the text is updated.
1707 mImpl->mTextUpdateInfo.Clear();
1709 // FullRelayoutNeeded should be true because DoRelayout is MAX_FLOAT, MAX_FLOAT.
1710 mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
1712 mImpl->mUpdateTextDirection = false;
1715 return mImpl->mIsTextDirectionRTL ? Toolkit::DevelText::TextDirection::RIGHT_TO_LEFT : Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT;
1718 Toolkit::DevelText::VerticalLineAlignment::Type Controller::GetVerticalLineAlignment() const
1720 return mImpl->mModel->GetVerticalLineAlignment();
1723 void Controller::SetVerticalLineAlignment(Toolkit::DevelText::VerticalLineAlignment::Type alignment)
1725 mImpl->mModel->mVerticalLineAlignment = alignment;
1728 Toolkit::DevelText::EllipsisPosition::Type Controller::GetEllipsisPosition() const
1730 return mImpl->mModel->GetEllipsisPosition();
1733 void Controller::SetEllipsisPosition(Toolkit::DevelText::EllipsisPosition::Type ellipsisPosition)
1735 mImpl->mModel->mEllipsisPosition = ellipsisPosition;
1736 mImpl->mModel->mVisualModel->SetEllipsisPosition(ellipsisPosition);
1739 // public : Relayout.
1741 Controller::UpdateTextType Controller::Relayout(const Size& size, Dali::LayoutDirection::Type layoutDirection)
1743 return Relayouter::Relayout(*this, size, layoutDirection);
1746 void Controller::RequestRelayout()
1748 mImpl->RequestRelayout();
1751 // public : Input style change signals.
1753 bool Controller::IsInputStyleChangedSignalsQueueEmpty()
1755 return (NULL == mImpl->mEventData) || (0u == mImpl->mEventData->mInputStyleChangedQueue.Count());
1758 void Controller::ProcessInputStyleChangedSignals()
1760 if(NULL == mImpl->mEventData)
1766 for(Vector<InputStyle::Mask>::ConstIterator it = mImpl->mEventData->mInputStyleChangedQueue.Begin(),
1767 endIt = mImpl->mEventData->mInputStyleChangedQueue.End();
1771 const InputStyle::Mask mask = *it;
1773 if(NULL != mImpl->mEditableControlInterface)
1775 // Emit the input style changed signal.
1776 mImpl->mEditableControlInterface->InputStyleChanged(mask);
1780 mImpl->mEventData->mInputStyleChangedQueue.Clear();
1783 // public : Text-input Event Queuing.
1785 void Controller::KeyboardFocusGainEvent()
1787 EventHandler::KeyboardFocusGainEvent(*this);
1790 void Controller::KeyboardFocusLostEvent()
1792 EventHandler::KeyboardFocusLostEvent(*this);
1795 bool Controller::KeyEvent(const Dali::KeyEvent& keyEvent)
1797 return EventHandler::KeyEvent(*this, keyEvent);
1800 void Controller::AnchorEvent(float x, float y)
1802 EventHandler::AnchorEvent(*this, x, y);
1805 void Controller::TapEvent(unsigned int tapCount, float x, float y)
1807 EventHandler::TapEvent(*this, tapCount, x, y);
1810 void Controller::PanEvent(GestureState state, const Vector2& displacement)
1812 EventHandler::PanEvent(*this, state, displacement);
1815 void Controller::LongPressEvent(GestureState state, float x, float y)
1817 EventHandler::LongPressEvent(*this, state, x, y);
1820 void Controller::SelectEvent(float x, float y, SelectionType selectType)
1822 EventHandler::SelectEvent(*this, x, y, selectType);
1825 void Controller::SelectEvent(const uint32_t start, const uint32_t end, SelectionType selectType)
1827 EventHandler::SelectEvent(*this, start, end, selectType);
1830 void Controller::SetTextSelectionRange(const uint32_t* start, const uint32_t* end)
1832 if(mImpl->mEventData)
1834 mImpl->mEventData->mCheckScrollAmount = true;
1835 mImpl->mEventData->mIsLeftHandleSelected = true;
1836 mImpl->mEventData->mIsRightHandleSelected = true;
1837 mImpl->SetTextSelectionRange(start, end);
1838 mImpl->RequestRelayout();
1839 KeyboardFocusGainEvent();
1843 Uint32Pair Controller::GetTextSelectionRange() const
1845 return mImpl->GetTextSelectionRange();
1848 CharacterIndex Controller::GetPrimaryCursorPosition() const
1850 return mImpl->GetPrimaryCursorPosition();
1853 bool Controller::SetPrimaryCursorPosition(CharacterIndex index, bool focused)
1855 if(mImpl->mEventData)
1857 mImpl->mEventData->mCheckScrollAmount = true;
1858 mImpl->mEventData->mIsLeftHandleSelected = true;
1859 mImpl->mEventData->mIsRightHandleSelected = true;
1860 mImpl->mEventData->mCheckScrollAmount = true;
1861 if(mImpl->SetPrimaryCursorPosition(index, focused) && focused)
1863 KeyboardFocusGainEvent();
1870 void Controller::SelectWholeText()
1872 SelectEvent(0.f, 0.f, SelectionType::ALL);
1875 void Controller::SelectNone()
1877 SelectEvent(0.f, 0.f, SelectionType::NONE);
1880 void Controller::SelectText(const uint32_t start, const uint32_t end)
1882 SelectEvent(start, end, SelectionType::RANGE);
1885 string Controller::GetSelectedText() const
1888 if(EventData::SELECTING == mImpl->mEventData->mState)
1890 mImpl->RetrieveSelection(text, false);
1895 InputMethodContext::CallbackData Controller::OnInputMethodContextEvent(InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent)
1897 return EventHandler::OnInputMethodContextEvent(*this, inputMethodContext, inputMethodContextEvent);
1900 void Controller::PasteClipboardItemEvent()
1902 EventHandler::PasteClipboardItemEvent(*this);
1905 // protected : Inherit from Text::Decorator::ControllerInterface.
1907 void Controller::GetTargetSize(Vector2& targetSize)
1909 targetSize = mImpl->mModel->mVisualModel->mControlSize;
1912 void Controller::AddDecoration(Actor& actor, bool needsClipping)
1914 if(NULL != mImpl->mEditableControlInterface)
1916 mImpl->mEditableControlInterface->AddDecoration(actor, needsClipping);
1920 bool Controller::IsEditable() const
1922 return mImpl->IsEditable();
1925 void Controller::SetEditable(bool editable)
1927 mImpl->SetEditable(editable);
1928 if(mImpl->mEventData && mImpl->mEventData->mDecorator)
1930 mImpl->mEventData->mDecorator->SetEditable(editable);
1934 void Controller::ScrollBy(Vector2 scroll)
1936 if(mImpl->mEventData && (fabs(scroll.x) > Math::MACHINE_EPSILON_0 || fabs(scroll.y) > Math::MACHINE_EPSILON_0))
1938 const Vector2& layoutSize = mImpl->mModel->mVisualModel->GetLayoutSize();
1939 const Vector2 currentScroll = mImpl->mModel->mScrollPosition;
1941 scroll.x = -scroll.x;
1942 scroll.y = -scroll.y;
1944 if(fabs(scroll.x) > Math::MACHINE_EPSILON_0)
1946 mImpl->mModel->mScrollPosition.x += scroll.x;
1947 mImpl->ClampHorizontalScroll(layoutSize);
1950 if(fabs(scroll.y) > Math::MACHINE_EPSILON_0)
1952 mImpl->mModel->mScrollPosition.y += scroll.y;
1953 mImpl->ClampVerticalScroll(layoutSize);
1956 if(mImpl->mModel->mScrollPosition != currentScroll)
1958 mImpl->mEventData->mDecorator->UpdatePositions(mImpl->mModel->mScrollPosition - currentScroll);
1959 mImpl->RequestRelayout();
1964 float Controller::GetHorizontalScrollPosition()
1966 if(mImpl->mEventData)
1968 //scroll values are negative internally so we convert them to positive numbers
1969 return -mImpl->mModel->mScrollPosition.x;
1974 float Controller::GetVerticalScrollPosition()
1976 if(mImpl->mEventData)
1978 //scroll values are negative internally so we convert them to positive numbers
1979 return -mImpl->mModel->mScrollPosition.y;
1984 void Controller::DecorationEvent(HandleType handleType, HandleState state, float x, float y)
1986 EventHandler::DecorationEvent(*this, handleType, state, x, y);
1989 // protected : Inherit from TextSelectionPopup::TextPopupButtonCallbackInterface.
1991 void Controller::TextPopupButtonTouched(Dali::Toolkit::TextSelectionPopup::Buttons button)
1993 EventHandler::TextPopupButtonTouched(*this, button);
1996 void Controller::DisplayTimeExpired()
1998 mImpl->mEventData->mUpdateCursorPosition = true;
1999 // Apply modifications to the model
2000 mImpl->mOperationsPending = ALL_OPERATIONS;
2002 mImpl->RequestRelayout();
2005 // private : Update.
2007 void Controller::InsertText(const std::string& text, Controller::InsertType type)
2009 TextUpdater::InsertText(*this, text, type);
2012 void Controller::PasteText(const std::string& stringToPaste)
2014 TextUpdater::PasteText(*this, stringToPaste);
2017 bool Controller::RemoveText(int cursorOffset,
2018 int numberOfCharacters,
2019 UpdateInputStyleType type)
2021 return TextUpdater::RemoveText(*this, cursorOffset, numberOfCharacters, type);
2024 bool Controller::RemoveSelectedText()
2026 return TextUpdater::RemoveSelectedText(*this);
2029 void Controller::InsertTextAnchor(int numberOfCharacters,
2030 CharacterIndex previousCursorIndex)
2032 TextUpdater::InsertTextAnchor(*this, numberOfCharacters, previousCursorIndex);
2035 void Controller::RemoveTextAnchor(int cursorOffset,
2036 int numberOfCharacters,
2037 CharacterIndex previousCursorIndex)
2039 TextUpdater::RemoveTextAnchor(*this, cursorOffset, numberOfCharacters, previousCursorIndex);
2042 // private : Relayout.
2044 bool Controller::DoRelayout(const Size& size,
2045 OperationsMask operationsRequired,
2048 return Relayouter::DoRelayout(*this, size, operationsRequired, layoutSize);
2051 void Controller::CalculateVerticalOffset(const Size& controlSize)
2053 Relayouter::CalculateVerticalOffset(*this, controlSize);
2056 // private : Events.
2058 void Controller::ProcessModifyEvents()
2060 EventHandler::ProcessModifyEvents(*this);
2063 void Controller::TextReplacedEvent()
2065 EventHandler::TextReplacedEvent(*this);
2068 void Controller::TextInsertedEvent()
2070 EventHandler::TextInsertedEvent(*this);
2073 void Controller::TextDeletedEvent()
2075 EventHandler::TextDeletedEvent(*this);
2078 bool Controller::DeleteEvent(int keyCode)
2080 return EventHandler::DeleteEvent(*this, keyCode);
2083 // private : Helpers.
2085 void Controller::ResetText()
2087 TextUpdater::ResetText(*this);
2090 void Controller::ShowPlaceholderText()
2092 PlaceholderHandler::ShowPlaceholderText(*this);
2095 void Controller::ClearFontData()
2097 if(mImpl->mFontDefaults)
2099 mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
2102 // Set flags to update the model.
2103 mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
2104 mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
2105 mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mModel->mLogicalModel->mText.Count();
2107 mImpl->mTextUpdateInfo.mClearAll = true;
2108 mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
2109 mImpl->mRecalculateNaturalSize = true;
2111 mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
2117 UPDATE_LAYOUT_SIZE |
2122 void Controller::ClearStyleData()
2124 mImpl->mModel->mLogicalModel->mColorRuns.Clear();
2125 mImpl->mModel->mLogicalModel->ClearFontDescriptionRuns();
2128 void Controller::ResetCursorPosition(CharacterIndex cursorIndex)
2130 // Reset the cursor position
2131 if(NULL != mImpl->mEventData)
2133 mImpl->mEventData->mPrimaryCursorPosition = cursorIndex;
2135 // Update the cursor if it's in editing mode.
2136 if(EventData::IsEditingState(mImpl->mEventData->mState))
2138 mImpl->mEventData->mUpdateCursorPosition = true;
2143 CharacterIndex Controller::GetCursorPosition()
2145 if(!mImpl->mEventData)
2148 return mImpl->mEventData->mPrimaryCursorPosition;
2151 void Controller::ResetScrollPosition()
2153 if(NULL != mImpl->mEventData)
2155 // Reset the scroll position.
2156 mImpl->mModel->mScrollPosition = Vector2::ZERO;
2157 mImpl->mEventData->mScrollAfterUpdatePosition = true;
2161 void Controller::SetControlInterface(ControlInterface* controlInterface)
2163 mImpl->mControlInterface = controlInterface;
2166 void Controller::SetAnchorControlInterface(AnchorControlInterface* anchorControlInterface)
2168 mImpl->mAnchorControlInterface = anchorControlInterface;
2171 bool Controller::ShouldClearFocusOnEscape() const
2173 return mImpl->mShouldClearFocusOnEscape;
2176 Actor Controller::CreateBackgroundActor()
2178 return mImpl->CreateBackgroundActor();
2181 // private : Private contructors & copy operator.
2183 Controller::Controller()
2184 : Controller(nullptr, nullptr, nullptr, nullptr)
2188 Controller::Controller(ControlInterface* controlInterface)
2189 : Controller(controlInterface, nullptr, nullptr, nullptr)
2193 Controller::Controller(ControlInterface* controlInterface,
2194 EditableControlInterface* editableControlInterface,
2195 SelectableControlInterface* selectableControlInterface,
2196 AnchorControlInterface* anchorControlInterface)
2197 : mImpl(new Controller::Impl(controlInterface, editableControlInterface, selectableControlInterface, anchorControlInterface))
2201 // The copy constructor and operator are left unimplemented.
2203 // protected : Destructor.
2205 Controller::~Controller()
2212 } // namespace Toolkit