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 void Controller::RelayoutForNewLineSize()
1224 // relayout all characters
1225 mImpl->mTextUpdateInfo.mCharacterIndex = 0;
1226 mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
1227 mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mModel->mLogicalModel->mText.Count();
1228 mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | LAYOUT);
1231 if((mImpl->mEventData != nullptr) && (mImpl->mEventData->mState == EventData::SELECTING))
1233 mImpl->ChangeState(EventData::EDITING);
1236 mImpl->RequestRelayout();
1239 bool Controller::SetDefaultLineSpacing(float lineSpacing)
1241 if(std::fabs(lineSpacing - mImpl->mLayoutEngine.GetDefaultLineSpacing()) > Math::MACHINE_EPSILON_1000)
1243 mImpl->mLayoutEngine.SetDefaultLineSpacing(lineSpacing);
1244 mImpl->mRecalculateNaturalSize = true;
1246 RelayoutForNewLineSize();
1252 float Controller::GetDefaultLineSpacing() const
1254 return mImpl->mLayoutEngine.GetDefaultLineSpacing();
1257 bool Controller::SetDefaultLineSize(float lineSize)
1259 if(std::fabs(lineSize - mImpl->mLayoutEngine.GetDefaultLineSize()) > Math::MACHINE_EPSILON_1000)
1261 mImpl->mLayoutEngine.SetDefaultLineSize(lineSize);
1262 mImpl->mRecalculateNaturalSize = true;
1264 RelayoutForNewLineSize();
1270 float Controller::GetDefaultLineSize() const
1272 return mImpl->mLayoutEngine.GetDefaultLineSize();
1275 void Controller::SetInputColor(const Vector4& color)
1277 if(NULL != mImpl->mEventData)
1279 mImpl->mEventData->mInputStyle.textColor = color;
1280 mImpl->mEventData->mInputStyle.isDefaultColor = false;
1282 if(EventData::SELECTING == mImpl->mEventData->mState || EventData::EDITING == mImpl->mEventData->mState || EventData::INACTIVE == mImpl->mEventData->mState)
1284 if(EventData::SELECTING == mImpl->mEventData->mState)
1286 const bool handlesCrossed = mImpl->mEventData->mLeftSelectionPosition > mImpl->mEventData->mRightSelectionPosition;
1288 // Get start and end position of selection
1289 const CharacterIndex startOfSelectedText = handlesCrossed ? mImpl->mEventData->mRightSelectionPosition : mImpl->mEventData->mLeftSelectionPosition;
1290 const Length lengthOfSelectedText = (handlesCrossed ? mImpl->mEventData->mLeftSelectionPosition : mImpl->mEventData->mRightSelectionPosition) - startOfSelectedText;
1292 // Add the color run.
1293 const VectorBase::SizeType numberOfRuns = mImpl->mModel->mLogicalModel->mColorRuns.Count();
1294 mImpl->mModel->mLogicalModel->mColorRuns.Resize(numberOfRuns + 1u);
1296 ColorRun& colorRun = *(mImpl->mModel->mLogicalModel->mColorRuns.Begin() + numberOfRuns);
1297 colorRun.color = color;
1298 colorRun.characterRun.characterIndex = startOfSelectedText;
1299 colorRun.characterRun.numberOfCharacters = lengthOfSelectedText;
1301 mImpl->mTextUpdateInfo.mCharacterIndex = startOfSelectedText;
1302 mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
1303 mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = lengthOfSelectedText;
1307 mImpl->mTextUpdateInfo.mCharacterIndex = 0;
1308 mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
1309 mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mModel->mLogicalModel->mText.Count();
1312 // Request to relayout.
1313 mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | COLOR);
1314 mImpl->RequestRelayout();
1319 const Vector4& Controller::GetInputColor() const
1321 if(NULL != mImpl->mEventData)
1323 return mImpl->mEventData->mInputStyle.textColor;
1326 // Return the default text's color if there is no EventData.
1327 return mImpl->mTextColor;
1330 void Controller::SetInputFontFamily(const std::string& fontFamily)
1332 InputFontHandler::SetInputFontFamily(*this, fontFamily);
1335 const std::string& Controller::GetInputFontFamily() const
1337 return InputFontHandler::GetInputFontFamily(*this);
1340 void Controller::SetInputFontWeight(FontWeight weight)
1342 InputFontHandler::SetInputFontWeight(*this, weight);
1345 bool Controller::IsInputFontWeightDefined() const
1347 return InputFontHandler::IsInputFontWeightDefined(*this);
1350 FontWeight Controller::GetInputFontWeight() const
1352 return InputFontHandler::GetInputFontWeight(*this);
1355 void Controller::SetInputFontWidth(FontWidth width)
1357 InputFontHandler::SetInputFontWidth(*this, width);
1360 bool Controller::IsInputFontWidthDefined() const
1362 return InputFontHandler::IsInputFontWidthDefined(*this);
1365 FontWidth Controller::GetInputFontWidth() const
1367 return InputFontHandler::GetInputFontWidth(*this);
1370 void Controller::SetInputFontSlant(FontSlant slant)
1372 InputFontHandler::SetInputFontSlant(*this, slant);
1375 bool Controller::IsInputFontSlantDefined() const
1377 return InputFontHandler::IsInputFontSlantDefined(*this);
1380 FontSlant Controller::GetInputFontSlant() const
1382 return InputFontHandler::GetInputFontSlant(*this);
1385 void Controller::SetInputFontPointSize(float size)
1387 InputFontHandler::SetInputFontPointSize(*this, size);
1390 float Controller::GetInputFontPointSize() const
1392 return InputFontHandler::GetInputFontPointSize(*this);
1395 void Controller::SetInputLineSpacing(float lineSpacing)
1397 if(NULL != mImpl->mEventData)
1399 mImpl->mEventData->mInputStyle.lineSpacing = lineSpacing;
1400 mImpl->mEventData->mInputStyle.isLineSpacingDefined = true;
1404 float Controller::GetInputLineSpacing() const
1406 if(NULL != mImpl->mEventData)
1408 return mImpl->mEventData->mInputStyle.lineSpacing;
1414 void Controller::SetInputShadowProperties(const std::string& shadowProperties)
1416 if(NULL != mImpl->mEventData)
1418 mImpl->mEventData->mInputStyle.shadowProperties = shadowProperties;
1422 const std::string& Controller::GetInputShadowProperties() const
1424 if(NULL != mImpl->mEventData)
1426 return mImpl->mEventData->mInputStyle.shadowProperties;
1429 return EMPTY_STRING;
1432 void Controller::SetInputUnderlineProperties(const std::string& underlineProperties)
1434 if(NULL != mImpl->mEventData)
1436 mImpl->mEventData->mInputStyle.underlineProperties = underlineProperties;
1440 const std::string& Controller::GetInputUnderlineProperties() const
1442 if(NULL != mImpl->mEventData)
1444 return mImpl->mEventData->mInputStyle.underlineProperties;
1447 return EMPTY_STRING;
1450 void Controller::SetInputEmbossProperties(const std::string& embossProperties)
1452 if(NULL != mImpl->mEventData)
1454 mImpl->mEventData->mInputStyle.embossProperties = embossProperties;
1458 const std::string& Controller::GetInputEmbossProperties() const
1460 if(NULL != mImpl->mEventData)
1462 return mImpl->mEventData->mInputStyle.embossProperties;
1465 return GetDefaultEmbossProperties();
1468 void Controller::SetInputOutlineProperties(const std::string& outlineProperties)
1470 if(NULL != mImpl->mEventData)
1472 mImpl->mEventData->mInputStyle.outlineProperties = outlineProperties;
1476 const std::string& Controller::GetInputOutlineProperties() const
1478 if(NULL != mImpl->mEventData)
1480 return mImpl->mEventData->mInputStyle.outlineProperties;
1483 return GetDefaultOutlineProperties();
1486 void Controller::SetInputModePassword(bool passwordInput)
1488 if(NULL != mImpl->mEventData)
1490 mImpl->mEventData->mPasswordInput = passwordInput;
1494 bool Controller::IsInputModePassword()
1496 if(NULL != mImpl->mEventData)
1498 return mImpl->mEventData->mPasswordInput;
1503 void Controller::SetNoTextDoubleTapAction(NoTextTap::Action action)
1505 if(NULL != mImpl->mEventData)
1507 mImpl->mEventData->mDoubleTapAction = action;
1511 Controller::NoTextTap::Action Controller::GetNoTextDoubleTapAction() const
1513 NoTextTap::Action action = NoTextTap::NO_ACTION;
1515 if(NULL != mImpl->mEventData)
1517 action = mImpl->mEventData->mDoubleTapAction;
1523 void Controller::SetNoTextLongPressAction(NoTextTap::Action action)
1525 if(NULL != mImpl->mEventData)
1527 mImpl->mEventData->mLongPressAction = action;
1531 Controller::NoTextTap::Action Controller::GetNoTextLongPressAction() const
1533 NoTextTap::Action action = NoTextTap::NO_ACTION;
1535 if(NULL != mImpl->mEventData)
1537 action = mImpl->mEventData->mLongPressAction;
1543 bool Controller::IsUnderlineSetByString()
1545 return mImpl->mUnderlineSetByString;
1548 void Controller::UnderlineSetByString(bool setByString)
1550 mImpl->mUnderlineSetByString = setByString;
1553 bool Controller::IsShadowSetByString()
1555 return mImpl->mShadowSetByString;
1558 void Controller::ShadowSetByString(bool setByString)
1560 mImpl->mShadowSetByString = setByString;
1563 bool Controller::IsOutlineSetByString()
1565 return mImpl->mOutlineSetByString;
1568 void Controller::OutlineSetByString(bool setByString)
1570 mImpl->mOutlineSetByString = setByString;
1573 bool Controller::IsFontStyleSetByString()
1575 return mImpl->mFontStyleSetByString;
1578 void Controller::FontStyleSetByString(bool setByString)
1580 mImpl->mFontStyleSetByString = setByString;
1583 // public : Queries & retrieves.
1585 Layout::Engine& Controller::GetLayoutEngine()
1587 return mImpl->mLayoutEngine;
1590 View& Controller::GetView()
1592 return mImpl->mView;
1595 Vector3 Controller::GetNaturalSize()
1597 return Relayouter::GetNaturalSize(*this);
1600 bool Controller::CheckForTextFit(float pointSize, Size& layoutSize)
1602 return Relayouter::CheckForTextFit(*this, pointSize, layoutSize);
1605 void Controller::FitPointSizeforLayout(Size layoutSize)
1607 Relayouter::FitPointSizeforLayout(*this, layoutSize);
1610 float Controller::GetHeightForWidth(float width)
1612 return Relayouter::GetHeightForWidth(*this, width);
1615 int Controller::GetLineCount(float width)
1617 GetHeightForWidth(width);
1618 int numberofLines = mImpl->mModel->GetNumberOfLines();
1619 return numberofLines;
1622 const ModelInterface* const Controller::GetTextModel() const
1624 return mImpl->mModel.Get();
1627 float Controller::GetScrollAmountByUserInput()
1629 float scrollAmount = 0.0f;
1631 if(NULL != mImpl->mEventData && mImpl->mEventData->mCheckScrollAmount)
1633 scrollAmount = mImpl->mModel->mScrollPosition.y - mImpl->mModel->mScrollPositionLast.y;
1634 mImpl->mEventData->mCheckScrollAmount = false;
1636 return scrollAmount;
1639 bool Controller::GetTextScrollInfo(float& scrollPosition, float& controlHeight, float& layoutHeight)
1641 const Vector2& layout = mImpl->mModel->mVisualModel->GetLayoutSize();
1644 controlHeight = mImpl->mModel->mVisualModel->mControlSize.height;
1645 layoutHeight = layout.height;
1646 scrollPosition = mImpl->mModel->mScrollPosition.y;
1647 isScrolled = !Equals(mImpl->mModel->mScrollPosition.y, mImpl->mModel->mScrollPositionLast.y, Math::MACHINE_EPSILON_1);
1651 void Controller::SetHiddenInputOption(const Property::Map& options)
1653 if(NULL == mImpl->mHiddenInput)
1655 mImpl->mHiddenInput = new HiddenText(this);
1657 mImpl->mHiddenInput->SetProperties(options);
1660 void Controller::GetHiddenInputOption(Property::Map& options)
1662 if(NULL != mImpl->mHiddenInput)
1664 mImpl->mHiddenInput->GetProperties(options);
1668 void Controller::SetInputFilterOption(const Property::Map& options)
1670 if(!mImpl->mInputFilter)
1672 mImpl->mInputFilter = std::unique_ptr<InputFilter>(new InputFilter());
1674 mImpl->mInputFilter->SetProperties(options);
1677 void Controller::GetInputFilterOption(Property::Map& options)
1679 if(NULL != mImpl->mInputFilter)
1681 mImpl->mInputFilter->GetProperties(options);
1685 void Controller::SetPlaceholderProperty(const Property::Map& map)
1687 PlaceholderHandler::SetPlaceholderProperty(*this, map);
1690 void Controller::GetPlaceholderProperty(Property::Map& map)
1692 PlaceholderHandler::GetPlaceholderProperty(*this, map);
1695 Toolkit::DevelText::TextDirection::Type Controller::GetTextDirection()
1697 // Make sure the model is up-to-date before layouting
1698 ProcessModifyEvents();
1700 if(mImpl->mUpdateTextDirection)
1702 // Operations that can be done only once until the text changes.
1703 const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
1711 // Set the update info to relayout the whole text.
1712 mImpl->mTextUpdateInfo.mParagraphCharacterIndex = 0u;
1713 mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters = mImpl->mModel->mLogicalModel->mText.Count();
1715 // Make sure the model is up-to-date before layouting
1716 mImpl->UpdateModel(onlyOnceOperations);
1718 Vector3 naturalSize;
1719 DoRelayout(Size(MAX_FLOAT, MAX_FLOAT),
1720 static_cast<OperationsMask>(onlyOnceOperations |
1721 LAYOUT | REORDER | UPDATE_DIRECTION),
1722 naturalSize.GetVectorXY());
1724 // Do not do again the only once operations.
1725 mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending & ~onlyOnceOperations);
1727 // Clear the update info. This info will be set the next time the text is updated.
1728 mImpl->mTextUpdateInfo.Clear();
1730 // FullRelayoutNeeded should be true because DoRelayout is MAX_FLOAT, MAX_FLOAT.
1731 mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
1733 mImpl->mUpdateTextDirection = false;
1736 return mImpl->mIsTextDirectionRTL ? Toolkit::DevelText::TextDirection::RIGHT_TO_LEFT : Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT;
1739 Toolkit::DevelText::VerticalLineAlignment::Type Controller::GetVerticalLineAlignment() const
1741 return mImpl->mModel->GetVerticalLineAlignment();
1744 void Controller::SetVerticalLineAlignment(Toolkit::DevelText::VerticalLineAlignment::Type alignment)
1746 mImpl->mModel->mVerticalLineAlignment = alignment;
1749 Toolkit::DevelText::EllipsisPosition::Type Controller::GetEllipsisPosition() const
1751 return mImpl->mModel->GetEllipsisPosition();
1754 void Controller::SetEllipsisPosition(Toolkit::DevelText::EllipsisPosition::Type ellipsisPosition)
1756 mImpl->mModel->mEllipsisPosition = ellipsisPosition;
1757 mImpl->mModel->mVisualModel->SetEllipsisPosition(ellipsisPosition);
1760 // public : Relayout.
1762 Controller::UpdateTextType Controller::Relayout(const Size& size, Dali::LayoutDirection::Type layoutDirection)
1764 return Relayouter::Relayout(*this, size, layoutDirection);
1767 void Controller::RequestRelayout()
1769 mImpl->RequestRelayout();
1772 // public : Input style change signals.
1774 bool Controller::IsInputStyleChangedSignalsQueueEmpty()
1776 return (NULL == mImpl->mEventData) || (0u == mImpl->mEventData->mInputStyleChangedQueue.Count());
1779 void Controller::ProcessInputStyleChangedSignals()
1781 if(NULL == mImpl->mEventData)
1787 for(Vector<InputStyle::Mask>::ConstIterator it = mImpl->mEventData->mInputStyleChangedQueue.Begin(),
1788 endIt = mImpl->mEventData->mInputStyleChangedQueue.End();
1792 const InputStyle::Mask mask = *it;
1794 if(NULL != mImpl->mEditableControlInterface)
1796 // Emit the input style changed signal.
1797 mImpl->mEditableControlInterface->InputStyleChanged(mask);
1801 mImpl->mEventData->mInputStyleChangedQueue.Clear();
1804 // public : Text-input Event Queuing.
1806 void Controller::KeyboardFocusGainEvent()
1808 EventHandler::KeyboardFocusGainEvent(*this);
1811 void Controller::KeyboardFocusLostEvent()
1813 EventHandler::KeyboardFocusLostEvent(*this);
1816 bool Controller::KeyEvent(const Dali::KeyEvent& keyEvent)
1818 return EventHandler::KeyEvent(*this, keyEvent);
1821 void Controller::AnchorEvent(float x, float y)
1823 EventHandler::AnchorEvent(*this, x, y);
1826 void Controller::TapEvent(unsigned int tapCount, float x, float y)
1828 EventHandler::TapEvent(*this, tapCount, x, y);
1831 void Controller::PanEvent(GestureState state, const Vector2& displacement)
1833 EventHandler::PanEvent(*this, state, displacement);
1836 void Controller::LongPressEvent(GestureState state, float x, float y)
1838 EventHandler::LongPressEvent(*this, state, x, y);
1841 void Controller::SelectEvent(float x, float y, SelectionType selectType)
1843 EventHandler::SelectEvent(*this, x, y, selectType);
1846 void Controller::SelectEvent(const uint32_t start, const uint32_t end, SelectionType selectType)
1848 EventHandler::SelectEvent(*this, start, end, selectType);
1851 void Controller::SetTextSelectionRange(const uint32_t* start, const uint32_t* end)
1853 if(mImpl->mEventData)
1855 mImpl->mEventData->mCheckScrollAmount = true;
1856 mImpl->mEventData->mIsLeftHandleSelected = true;
1857 mImpl->mEventData->mIsRightHandleSelected = true;
1858 mImpl->SetTextSelectionRange(start, end);
1859 mImpl->RequestRelayout();
1860 KeyboardFocusGainEvent();
1864 Uint32Pair Controller::GetTextSelectionRange() const
1866 return mImpl->GetTextSelectionRange();
1869 CharacterIndex Controller::GetPrimaryCursorPosition() const
1871 return mImpl->GetPrimaryCursorPosition();
1874 bool Controller::SetPrimaryCursorPosition(CharacterIndex index, bool focused)
1876 if(mImpl->mEventData)
1878 mImpl->mEventData->mCheckScrollAmount = true;
1879 mImpl->mEventData->mIsLeftHandleSelected = true;
1880 mImpl->mEventData->mIsRightHandleSelected = true;
1881 mImpl->mEventData->mCheckScrollAmount = true;
1882 if(mImpl->SetPrimaryCursorPosition(index, focused) && focused)
1884 KeyboardFocusGainEvent();
1891 void Controller::SelectWholeText()
1893 SelectEvent(0.f, 0.f, SelectionType::ALL);
1896 void Controller::SelectNone()
1898 SelectEvent(0.f, 0.f, SelectionType::NONE);
1901 void Controller::SelectText(const uint32_t start, const uint32_t end)
1903 SelectEvent(start, end, SelectionType::RANGE);
1906 string Controller::GetSelectedText() const
1909 if(EventData::SELECTING == mImpl->mEventData->mState)
1911 mImpl->RetrieveSelection(text, false);
1916 InputMethodContext::CallbackData Controller::OnInputMethodContextEvent(InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent)
1918 return EventHandler::OnInputMethodContextEvent(*this, inputMethodContext, inputMethodContextEvent);
1921 void Controller::PasteClipboardItemEvent()
1923 EventHandler::PasteClipboardItemEvent(*this);
1926 // protected : Inherit from Text::Decorator::ControllerInterface.
1928 void Controller::GetTargetSize(Vector2& targetSize)
1930 targetSize = mImpl->mModel->mVisualModel->mControlSize;
1933 void Controller::AddDecoration(Actor& actor, bool needsClipping)
1935 if(NULL != mImpl->mEditableControlInterface)
1937 mImpl->mEditableControlInterface->AddDecoration(actor, needsClipping);
1941 bool Controller::IsEditable() const
1943 return mImpl->IsEditable();
1946 void Controller::SetEditable(bool editable)
1948 mImpl->SetEditable(editable);
1949 if(mImpl->mEventData && mImpl->mEventData->mDecorator)
1951 mImpl->mEventData->mDecorator->SetEditable(editable);
1955 void Controller::ScrollBy(Vector2 scroll)
1957 if(mImpl->mEventData && (fabs(scroll.x) > Math::MACHINE_EPSILON_0 || fabs(scroll.y) > Math::MACHINE_EPSILON_0))
1959 const Vector2& layoutSize = mImpl->mModel->mVisualModel->GetLayoutSize();
1960 const Vector2 currentScroll = mImpl->mModel->mScrollPosition;
1962 scroll.x = -scroll.x;
1963 scroll.y = -scroll.y;
1965 if(fabs(scroll.x) > Math::MACHINE_EPSILON_0)
1967 mImpl->mModel->mScrollPosition.x += scroll.x;
1968 mImpl->ClampHorizontalScroll(layoutSize);
1971 if(fabs(scroll.y) > Math::MACHINE_EPSILON_0)
1973 mImpl->mModel->mScrollPosition.y += scroll.y;
1974 mImpl->ClampVerticalScroll(layoutSize);
1977 if(mImpl->mModel->mScrollPosition != currentScroll)
1979 mImpl->mEventData->mDecorator->UpdatePositions(mImpl->mModel->mScrollPosition - currentScroll);
1980 mImpl->RequestRelayout();
1985 float Controller::GetHorizontalScrollPosition()
1987 if(mImpl->mEventData)
1989 //scroll values are negative internally so we convert them to positive numbers
1990 return -mImpl->mModel->mScrollPosition.x;
1995 float Controller::GetVerticalScrollPosition()
1997 if(mImpl->mEventData)
1999 //scroll values are negative internally so we convert them to positive numbers
2000 return -mImpl->mModel->mScrollPosition.y;
2005 void Controller::DecorationEvent(HandleType handleType, HandleState state, float x, float y)
2007 EventHandler::DecorationEvent(*this, handleType, state, x, y);
2010 // protected : Inherit from TextSelectionPopup::TextPopupButtonCallbackInterface.
2012 void Controller::TextPopupButtonTouched(Dali::Toolkit::TextSelectionPopup::Buttons button)
2014 EventHandler::TextPopupButtonTouched(*this, button);
2017 void Controller::DisplayTimeExpired()
2019 mImpl->mEventData->mUpdateCursorPosition = true;
2020 // Apply modifications to the model
2021 mImpl->mOperationsPending = ALL_OPERATIONS;
2023 mImpl->RequestRelayout();
2026 // private : Update.
2028 void Controller::InsertText(const std::string& text, Controller::InsertType type)
2030 TextUpdater::InsertText(*this, text, type);
2033 void Controller::PasteText(const std::string& stringToPaste)
2035 TextUpdater::PasteText(*this, stringToPaste);
2038 bool Controller::RemoveText(int cursorOffset,
2039 int numberOfCharacters,
2040 UpdateInputStyleType type)
2042 return TextUpdater::RemoveText(*this, cursorOffset, numberOfCharacters, type);
2045 bool Controller::RemoveSelectedText()
2047 return TextUpdater::RemoveSelectedText(*this);
2050 void Controller::InsertTextAnchor(int numberOfCharacters,
2051 CharacterIndex previousCursorIndex)
2053 TextUpdater::InsertTextAnchor(*this, numberOfCharacters, previousCursorIndex);
2056 void Controller::RemoveTextAnchor(int cursorOffset,
2057 int numberOfCharacters,
2058 CharacterIndex previousCursorIndex)
2060 TextUpdater::RemoveTextAnchor(*this, cursorOffset, numberOfCharacters, previousCursorIndex);
2063 // private : Relayout.
2065 bool Controller::DoRelayout(const Size& size,
2066 OperationsMask operationsRequired,
2069 return Relayouter::DoRelayout(*this, size, operationsRequired, layoutSize);
2072 void Controller::CalculateVerticalOffset(const Size& controlSize)
2074 Relayouter::CalculateVerticalOffset(*this, controlSize);
2077 // private : Events.
2079 void Controller::ProcessModifyEvents()
2081 EventHandler::ProcessModifyEvents(*this);
2084 void Controller::TextReplacedEvent()
2086 EventHandler::TextReplacedEvent(*this);
2089 void Controller::TextInsertedEvent()
2091 EventHandler::TextInsertedEvent(*this);
2094 void Controller::TextDeletedEvent()
2096 EventHandler::TextDeletedEvent(*this);
2099 bool Controller::DeleteEvent(int keyCode)
2101 return EventHandler::DeleteEvent(*this, keyCode);
2104 // private : Helpers.
2106 void Controller::ResetText()
2108 TextUpdater::ResetText(*this);
2111 void Controller::ShowPlaceholderText()
2113 PlaceholderHandler::ShowPlaceholderText(*this);
2116 void Controller::ClearFontData()
2118 if(mImpl->mFontDefaults)
2120 mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
2123 // Set flags to update the model.
2124 mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
2125 mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
2126 mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mModel->mLogicalModel->mText.Count();
2128 mImpl->mTextUpdateInfo.mClearAll = true;
2129 mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
2130 mImpl->mRecalculateNaturalSize = true;
2132 mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
2138 UPDATE_LAYOUT_SIZE |
2143 void Controller::ClearStyleData()
2145 mImpl->mModel->mLogicalModel->mColorRuns.Clear();
2146 mImpl->mModel->mLogicalModel->ClearFontDescriptionRuns();
2149 void Controller::ResetCursorPosition(CharacterIndex cursorIndex)
2151 // Reset the cursor position
2152 if(NULL != mImpl->mEventData)
2154 mImpl->mEventData->mPrimaryCursorPosition = cursorIndex;
2156 // Update the cursor if it's in editing mode.
2157 if(EventData::IsEditingState(mImpl->mEventData->mState))
2159 mImpl->mEventData->mUpdateCursorPosition = true;
2164 CharacterIndex Controller::GetCursorPosition()
2166 if(!mImpl->mEventData)
2169 return mImpl->mEventData->mPrimaryCursorPosition;
2172 void Controller::ResetScrollPosition()
2174 if(NULL != mImpl->mEventData)
2176 // Reset the scroll position.
2177 mImpl->mModel->mScrollPosition = Vector2::ZERO;
2178 mImpl->mEventData->mScrollAfterUpdatePosition = true;
2182 void Controller::SetControlInterface(ControlInterface* controlInterface)
2184 mImpl->mControlInterface = controlInterface;
2187 void Controller::SetAnchorControlInterface(AnchorControlInterface* anchorControlInterface)
2189 mImpl->mAnchorControlInterface = anchorControlInterface;
2192 bool Controller::ShouldClearFocusOnEscape() const
2194 return mImpl->mShouldClearFocusOnEscape;
2197 Actor Controller::CreateBackgroundActor()
2199 return mImpl->CreateBackgroundActor();
2202 // private : Private contructors & copy operator.
2204 Controller::Controller()
2205 : Controller(nullptr, nullptr, nullptr, nullptr)
2209 Controller::Controller(ControlInterface* controlInterface)
2210 : Controller(controlInterface, nullptr, nullptr, nullptr)
2214 Controller::Controller(ControlInterface* controlInterface,
2215 EditableControlInterface* editableControlInterface,
2216 SelectableControlInterface* selectableControlInterface,
2217 AnchorControlInterface* anchorControlInterface)
2218 : mImpl(new Controller::Impl(controlInterface, editableControlInterface, selectableControlInterface, anchorControlInterface))
2222 // The copy constructor and operator are left unimplemented.
2224 // protected : Destructor.
2226 Controller::~Controller()
2233 } // namespace Toolkit