Merge "Add some APIs into web context." into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-controller.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali-toolkit/internal/text/text-controller.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <memory.h>
24 #include <cmath>
25 #include <limits>
26
27 // INTERNAL INCLUDES
28 #include <dali-toolkit/internal/text/text-controller-event-handler.h>
29 #include <dali-toolkit/internal/text/text-controller-impl.h>
30 #include <dali-toolkit/internal/text/text-controller-input-font-handler.h>
31 #include <dali-toolkit/internal/text/text-controller-placeholder-handler.h>
32 #include <dali-toolkit/internal/text/text-controller-relayouter.h>
33 #include <dali-toolkit/internal/text/text-controller-text-updater.h>
34 #include <dali-toolkit/internal/text/text-editable-control-interface.h>
35
36 namespace
37 {
38 #if defined(DEBUG_ENABLED)
39 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
40 #endif
41
42 constexpr float MAX_FLOAT = std::numeric_limits<float>::max();
43
44 const std::string EMPTY_STRING("");
45
46 int ConvertPixelToPint(float pixel)
47 {
48   unsigned int                      horizontalDpi = 0u;
49   unsigned int                      verticalDpi   = 0u;
50   Dali::TextAbstraction::FontClient fontClient    = Dali::TextAbstraction::FontClient::Get();
51   fontClient.GetDpi(horizontalDpi, verticalDpi);
52
53   return (pixel * 72.f) / static_cast<float>(horizontalDpi);
54 }
55
56 } // namespace
57
58 namespace Dali
59 {
60 namespace Toolkit
61 {
62 namespace Text
63 {
64 // public : Constructor.
65
66 ControllerPtr Controller::New()
67 {
68   return ControllerPtr(new Controller());
69 }
70
71 ControllerPtr Controller::New(ControlInterface* controlInterface)
72 {
73   return ControllerPtr(new Controller(controlInterface));
74 }
75
76 ControllerPtr Controller::New(ControlInterface*           controlInterface,
77                               EditableControlInterface*   editableControlInterface,
78                               SelectableControlInterface* selectableControlInterface,
79                               AnchorControlInterface*     anchorControlInterface)
80 {
81   return ControllerPtr(new Controller(controlInterface,
82                                       editableControlInterface,
83                                       selectableControlInterface,
84                                       anchorControlInterface));
85 }
86
87 // public : Configure the text controller.
88
89 void Controller::EnableTextInput(DecoratorPtr decorator, InputMethodContext& inputMethodContext)
90 {
91   if(!decorator)
92   {
93     delete mImpl->mEventData;
94     mImpl->mEventData = NULL;
95
96     // Nothing else to do.
97     return;
98   }
99
100   if(NULL == mImpl->mEventData)
101   {
102     mImpl->mEventData = new EventData(decorator, inputMethodContext);
103   }
104 }
105
106 void Controller::SetGlyphType(TextAbstraction::GlyphType glyphType)
107 {
108   // Metrics for bitmap & vector based glyphs are different
109   mImpl->mMetrics->SetGlyphType(glyphType);
110
111   // Clear the font-specific data
112   ClearFontData();
113
114   mImpl->RequestRelayout();
115 }
116
117 void Controller::SetMarkupProcessorEnabled(bool enable)
118 {
119   if(enable != mImpl->mMarkupProcessorEnabled)
120   {
121     //If Text was already set, call the SetText again for enabling or disabling markup
122     mImpl->mMarkupProcessorEnabled = enable;
123     std::string text;
124     GetText(text);
125     SetText(text);
126   }
127 }
128
129 bool Controller::IsMarkupProcessorEnabled() const
130 {
131   return mImpl->mMarkupProcessorEnabled;
132 }
133
134 void Controller::SetAutoScrollEnabled(bool enable)
135 {
136   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);
137
138   if(mImpl->mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX)
139   {
140     if(enable)
141     {
142       DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled for SINGLE_LINE_BOX\n");
143       mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
144                                                               LAYOUT |
145                                                               ALIGN |
146                                                               UPDATE_LAYOUT_SIZE |
147                                                               UPDATE_DIRECTION |
148                                                               REORDER);
149     }
150     else
151     {
152       DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled Disabling autoscroll\n");
153       mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
154                                                               LAYOUT |
155                                                               ALIGN |
156                                                               UPDATE_LAYOUT_SIZE |
157                                                               REORDER);
158     }
159
160     mImpl->mIsAutoScrollEnabled = enable;
161     mImpl->RequestRelayout();
162   }
163   else
164   {
165     DALI_LOG_WARNING("Attempted AutoScrolling on a non SINGLE_LINE_BOX, request ignored\n");
166     mImpl->mIsAutoScrollEnabled = false;
167   }
168 }
169
170 bool Controller::IsAutoScrollEnabled() const
171 {
172   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::IsAutoScrollEnabled[%s]\n", mImpl->mIsAutoScrollEnabled ? "true" : "false");
173
174   return mImpl->mIsAutoScrollEnabled;
175 }
176
177 CharacterDirection Controller::GetAutoScrollDirection() const
178 {
179   return mImpl->mIsTextDirectionRTL;
180 }
181
182 float Controller::GetAutoScrollLineAlignment() const
183 {
184   float offset = 0.f;
185
186   if(mImpl->mModel->mVisualModel &&
187      (0u != mImpl->mModel->mVisualModel->mLines.Count()))
188   {
189     offset = (*mImpl->mModel->mVisualModel->mLines.Begin()).alignmentOffset;
190   }
191
192   return offset;
193 }
194
195 void Controller::SetHorizontalScrollEnabled(bool enable)
196 {
197   if((NULL != mImpl->mEventData) &&
198      mImpl->mEventData->mDecorator)
199   {
200     mImpl->mEventData->mDecorator->SetHorizontalScrollEnabled(enable);
201   }
202 }
203 bool Controller::IsHorizontalScrollEnabled() const
204 {
205   if((NULL != mImpl->mEventData) &&
206      mImpl->mEventData->mDecorator)
207   {
208     return mImpl->mEventData->mDecorator->IsHorizontalScrollEnabled();
209   }
210
211   return false;
212 }
213
214 void Controller::SetVerticalScrollEnabled(bool enable)
215 {
216   if((NULL != mImpl->mEventData) &&
217      mImpl->mEventData->mDecorator)
218   {
219     if(mImpl->mEventData->mDecorator)
220     {
221       mImpl->mEventData->mDecorator->SetVerticalScrollEnabled(enable);
222     }
223   }
224 }
225
226 bool Controller::IsVerticalScrollEnabled() const
227 {
228   if((NULL != mImpl->mEventData) &&
229      mImpl->mEventData->mDecorator)
230   {
231     return mImpl->mEventData->mDecorator->IsVerticalScrollEnabled();
232   }
233
234   return false;
235 }
236
237 void Controller::SetSmoothHandlePanEnabled(bool enable)
238 {
239   if((NULL != mImpl->mEventData) &&
240      mImpl->mEventData->mDecorator)
241   {
242     mImpl->mEventData->mDecorator->SetSmoothHandlePanEnabled(enable);
243   }
244 }
245
246 bool Controller::IsSmoothHandlePanEnabled() const
247 {
248   if((NULL != mImpl->mEventData) &&
249      mImpl->mEventData->mDecorator)
250   {
251     return mImpl->mEventData->mDecorator->IsSmoothHandlePanEnabled();
252   }
253
254   return false;
255 }
256
257 void Controller::SetMaximumNumberOfCharacters(Length maxCharacters)
258 {
259   mImpl->mMaximumNumberOfCharacters = maxCharacters;
260 }
261
262 int Controller::GetMaximumNumberOfCharacters()
263 {
264   return mImpl->mMaximumNumberOfCharacters;
265 }
266
267 void Controller::SetEnableCursorBlink(bool enable)
268 {
269   DALI_ASSERT_DEBUG(NULL != mImpl->mEventData && "TextInput disabled");
270
271   if(NULL != mImpl->mEventData)
272   {
273     mImpl->mEventData->mCursorBlinkEnabled = enable;
274
275     if(!enable &&
276        mImpl->mEventData->mDecorator)
277     {
278       mImpl->mEventData->mDecorator->StopCursorBlink();
279     }
280   }
281 }
282
283 bool Controller::GetEnableCursorBlink() const
284 {
285   if(NULL != mImpl->mEventData)
286   {
287     return mImpl->mEventData->mCursorBlinkEnabled;
288   }
289
290   return false;
291 }
292
293 void Controller::SetMultiLineEnabled(bool enable)
294 {
295   const Layout::Engine::Type layout = enable ? Layout::Engine::MULTI_LINE_BOX : Layout::Engine::SINGLE_LINE_BOX;
296
297   if(layout != mImpl->mLayoutEngine.GetLayout())
298   {
299     // Set the layout type.
300     mImpl->mLayoutEngine.SetLayout(layout);
301
302     // Set the flags to redo the layout operations
303     const OperationsMask layoutOperations = static_cast<OperationsMask>(LAYOUT |
304                                                                         UPDATE_LAYOUT_SIZE |
305                                                                         ALIGN |
306                                                                         REORDER);
307
308     mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
309     mImpl->mOperationsPending                  = static_cast<OperationsMask>(mImpl->mOperationsPending | layoutOperations);
310
311     // Need to recalculate natural size
312     mImpl->mRecalculateNaturalSize = true;
313
314     mImpl->RequestRelayout();
315   }
316 }
317
318 bool Controller::IsMultiLineEnabled() const
319 {
320   return Layout::Engine::MULTI_LINE_BOX == mImpl->mLayoutEngine.GetLayout();
321 }
322
323 void Controller::SetHorizontalAlignment(Text::HorizontalAlignment::Type alignment)
324 {
325   if(alignment != mImpl->mModel->mHorizontalAlignment)
326   {
327     // Set the alignment.
328     mImpl->mModel->mHorizontalAlignment = alignment;
329
330     // Set the flag to redo the alignment operation.
331     mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | ALIGN);
332
333     if(mImpl->mEventData)
334     {
335       mImpl->mEventData->mUpdateAlignment = true;
336
337       // Update the cursor if it's in editing mode
338       if(EventData::IsEditingState(mImpl->mEventData->mState))
339       {
340         mImpl->ChangeState(EventData::EDITING);
341         mImpl->mEventData->mUpdateCursorPosition = true;
342       }
343     }
344
345     mImpl->RequestRelayout();
346   }
347 }
348
349 Text::HorizontalAlignment::Type Controller::GetHorizontalAlignment() const
350 {
351   return mImpl->mModel->mHorizontalAlignment;
352 }
353
354 void Controller::SetVerticalAlignment(VerticalAlignment::Type alignment)
355 {
356   if(alignment != mImpl->mModel->mVerticalAlignment)
357   {
358     // Set the alignment.
359     mImpl->mModel->mVerticalAlignment = alignment;
360
361     mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | ALIGN);
362
363     mImpl->RequestRelayout();
364   }
365 }
366
367 VerticalAlignment::Type Controller::GetVerticalAlignment() const
368 {
369   return mImpl->mModel->mVerticalAlignment;
370 }
371
372 bool Controller::IsIgnoreSpacesAfterText() const
373 {
374   return mImpl->mModel->mIgnoreSpacesAfterText;
375 }
376
377 void Controller::SetIgnoreSpacesAfterText(bool ignore)
378 {
379   mImpl->mModel->mIgnoreSpacesAfterText = ignore;
380 }
381
382 bool Controller::IsMatchSystemLanguageDirection() const
383 {
384   return mImpl->mModel->mMatchSystemLanguageDirection;
385 }
386
387 void Controller::SetMatchSystemLanguageDirection(bool match)
388 {
389   mImpl->mModel->mMatchSystemLanguageDirection = match;
390 }
391
392 void Controller::SetLayoutDirection(Dali::LayoutDirection::Type layoutDirection)
393 {
394   mImpl->mLayoutDirection = layoutDirection;
395 }
396
397 bool Controller::IsShowingRealText() const
398 {
399   return mImpl->IsShowingRealText();
400 }
401
402 void Controller::SetLineWrapMode(Text::LineWrap::Mode lineWrapMode)
403 {
404   if(lineWrapMode != mImpl->mModel->mLineWrapMode)
405   {
406     // Set the text wrap mode.
407     mImpl->mModel->mLineWrapMode = lineWrapMode;
408
409     // Update Text layout for applying wrap mode
410     mImpl->mOperationsPending                          = static_cast<OperationsMask>(mImpl->mOperationsPending |
411                                                             ALIGN |
412                                                             LAYOUT |
413                                                             UPDATE_LAYOUT_SIZE |
414                                                             REORDER);
415     mImpl->mTextUpdateInfo.mCharacterIndex             = 0u;
416     mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
417     mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = mImpl->mModel->mLogicalModel->mText.Count();
418
419     // Request relayout
420     mImpl->RequestRelayout();
421   }
422 }
423
424 Text::LineWrap::Mode Controller::GetLineWrapMode() const
425 {
426   return mImpl->mModel->mLineWrapMode;
427 }
428
429 void Controller::SetTextElideEnabled(bool enabled)
430 {
431   mImpl->mModel->mElideEnabled = enabled;
432 }
433
434 bool Controller::IsTextElideEnabled() const
435 {
436   return mImpl->mModel->mElideEnabled;
437 }
438
439 void Controller::SetTextFitEnabled(bool enabled)
440 {
441   mImpl->mTextFitEnabled = enabled;
442 }
443
444 bool Controller::IsTextFitEnabled() const
445 {
446   return mImpl->mTextFitEnabled;
447 }
448
449 void Controller::SetTextFitMinSize(float minSize, FontSizeType type)
450 {
451   switch(type)
452   {
453     case POINT_SIZE:
454     {
455       mImpl->mTextFitMinSize = minSize;
456       break;
457     }
458     case PIXEL_SIZE:
459     {
460       mImpl->mTextFitMinSize = ConvertPixelToPint(minSize);
461       break;
462     }
463   }
464 }
465
466 float Controller::GetTextFitMinSize() const
467 {
468   return mImpl->mTextFitMinSize;
469 }
470
471 void Controller::SetTextFitMaxSize(float maxSize, FontSizeType type)
472 {
473   switch(type)
474   {
475     case POINT_SIZE:
476     {
477       mImpl->mTextFitMaxSize = maxSize;
478       break;
479     }
480     case PIXEL_SIZE:
481     {
482       mImpl->mTextFitMaxSize = ConvertPixelToPint(maxSize);
483       break;
484     }
485   }
486 }
487
488 float Controller::GetTextFitMaxSize() const
489 {
490   return mImpl->mTextFitMaxSize;
491 }
492
493 void Controller::SetTextFitStepSize(float step, FontSizeType type)
494 {
495   switch(type)
496   {
497     case POINT_SIZE:
498     {
499       mImpl->mTextFitStepSize = step;
500       break;
501     }
502     case PIXEL_SIZE:
503     {
504       mImpl->mTextFitStepSize = ConvertPixelToPint(step);
505       break;
506     }
507   }
508 }
509
510 float Controller::GetTextFitStepSize() const
511 {
512   return mImpl->mTextFitStepSize;
513 }
514
515 void Controller::SetTextFitContentSize(Vector2 size)
516 {
517   mImpl->mTextFitContentSize = size;
518 }
519
520 Vector2 Controller::GetTextFitContentSize() const
521 {
522   return mImpl->mTextFitContentSize;
523 }
524
525 void Controller::SetPlaceholderTextElideEnabled(bool enabled)
526 {
527   PlaceholderHandler::SetPlaceholderTextElideEnabled(*this, enabled);
528 }
529
530 bool Controller::IsPlaceholderTextElideEnabled() const
531 {
532   return PlaceholderHandler::IsPlaceholderTextElideEnabled(*this);
533 }
534
535 void Controller::SetSelectionEnabled(bool enabled)
536 {
537   mImpl->mEventData->mSelectionEnabled = enabled;
538 }
539
540 bool Controller::IsSelectionEnabled() const
541 {
542   return mImpl->mEventData->mSelectionEnabled;
543 }
544
545 void Controller::SetShiftSelectionEnabled(bool enabled)
546 {
547   mImpl->mEventData->mShiftSelectionFlag = enabled;
548 }
549
550 bool Controller::IsShiftSelectionEnabled() const
551 {
552   return mImpl->mEventData->mShiftSelectionFlag;
553 }
554
555 void Controller::SetGrabHandleEnabled(bool enabled)
556 {
557   mImpl->mEventData->mGrabHandleEnabled = enabled;
558 }
559
560 bool Controller::IsGrabHandleEnabled() const
561 {
562   return mImpl->mEventData->mGrabHandleEnabled;
563 }
564
565 void Controller::SetGrabHandlePopupEnabled(bool enabled)
566 {
567   mImpl->mEventData->mGrabHandlePopupEnabled = enabled;
568 }
569
570 bool Controller::IsGrabHandlePopupEnabled() const
571 {
572   return mImpl->mEventData->mGrabHandlePopupEnabled;
573 }
574
575 // public : Update
576
577 void Controller::SetText(const std::string& text)
578 {
579   TextUpdater::SetText(*this, text);
580 }
581
582 void Controller::GetText(std::string& text) const
583 {
584   if(!mImpl->IsShowingPlaceholderText())
585   {
586     // Retrieves the text string.
587     mImpl->GetText(0u, text);
588   }
589   else
590   {
591     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::GetText %p empty (but showing placeholder)\n", this);
592   }
593 }
594
595 void Controller::SetPlaceholderText(PlaceholderType type, const std::string& text)
596 {
597   PlaceholderHandler::SetPlaceholderText(*this, type, text);
598 }
599
600 void Controller::GetPlaceholderText(PlaceholderType type, std::string& text) const
601 {
602   PlaceholderHandler::GetPlaceholderText(*this, type, text);
603 }
604
605 void Controller::UpdateAfterFontChange(const std::string& newDefaultFont)
606 {
607   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::UpdateAfterFontChange\n");
608
609   if(!mImpl->mFontDefaults->familyDefined) // If user defined font then should not update when system font changes
610   {
611     DALI_LOG_INFO(gLogFilter, Debug::Concise, "Controller::UpdateAfterFontChange newDefaultFont(%s)\n", newDefaultFont.c_str());
612     mImpl->mFontDefaults->mFontDescription.family = newDefaultFont;
613
614     ClearFontData();
615
616     mImpl->RequestRelayout();
617   }
618 }
619
620 void Controller::RetrieveSelection(std::string& selectedText) const
621 {
622   mImpl->RetrieveSelection(selectedText, false);
623 }
624
625 void Controller::SetSelection(int start, int end)
626 {
627   mImpl->SetSelection(start, end);
628 }
629
630 std::pair<int, int> Controller::GetSelectionIndexes() const
631 {
632   return mImpl->GetSelectionIndexes();
633 }
634
635 void Controller::CopyStringToClipboard(const std::string& source)
636 {
637   mImpl->CopyStringToClipboard(source);
638 }
639
640 void Controller::SendSelectionToClipboard(bool deleteAfterSending)
641 {
642   mImpl->SendSelectionToClipboard(deleteAfterSending);
643 }
644
645 // public : Default style & Input style
646
647 void Controller::SetDefaultFontFamily(const std::string& defaultFontFamily)
648 {
649   if(NULL == mImpl->mFontDefaults)
650   {
651     mImpl->mFontDefaults = new FontDefaults();
652   }
653
654   mImpl->mFontDefaults->mFontDescription.family = defaultFontFamily;
655   DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetDefaultFontFamily %s\n", defaultFontFamily.c_str());
656   mImpl->mFontDefaults->familyDefined = !defaultFontFamily.empty();
657
658   if(mImpl->mEventData)
659   {
660     // Update the cursor position if it's in editing mode
661     if(EventData::IsEditingState(mImpl->mEventData->mState))
662     {
663       mImpl->mEventData->mDecoratorUpdated     = true;
664       mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font family is updated.
665     }
666   }
667
668   // Clear the font-specific data
669   ClearFontData();
670
671   mImpl->RequestRelayout();
672 }
673
674 const std::string& Controller::GetDefaultFontFamily() const
675 {
676   if(NULL != mImpl->mFontDefaults)
677   {
678     return mImpl->mFontDefaults->mFontDescription.family;
679   }
680
681   return EMPTY_STRING;
682 }
683
684 void Controller::SetPlaceholderFontFamily(const std::string& placeholderTextFontFamily)
685 {
686   PlaceholderHandler::SetPlaceholderFontFamily(*this, placeholderTextFontFamily);
687 }
688
689 const std::string& Controller::GetPlaceholderFontFamily() const
690 {
691   return PlaceholderHandler::GetPlaceholderFontFamily(*this);
692 }
693
694 void Controller::SetDefaultFontWeight(FontWeight weight)
695 {
696   if(NULL == mImpl->mFontDefaults)
697   {
698     mImpl->mFontDefaults = new FontDefaults();
699   }
700
701   mImpl->mFontDefaults->mFontDescription.weight = weight;
702   mImpl->mFontDefaults->weightDefined           = true;
703
704   if(mImpl->mEventData)
705   {
706     // Update the cursor position if it's in editing mode
707     if(EventData::IsEditingState(mImpl->mEventData->mState))
708     {
709       mImpl->mEventData->mDecoratorUpdated     = true;
710       mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font weight is updated.
711     }
712   }
713
714   // Clear the font-specific data
715   ClearFontData();
716
717   mImpl->RequestRelayout();
718 }
719
720 bool Controller::IsDefaultFontWeightDefined() const
721 {
722   if(NULL != mImpl->mFontDefaults)
723   {
724     return mImpl->mFontDefaults->weightDefined;
725   }
726
727   return false;
728 }
729
730 FontWeight Controller::GetDefaultFontWeight() const
731 {
732   if(NULL != mImpl->mFontDefaults)
733   {
734     return mImpl->mFontDefaults->mFontDescription.weight;
735   }
736
737   return TextAbstraction::FontWeight::NORMAL;
738 }
739
740 void Controller::SetPlaceholderTextFontWeight(FontWeight weight)
741 {
742   PlaceholderHandler::SetPlaceholderTextFontWeight(*this, weight);
743 }
744
745 bool Controller::IsPlaceholderTextFontWeightDefined() const
746 {
747   return PlaceholderHandler::IsPlaceholderTextFontWeightDefined(*this);
748   ;
749 }
750
751 FontWeight Controller::GetPlaceholderTextFontWeight() const
752 {
753   return PlaceholderHandler::GetPlaceholderTextFontWeight(*this);
754 }
755
756 void Controller::SetDefaultFontWidth(FontWidth width)
757 {
758   if(NULL == mImpl->mFontDefaults)
759   {
760     mImpl->mFontDefaults = new FontDefaults();
761   }
762
763   mImpl->mFontDefaults->mFontDescription.width = width;
764   mImpl->mFontDefaults->widthDefined           = true;
765
766   if(mImpl->mEventData)
767   {
768     // Update the cursor position if it's in editing mode
769     if(EventData::IsEditingState(mImpl->mEventData->mState))
770     {
771       mImpl->mEventData->mDecoratorUpdated     = true;
772       mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font width is updated.
773     }
774   }
775
776   // Clear the font-specific data
777   ClearFontData();
778
779   mImpl->RequestRelayout();
780 }
781
782 bool Controller::IsDefaultFontWidthDefined() const
783 {
784   if(NULL != mImpl->mFontDefaults)
785   {
786     return mImpl->mFontDefaults->widthDefined;
787   }
788
789   return false;
790 }
791
792 FontWidth Controller::GetDefaultFontWidth() const
793 {
794   if(NULL != mImpl->mFontDefaults)
795   {
796     return mImpl->mFontDefaults->mFontDescription.width;
797   }
798
799   return TextAbstraction::FontWidth::NORMAL;
800 }
801
802 void Controller::SetPlaceholderTextFontWidth(FontWidth width)
803 {
804   PlaceholderHandler::SetPlaceholderTextFontWidth(*this, width);
805 }
806
807 bool Controller::IsPlaceholderTextFontWidthDefined() const
808 {
809   return PlaceholderHandler::IsPlaceholderTextFontWidthDefined(*this);
810 }
811
812 FontWidth Controller::GetPlaceholderTextFontWidth() const
813 {
814   return PlaceholderHandler::GetPlaceholderTextFontWidth(*this);
815 }
816
817 void Controller::SetDefaultFontSlant(FontSlant slant)
818 {
819   if(NULL == mImpl->mFontDefaults)
820   {
821     mImpl->mFontDefaults = new FontDefaults();
822   }
823
824   mImpl->mFontDefaults->mFontDescription.slant = slant;
825   mImpl->mFontDefaults->slantDefined           = true;
826
827   if(mImpl->mEventData)
828   {
829     // Update the cursor position if it's in editing mode
830     if(EventData::IsEditingState(mImpl->mEventData->mState))
831     {
832       mImpl->mEventData->mDecoratorUpdated     = true;
833       mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font slant is updated.
834     }
835   }
836
837   // Clear the font-specific data
838   ClearFontData();
839
840   mImpl->RequestRelayout();
841 }
842
843 bool Controller::IsDefaultFontSlantDefined() const
844 {
845   if(NULL != mImpl->mFontDefaults)
846   {
847     return mImpl->mFontDefaults->slantDefined;
848   }
849   return false;
850 }
851
852 FontSlant Controller::GetDefaultFontSlant() const
853 {
854   if(NULL != mImpl->mFontDefaults)
855   {
856     return mImpl->mFontDefaults->mFontDescription.slant;
857   }
858
859   return TextAbstraction::FontSlant::NORMAL;
860 }
861
862 void Controller::SetPlaceholderTextFontSlant(FontSlant slant)
863 {
864   PlaceholderHandler::SetPlaceholderTextFontSlant(*this, slant);
865 }
866
867 bool Controller::IsPlaceholderTextFontSlantDefined() const
868 {
869   return PlaceholderHandler::IsPlaceholderTextFontSlantDefined(*this);
870 }
871
872 FontSlant Controller::GetPlaceholderTextFontSlant() const
873 {
874   return PlaceholderHandler::GetPlaceholderTextFontSlant(*this);
875 }
876
877 void Controller::SetFontSizeScale(float scale)
878 {
879   mImpl->mFontSizeScale = scale;
880
881   if(mImpl->mEventData)
882   {
883     // Update the cursor position if it's in editing mode
884     if(EventData::IsEditingState(mImpl->mEventData->mState))
885     {
886       mImpl->mEventData->mDecoratorUpdated     = true;
887       mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font size is updated.
888     }
889   }
890
891   // Clear the font-specific data
892   ClearFontData();
893
894   mImpl->RequestRelayout();
895 }
896
897 float Controller::GetFontSizeScale() const
898 {
899   if(nullptr != mImpl->mFontDefaults)
900   {
901     return mImpl->mFontSizeScale;
902   }
903
904   return 1.f;
905 }
906
907 void Controller::SetDefaultFontSize(float fontSize, FontSizeType type)
908 {
909   if(NULL == mImpl->mFontDefaults)
910   {
911     mImpl->mFontDefaults = new FontDefaults();
912   }
913
914   switch(type)
915   {
916     case POINT_SIZE:
917     {
918       mImpl->mFontDefaults->mDefaultPointSize = fontSize;
919       mImpl->mFontDefaults->sizeDefined       = true;
920       break;
921     }
922     case PIXEL_SIZE:
923     {
924       // Point size = Pixel size * 72.f / DPI
925       unsigned int                horizontalDpi = 0u;
926       unsigned int                verticalDpi   = 0u;
927       TextAbstraction::FontClient fontClient    = TextAbstraction::FontClient::Get();
928       fontClient.GetDpi(horizontalDpi, verticalDpi);
929
930       mImpl->mFontDefaults->mDefaultPointSize = (fontSize * 72.f) / static_cast<float>(horizontalDpi);
931       mImpl->mFontDefaults->sizeDefined       = true;
932       break;
933     }
934   }
935
936   if(mImpl->mEventData)
937   {
938     // Update the cursor position if it's in editing mode
939     if(EventData::IsEditingState(mImpl->mEventData->mState))
940     {
941       mImpl->mEventData->mDecoratorUpdated     = true;
942       mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font size is updated.
943     }
944   }
945
946   // Clear the font-specific data
947   ClearFontData();
948
949   mImpl->RequestRelayout();
950 }
951
952 float Controller::GetDefaultFontSize(FontSizeType type) const
953 {
954   float value = 0.0f;
955   if(NULL != mImpl->mFontDefaults)
956   {
957     switch(type)
958     {
959       case POINT_SIZE:
960       {
961         value = mImpl->mFontDefaults->mDefaultPointSize;
962         break;
963       }
964       case PIXEL_SIZE:
965       {
966         // Pixel size = Point size * DPI / 72.f
967         unsigned int                horizontalDpi = 0u;
968         unsigned int                verticalDpi   = 0u;
969         TextAbstraction::FontClient fontClient    = TextAbstraction::FontClient::Get();
970         fontClient.GetDpi(horizontalDpi, verticalDpi);
971
972         value = mImpl->mFontDefaults->mDefaultPointSize * static_cast<float>(horizontalDpi) / 72.f;
973         break;
974       }
975     }
976     return value;
977   }
978
979   return value;
980 }
981
982 void Controller::SetPlaceholderTextFontSize(float fontSize, FontSizeType type)
983 {
984   PlaceholderHandler::SetPlaceholderTextFontSize(*this, fontSize, type);
985 }
986
987 float Controller::GetPlaceholderTextFontSize(FontSizeType type) const
988 {
989   return PlaceholderHandler::GetPlaceholderTextFontSize(*this, type);
990 }
991
992 void Controller::SetDefaultColor(const Vector4& color)
993 {
994   mImpl->mTextColor = color;
995
996   if(!mImpl->IsShowingPlaceholderText())
997   {
998     mImpl->mModel->mVisualModel->SetTextColor(color);
999
1000     mImpl->mModel->mLogicalModel->mColorRuns.Clear();
1001
1002     mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | COLOR);
1003
1004     mImpl->RequestRelayout();
1005   }
1006 }
1007
1008 const Vector4& Controller::GetDefaultColor() const
1009 {
1010   return mImpl->mTextColor;
1011 }
1012
1013 void Controller::SetPlaceholderTextColor(const Vector4& textColor)
1014 {
1015   PlaceholderHandler::SetPlaceholderTextColor(*this, textColor);
1016 }
1017
1018 const Vector4& Controller::GetPlaceholderTextColor() const
1019 {
1020   return PlaceholderHandler::GetPlaceholderTextColor(*this);
1021 }
1022
1023 void Controller::SetShadowOffset(const Vector2& shadowOffset)
1024 {
1025   mImpl->mModel->mVisualModel->SetShadowOffset(shadowOffset);
1026
1027   mImpl->RequestRelayout();
1028 }
1029
1030 const Vector2& Controller::GetShadowOffset() const
1031 {
1032   return mImpl->mModel->mVisualModel->GetShadowOffset();
1033 }
1034
1035 void Controller::SetShadowColor(const Vector4& shadowColor)
1036 {
1037   mImpl->mModel->mVisualModel->SetShadowColor(shadowColor);
1038
1039   mImpl->RequestRelayout();
1040 }
1041
1042 const Vector4& Controller::GetShadowColor() const
1043 {
1044   return mImpl->mModel->mVisualModel->GetShadowColor();
1045 }
1046
1047 void Controller::SetShadowBlurRadius(const float& shadowBlurRadius)
1048 {
1049   if(fabsf(GetShadowBlurRadius() - shadowBlurRadius) > Math::MACHINE_EPSILON_1)
1050   {
1051     mImpl->mModel->mVisualModel->SetShadowBlurRadius(shadowBlurRadius);
1052
1053     mImpl->RequestRelayout();
1054   }
1055 }
1056
1057 const float& Controller::GetShadowBlurRadius() const
1058 {
1059   return mImpl->mModel->mVisualModel->GetShadowBlurRadius();
1060 }
1061
1062 void Controller::SetUnderlineColor(const Vector4& color)
1063 {
1064   mImpl->mModel->mVisualModel->SetUnderlineColor(color);
1065
1066   mImpl->RequestRelayout();
1067 }
1068
1069 const Vector4& Controller::GetUnderlineColor() const
1070 {
1071   return mImpl->mModel->mVisualModel->GetUnderlineColor();
1072 }
1073
1074 void Controller::SetUnderlineEnabled(bool enabled)
1075 {
1076   mImpl->mModel->mVisualModel->SetUnderlineEnabled(enabled);
1077
1078   mImpl->RequestRelayout();
1079 }
1080
1081 bool Controller::IsUnderlineEnabled() const
1082 {
1083   return mImpl->mModel->mVisualModel->IsUnderlineEnabled();
1084 }
1085
1086 void Controller::SetUnderlineHeight(float height)
1087 {
1088   mImpl->mModel->mVisualModel->SetUnderlineHeight(height);
1089
1090   mImpl->RequestRelayout();
1091 }
1092
1093 float Controller::GetUnderlineHeight() const
1094 {
1095   return mImpl->mModel->mVisualModel->GetUnderlineHeight();
1096 }
1097
1098 void Controller::SetOutlineColor(const Vector4& color)
1099 {
1100   mImpl->mModel->mVisualModel->SetOutlineColor(color);
1101
1102   mImpl->RequestRelayout();
1103 }
1104
1105 const Vector4& Controller::GetOutlineColor() const
1106 {
1107   return mImpl->mModel->mVisualModel->GetOutlineColor();
1108 }
1109
1110 void Controller::SetOutlineWidth(uint16_t width)
1111 {
1112   mImpl->mModel->mVisualModel->SetOutlineWidth(width);
1113
1114   mImpl->RequestRelayout();
1115 }
1116
1117 uint16_t Controller::GetOutlineWidth() const
1118 {
1119   return mImpl->mModel->mVisualModel->GetOutlineWidth();
1120 }
1121
1122 void Controller::SetBackgroundColor(const Vector4& color)
1123 {
1124   mImpl->mModel->mVisualModel->SetBackgroundColor(color);
1125
1126   mImpl->RequestRelayout();
1127 }
1128
1129 const Vector4& Controller::GetBackgroundColor() const
1130 {
1131   return mImpl->mModel->mVisualModel->GetBackgroundColor();
1132 }
1133
1134 void Controller::SetBackgroundEnabled(bool enabled)
1135 {
1136   mImpl->mModel->mVisualModel->SetBackgroundEnabled(enabled);
1137
1138   mImpl->RequestRelayout();
1139 }
1140
1141 bool Controller::IsBackgroundEnabled() const
1142 {
1143   return mImpl->mModel->mVisualModel->IsBackgroundEnabled();
1144 }
1145
1146 void Controller::SetDefaultEmbossProperties(const std::string& embossProperties)
1147 {
1148   if(NULL == mImpl->mEmbossDefaults)
1149   {
1150     mImpl->mEmbossDefaults = new EmbossDefaults();
1151   }
1152
1153   mImpl->mEmbossDefaults->properties = embossProperties;
1154 }
1155
1156 const std::string& Controller::GetDefaultEmbossProperties() const
1157 {
1158   if(NULL != mImpl->mEmbossDefaults)
1159   {
1160     return mImpl->mEmbossDefaults->properties;
1161   }
1162
1163   return EMPTY_STRING;
1164 }
1165
1166 void Controller::SetDefaultOutlineProperties(const std::string& outlineProperties)
1167 {
1168   if(NULL == mImpl->mOutlineDefaults)
1169   {
1170     mImpl->mOutlineDefaults = new OutlineDefaults();
1171   }
1172
1173   mImpl->mOutlineDefaults->properties = outlineProperties;
1174 }
1175
1176 const std::string& Controller::GetDefaultOutlineProperties() const
1177 {
1178   if(NULL != mImpl->mOutlineDefaults)
1179   {
1180     return mImpl->mOutlineDefaults->properties;
1181   }
1182
1183   return EMPTY_STRING;
1184 }
1185
1186 bool Controller::SetDefaultLineSpacing(float lineSpacing)
1187 {
1188   if(std::fabs(lineSpacing - mImpl->mLayoutEngine.GetDefaultLineSpacing()) > Math::MACHINE_EPSILON_1000)
1189   {
1190     mImpl->mLayoutEngine.SetDefaultLineSpacing(lineSpacing);
1191     mImpl->mRecalculateNaturalSize = true;
1192     return true;
1193   }
1194   return false;
1195 }
1196
1197 float Controller::GetDefaultLineSpacing() const
1198 {
1199   return mImpl->mLayoutEngine.GetDefaultLineSpacing();
1200 }
1201
1202 bool Controller::SetDefaultLineSize(float lineSize)
1203 {
1204   if(std::fabs(lineSize - mImpl->mLayoutEngine.GetDefaultLineSize()) > Math::MACHINE_EPSILON_1000)
1205   {
1206     mImpl->mLayoutEngine.SetDefaultLineSize(lineSize);
1207     mImpl->mRecalculateNaturalSize = true;
1208     return true;
1209   }
1210   return false;
1211 }
1212
1213 float Controller::GetDefaultLineSize() const
1214 {
1215   return mImpl->mLayoutEngine.GetDefaultLineSize();
1216 }
1217
1218 void Controller::SetInputColor(const Vector4& color)
1219 {
1220   if(NULL != mImpl->mEventData)
1221   {
1222     mImpl->mEventData->mInputStyle.textColor      = color;
1223     mImpl->mEventData->mInputStyle.isDefaultColor = false;
1224
1225     if(EventData::SELECTING == mImpl->mEventData->mState || EventData::EDITING == mImpl->mEventData->mState || EventData::INACTIVE == mImpl->mEventData->mState)
1226     {
1227       const bool handlesCrossed = mImpl->mEventData->mLeftSelectionPosition > mImpl->mEventData->mRightSelectionPosition;
1228
1229       // Get start and end position of selection
1230       const CharacterIndex startOfSelectedText  = handlesCrossed ? mImpl->mEventData->mRightSelectionPosition : mImpl->mEventData->mLeftSelectionPosition;
1231       const Length         lengthOfSelectedText = (handlesCrossed ? mImpl->mEventData->mLeftSelectionPosition : mImpl->mEventData->mRightSelectionPosition) - startOfSelectedText;
1232
1233       // Add the color run.
1234       const VectorBase::SizeType numberOfRuns = mImpl->mModel->mLogicalModel->mColorRuns.Count();
1235       mImpl->mModel->mLogicalModel->mColorRuns.Resize(numberOfRuns + 1u);
1236
1237       ColorRun& colorRun                       = *(mImpl->mModel->mLogicalModel->mColorRuns.Begin() + numberOfRuns);
1238       colorRun.color                           = color;
1239       colorRun.characterRun.characterIndex     = startOfSelectedText;
1240       colorRun.characterRun.numberOfCharacters = lengthOfSelectedText;
1241
1242       // Request to relayout.
1243       mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | COLOR);
1244       mImpl->RequestRelayout();
1245
1246       mImpl->mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
1247       mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
1248       mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = lengthOfSelectedText;
1249     }
1250   }
1251 }
1252
1253 const Vector4& Controller::GetInputColor() const
1254 {
1255   if(NULL != mImpl->mEventData)
1256   {
1257     return mImpl->mEventData->mInputStyle.textColor;
1258   }
1259
1260   // Return the default text's color if there is no EventData.
1261   return mImpl->mTextColor;
1262 }
1263
1264 void Controller::SetInputFontFamily(const std::string& fontFamily)
1265 {
1266   InputFontHandler::SetInputFontFamily(*this, fontFamily);
1267 }
1268
1269 const std::string& Controller::GetInputFontFamily() const
1270 {
1271   return InputFontHandler::GetInputFontFamily(*this);
1272 }
1273
1274 void Controller::SetInputFontWeight(FontWeight weight)
1275 {
1276   InputFontHandler::SetInputFontWeight(*this, weight);
1277 }
1278
1279 bool Controller::IsInputFontWeightDefined() const
1280 {
1281   return InputFontHandler::IsInputFontWeightDefined(*this);
1282 }
1283
1284 FontWeight Controller::GetInputFontWeight() const
1285 {
1286   return InputFontHandler::GetInputFontWeight(*this);
1287 }
1288
1289 void Controller::SetInputFontWidth(FontWidth width)
1290 {
1291   InputFontHandler::SetInputFontWidth(*this, width);
1292 }
1293
1294 bool Controller::IsInputFontWidthDefined() const
1295 {
1296   return InputFontHandler::IsInputFontWidthDefined(*this);
1297 }
1298
1299 FontWidth Controller::GetInputFontWidth() const
1300 {
1301   return InputFontHandler::GetInputFontWidth(*this);
1302 }
1303
1304 void Controller::SetInputFontSlant(FontSlant slant)
1305 {
1306   InputFontHandler::SetInputFontSlant(*this, slant);
1307 }
1308
1309 bool Controller::IsInputFontSlantDefined() const
1310 {
1311   return InputFontHandler::IsInputFontSlantDefined(*this);
1312 }
1313
1314 FontSlant Controller::GetInputFontSlant() const
1315 {
1316   return InputFontHandler::GetInputFontSlant(*this);
1317 }
1318
1319 void Controller::SetInputFontPointSize(float size)
1320 {
1321   InputFontHandler::SetInputFontPointSize(*this, size);
1322 }
1323
1324 float Controller::GetInputFontPointSize() const
1325 {
1326   return InputFontHandler::GetInputFontPointSize(*this);
1327 }
1328
1329 void Controller::SetInputLineSpacing(float lineSpacing)
1330 {
1331   if(NULL != mImpl->mEventData)
1332   {
1333     mImpl->mEventData->mInputStyle.lineSpacing          = lineSpacing;
1334     mImpl->mEventData->mInputStyle.isLineSpacingDefined = true;
1335   }
1336 }
1337
1338 float Controller::GetInputLineSpacing() const
1339 {
1340   if(NULL != mImpl->mEventData)
1341   {
1342     return mImpl->mEventData->mInputStyle.lineSpacing;
1343   }
1344
1345   return 0.f;
1346 }
1347
1348 void Controller::SetInputShadowProperties(const std::string& shadowProperties)
1349 {
1350   if(NULL != mImpl->mEventData)
1351   {
1352     mImpl->mEventData->mInputStyle.shadowProperties = shadowProperties;
1353   }
1354 }
1355
1356 const std::string& Controller::GetInputShadowProperties() const
1357 {
1358   if(NULL != mImpl->mEventData)
1359   {
1360     return mImpl->mEventData->mInputStyle.shadowProperties;
1361   }
1362
1363   return EMPTY_STRING;
1364 }
1365
1366 void Controller::SetInputUnderlineProperties(const std::string& underlineProperties)
1367 {
1368   if(NULL != mImpl->mEventData)
1369   {
1370     mImpl->mEventData->mInputStyle.underlineProperties = underlineProperties;
1371   }
1372 }
1373
1374 const std::string& Controller::GetInputUnderlineProperties() const
1375 {
1376   if(NULL != mImpl->mEventData)
1377   {
1378     return mImpl->mEventData->mInputStyle.underlineProperties;
1379   }
1380
1381   return EMPTY_STRING;
1382 }
1383
1384 void Controller::SetInputEmbossProperties(const std::string& embossProperties)
1385 {
1386   if(NULL != mImpl->mEventData)
1387   {
1388     mImpl->mEventData->mInputStyle.embossProperties = embossProperties;
1389   }
1390 }
1391
1392 const std::string& Controller::GetInputEmbossProperties() const
1393 {
1394   if(NULL != mImpl->mEventData)
1395   {
1396     return mImpl->mEventData->mInputStyle.embossProperties;
1397   }
1398
1399   return GetDefaultEmbossProperties();
1400 }
1401
1402 void Controller::SetInputOutlineProperties(const std::string& outlineProperties)
1403 {
1404   if(NULL != mImpl->mEventData)
1405   {
1406     mImpl->mEventData->mInputStyle.outlineProperties = outlineProperties;
1407   }
1408 }
1409
1410 const std::string& Controller::GetInputOutlineProperties() const
1411 {
1412   if(NULL != mImpl->mEventData)
1413   {
1414     return mImpl->mEventData->mInputStyle.outlineProperties;
1415   }
1416
1417   return GetDefaultOutlineProperties();
1418 }
1419
1420 void Controller::SetInputModePassword(bool passwordInput)
1421 {
1422   if(NULL != mImpl->mEventData)
1423   {
1424     mImpl->mEventData->mPasswordInput = passwordInput;
1425   }
1426 }
1427
1428 bool Controller::IsInputModePassword()
1429 {
1430   if(NULL != mImpl->mEventData)
1431   {
1432     return mImpl->mEventData->mPasswordInput;
1433   }
1434   return false;
1435 }
1436
1437 void Controller::SetNoTextDoubleTapAction(NoTextTap::Action action)
1438 {
1439   if(NULL != mImpl->mEventData)
1440   {
1441     mImpl->mEventData->mDoubleTapAction = action;
1442   }
1443 }
1444
1445 Controller::NoTextTap::Action Controller::GetNoTextDoubleTapAction() const
1446 {
1447   NoTextTap::Action action = NoTextTap::NO_ACTION;
1448
1449   if(NULL != mImpl->mEventData)
1450   {
1451     action = mImpl->mEventData->mDoubleTapAction;
1452   }
1453
1454   return action;
1455 }
1456
1457 void Controller::SetNoTextLongPressAction(NoTextTap::Action action)
1458 {
1459   if(NULL != mImpl->mEventData)
1460   {
1461     mImpl->mEventData->mLongPressAction = action;
1462   }
1463 }
1464
1465 Controller::NoTextTap::Action Controller::GetNoTextLongPressAction() const
1466 {
1467   NoTextTap::Action action = NoTextTap::NO_ACTION;
1468
1469   if(NULL != mImpl->mEventData)
1470   {
1471     action = mImpl->mEventData->mLongPressAction;
1472   }
1473
1474   return action;
1475 }
1476
1477 bool Controller::IsUnderlineSetByString()
1478 {
1479   return mImpl->mUnderlineSetByString;
1480 }
1481
1482 void Controller::UnderlineSetByString(bool setByString)
1483 {
1484   mImpl->mUnderlineSetByString = setByString;
1485 }
1486
1487 bool Controller::IsShadowSetByString()
1488 {
1489   return mImpl->mShadowSetByString;
1490 }
1491
1492 void Controller::ShadowSetByString(bool setByString)
1493 {
1494   mImpl->mShadowSetByString = setByString;
1495 }
1496
1497 bool Controller::IsOutlineSetByString()
1498 {
1499   return mImpl->mOutlineSetByString;
1500 }
1501
1502 void Controller::OutlineSetByString(bool setByString)
1503 {
1504   mImpl->mOutlineSetByString = setByString;
1505 }
1506
1507 bool Controller::IsFontStyleSetByString()
1508 {
1509   return mImpl->mFontStyleSetByString;
1510 }
1511
1512 void Controller::FontStyleSetByString(bool setByString)
1513 {
1514   mImpl->mFontStyleSetByString = setByString;
1515 }
1516
1517 // public : Queries & retrieves.
1518
1519 Layout::Engine& Controller::GetLayoutEngine()
1520 {
1521   return mImpl->mLayoutEngine;
1522 }
1523
1524 View& Controller::GetView()
1525 {
1526   return mImpl->mView;
1527 }
1528
1529 Vector3 Controller::GetNaturalSize()
1530 {
1531   return Relayouter::GetNaturalSize(*this);
1532 }
1533
1534 bool Controller::CheckForTextFit(float pointSize, Size& layoutSize)
1535 {
1536   return Relayouter::CheckForTextFit(*this, pointSize, layoutSize);
1537 }
1538
1539 void Controller::FitPointSizeforLayout(Size layoutSize)
1540 {
1541   Relayouter::FitPointSizeforLayout(*this, layoutSize);
1542 }
1543
1544 float Controller::GetHeightForWidth(float width)
1545 {
1546   return Relayouter::GetHeightForWidth(*this, width);
1547 }
1548
1549 int Controller::GetLineCount(float width)
1550 {
1551   GetHeightForWidth(width);
1552   int numberofLines = mImpl->mModel->GetNumberOfLines();
1553   return numberofLines;
1554 }
1555
1556 const ModelInterface* const Controller::GetTextModel() const
1557 {
1558   return mImpl->mModel.Get();
1559 }
1560
1561 float Controller::GetScrollAmountByUserInput()
1562 {
1563   float scrollAmount = 0.0f;
1564
1565   if(NULL != mImpl->mEventData && mImpl->mEventData->mCheckScrollAmount)
1566   {
1567     scrollAmount                          = mImpl->mModel->mScrollPosition.y - mImpl->mModel->mScrollPositionLast.y;
1568     mImpl->mEventData->mCheckScrollAmount = false;
1569   }
1570   return scrollAmount;
1571 }
1572
1573 bool Controller::GetTextScrollInfo(float& scrollPosition, float& controlHeight, float& layoutHeight)
1574 {
1575   const Vector2& layout = mImpl->mModel->mVisualModel->GetLayoutSize();
1576   bool           isScrolled;
1577
1578   controlHeight  = mImpl->mModel->mVisualModel->mControlSize.height;
1579   layoutHeight   = layout.height;
1580   scrollPosition = mImpl->mModel->mScrollPosition.y;
1581   isScrolled     = !Equals(mImpl->mModel->mScrollPosition.y, mImpl->mModel->mScrollPositionLast.y, Math::MACHINE_EPSILON_1);
1582   return isScrolled;
1583 }
1584
1585 void Controller::SetHiddenInputOption(const Property::Map& options)
1586 {
1587   if(NULL == mImpl->mHiddenInput)
1588   {
1589     mImpl->mHiddenInput = new HiddenText(this);
1590   }
1591   mImpl->mHiddenInput->SetProperties(options);
1592 }
1593
1594 void Controller::GetHiddenInputOption(Property::Map& options)
1595 {
1596   if(NULL != mImpl->mHiddenInput)
1597   {
1598     mImpl->mHiddenInput->GetProperties(options);
1599   }
1600 }
1601
1602 void Controller::SetPlaceholderProperty(const Property::Map& map)
1603 {
1604   PlaceholderHandler::SetPlaceholderProperty(*this, map);
1605 }
1606
1607 void Controller::GetPlaceholderProperty(Property::Map& map)
1608 {
1609   PlaceholderHandler::GetPlaceholderProperty(*this, map);
1610 }
1611
1612 Toolkit::DevelText::TextDirection::Type Controller::GetTextDirection()
1613 {
1614   // Make sure the model is up-to-date before layouting
1615   ProcessModifyEvents();
1616
1617   if(mImpl->mUpdateTextDirection)
1618   {
1619     // Operations that can be done only once until the text changes.
1620     const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
1621                                                                           GET_SCRIPTS |
1622                                                                           VALIDATE_FONTS |
1623                                                                           GET_LINE_BREAKS |
1624                                                                           BIDI_INFO |
1625                                                                           SHAPE_TEXT |
1626                                                                           GET_GLYPH_METRICS);
1627
1628     // Set the update info to relayout the whole text.
1629     mImpl->mTextUpdateInfo.mParagraphCharacterIndex     = 0u;
1630     mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters = mImpl->mModel->mLogicalModel->mText.Count();
1631
1632     // Make sure the model is up-to-date before layouting
1633     mImpl->UpdateModel(onlyOnceOperations);
1634
1635     Vector3 naturalSize;
1636     DoRelayout(Size(MAX_FLOAT, MAX_FLOAT),
1637                static_cast<OperationsMask>(onlyOnceOperations |
1638                                            LAYOUT | REORDER | UPDATE_DIRECTION),
1639                naturalSize.GetVectorXY());
1640
1641     // Do not do again the only once operations.
1642     mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending & ~onlyOnceOperations);
1643
1644     // Clear the update info. This info will be set the next time the text is updated.
1645     mImpl->mTextUpdateInfo.Clear();
1646
1647     // FullRelayoutNeeded should be true because DoRelayout is MAX_FLOAT, MAX_FLOAT.
1648     mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
1649
1650     mImpl->mUpdateTextDirection = false;
1651   }
1652
1653   return mImpl->mIsTextDirectionRTL ? Toolkit::DevelText::TextDirection::RIGHT_TO_LEFT : Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT;
1654 }
1655
1656 Toolkit::DevelText::VerticalLineAlignment::Type Controller::GetVerticalLineAlignment() const
1657 {
1658   return mImpl->mModel->GetVerticalLineAlignment();
1659 }
1660
1661 void Controller::SetVerticalLineAlignment(Toolkit::DevelText::VerticalLineAlignment::Type alignment)
1662 {
1663   mImpl->mModel->mVerticalLineAlignment = alignment;
1664 }
1665
1666 // public : Relayout.
1667
1668 Controller::UpdateTextType Controller::Relayout(const Size& size, Dali::LayoutDirection::Type layoutDirection)
1669 {
1670   return Relayouter::Relayout(*this, size, layoutDirection);
1671 }
1672
1673 void Controller::RequestRelayout()
1674 {
1675   mImpl->RequestRelayout();
1676 }
1677
1678 // public : Input style change signals.
1679
1680 bool Controller::IsInputStyleChangedSignalsQueueEmpty()
1681 {
1682   return (NULL == mImpl->mEventData) || (0u == mImpl->mEventData->mInputStyleChangedQueue.Count());
1683 }
1684
1685 void Controller::ProcessInputStyleChangedSignals()
1686 {
1687   if(NULL == mImpl->mEventData)
1688   {
1689     // Nothing to do.
1690     return;
1691   }
1692
1693   for(Vector<InputStyle::Mask>::ConstIterator it    = mImpl->mEventData->mInputStyleChangedQueue.Begin(),
1694                                               endIt = mImpl->mEventData->mInputStyleChangedQueue.End();
1695       it != endIt;
1696       ++it)
1697   {
1698     const InputStyle::Mask mask = *it;
1699
1700     if(NULL != mImpl->mEditableControlInterface)
1701     {
1702       // Emit the input style changed signal.
1703       mImpl->mEditableControlInterface->InputStyleChanged(mask);
1704     }
1705   }
1706
1707   mImpl->mEventData->mInputStyleChangedQueue.Clear();
1708 }
1709
1710 // public : Text-input Event Queuing.
1711
1712 void Controller::KeyboardFocusGainEvent()
1713 {
1714   EventHandler::KeyboardFocusGainEvent(*this);
1715 }
1716
1717 void Controller::KeyboardFocusLostEvent()
1718 {
1719   EventHandler::KeyboardFocusLostEvent(*this);
1720 }
1721
1722 bool Controller::KeyEvent(const Dali::KeyEvent& keyEvent)
1723 {
1724   return EventHandler::KeyEvent(*this, keyEvent);
1725 }
1726
1727 void Controller::AnchorEvent(float x, float y)
1728 {
1729   EventHandler::AnchorEvent(*this, x, y);
1730 }
1731
1732 void Controller::TapEvent(unsigned int tapCount, float x, float y)
1733 {
1734   EventHandler::TapEvent(*this, tapCount, x, y);
1735 }
1736
1737 void Controller::PanEvent(GestureState state, const Vector2& displacement)
1738 {
1739   EventHandler::PanEvent(*this, state, displacement);
1740 }
1741
1742 void Controller::LongPressEvent(GestureState state, float x, float y)
1743 {
1744   EventHandler::LongPressEvent(*this, state, x, y);
1745 }
1746
1747 void Controller::SelectEvent(float x, float y, SelectionType selectType)
1748 {
1749   EventHandler::SelectEvent(*this, x, y, selectType);
1750 }
1751
1752 void Controller::SetTextSelectionRange(const uint32_t* start, const uint32_t* end)
1753 {
1754   if(mImpl->mEventData)
1755   {
1756     mImpl->mEventData->mCheckScrollAmount     = true;
1757     mImpl->mEventData->mIsLeftHandleSelected  = true;
1758     mImpl->mEventData->mIsRightHandleSelected = true;
1759     mImpl->SetTextSelectionRange(start, end);
1760     mImpl->RequestRelayout();
1761     KeyboardFocusGainEvent();
1762   }
1763 }
1764
1765 Uint32Pair Controller::GetTextSelectionRange() const
1766 {
1767   return mImpl->GetTextSelectionRange();
1768 }
1769
1770 CharacterIndex Controller::GetPrimaryCursorPosition() const
1771 {
1772   return mImpl->GetPrimaryCursorPosition();
1773 }
1774
1775 bool Controller::SetPrimaryCursorPosition(CharacterIndex index)
1776 {
1777   if(mImpl->mEventData)
1778   {
1779     mImpl->mEventData->mCheckScrollAmount     = true;
1780     mImpl->mEventData->mIsLeftHandleSelected  = true;
1781     mImpl->mEventData->mIsRightHandleSelected = true;
1782     mImpl->mEventData->mCheckScrollAmount     = true;
1783     if(mImpl->SetPrimaryCursorPosition(index))
1784     {
1785       KeyboardFocusGainEvent();
1786       return true;
1787     }
1788   }
1789   return false;
1790 }
1791
1792 void Controller::SelectWholeText()
1793 {
1794   SelectEvent(0.f, 0.f, SelectionType::ALL);
1795 }
1796
1797 void Controller::SelectNone()
1798 {
1799   SelectEvent(0.f, 0.f, SelectionType::NONE);
1800 }
1801
1802 string Controller::GetSelectedText() const
1803 {
1804   string text;
1805   if(EventData::SELECTING == mImpl->mEventData->mState)
1806   {
1807     mImpl->RetrieveSelection(text, false);
1808   }
1809   return text;
1810 }
1811
1812 InputMethodContext::CallbackData Controller::OnInputMethodContextEvent(InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent)
1813 {
1814   return EventHandler::OnInputMethodContextEvent(*this, inputMethodContext, inputMethodContextEvent);
1815 }
1816
1817 void Controller::PasteClipboardItemEvent()
1818 {
1819   EventHandler::PasteClipboardItemEvent(*this);
1820 }
1821
1822 // protected : Inherit from Text::Decorator::ControllerInterface.
1823
1824 void Controller::GetTargetSize(Vector2& targetSize)
1825 {
1826   targetSize = mImpl->mModel->mVisualModel->mControlSize;
1827 }
1828
1829 void Controller::AddDecoration(Actor& actor, bool needsClipping)
1830 {
1831   if(NULL != mImpl->mEditableControlInterface)
1832   {
1833     mImpl->mEditableControlInterface->AddDecoration(actor, needsClipping);
1834   }
1835 }
1836
1837 bool Controller::IsEditable() const
1838 {
1839   return mImpl->IsEditable();
1840 }
1841
1842 void Controller::SetEditable(bool editable)
1843 {
1844   mImpl->SetEditable(editable);
1845   if(mImpl->mEventData && mImpl->mEventData->mDecorator)
1846   {
1847     mImpl->mEventData->mDecorator->SetEditable(editable);
1848   }
1849 }
1850
1851 void Controller::ScrollBy(Vector2 scroll)
1852 {
1853   if(mImpl->mEventData && (fabs(scroll.x) > Math::MACHINE_EPSILON_0 || fabs(scroll.y) > Math::MACHINE_EPSILON_0))
1854   {
1855     const Vector2& layoutSize    = mImpl->mModel->mVisualModel->GetLayoutSize();
1856     const Vector2  currentScroll = mImpl->mModel->mScrollPosition;
1857
1858     scroll.x = -scroll.x;
1859     scroll.y = -scroll.y;
1860
1861     if(fabs(scroll.x) > Math::MACHINE_EPSILON_0)
1862     {
1863       mImpl->mModel->mScrollPosition.x += scroll.x;
1864       mImpl->ClampHorizontalScroll(layoutSize);
1865     }
1866
1867     if(fabs(scroll.y) > Math::MACHINE_EPSILON_0)
1868     {
1869       mImpl->mModel->mScrollPosition.y += scroll.y;
1870       mImpl->ClampVerticalScroll(layoutSize);
1871     }
1872
1873     if(mImpl->mModel->mScrollPosition != currentScroll)
1874     {
1875       mImpl->mEventData->mDecorator->UpdatePositions(mImpl->mModel->mScrollPosition - currentScroll);
1876       mImpl->RequestRelayout();
1877     }
1878   }
1879 }
1880
1881 float Controller::GetHorizontalScrollPosition()
1882 {
1883   if(mImpl->mEventData)
1884   {
1885     //scroll values are negative internally so we convert them to positive numbers
1886     return -mImpl->mModel->mScrollPosition.x;
1887   }
1888   return 0;
1889 }
1890
1891 float Controller::GetVerticalScrollPosition()
1892 {
1893   if(mImpl->mEventData)
1894   {
1895     //scroll values are negative internally so we convert them to positive numbers
1896     return -mImpl->mModel->mScrollPosition.y;
1897   }
1898   return 0;
1899 }
1900
1901 void Controller::DecorationEvent(HandleType handleType, HandleState state, float x, float y)
1902 {
1903   EventHandler::DecorationEvent(*this, handleType, state, x, y);
1904 }
1905
1906 // protected : Inherit from TextSelectionPopup::TextPopupButtonCallbackInterface.
1907
1908 void Controller::TextPopupButtonTouched(Dali::Toolkit::TextSelectionPopup::Buttons button)
1909 {
1910   EventHandler::TextPopupButtonTouched(*this, button);
1911 }
1912
1913 void Controller::DisplayTimeExpired()
1914 {
1915   mImpl->mEventData->mUpdateCursorPosition = true;
1916   // Apply modifications to the model
1917   mImpl->mOperationsPending = ALL_OPERATIONS;
1918
1919   mImpl->RequestRelayout();
1920 }
1921
1922 // private : Update.
1923
1924 void Controller::InsertText(const std::string& text, Controller::InsertType type)
1925 {
1926   TextUpdater::InsertText(*this, text, type);
1927 }
1928
1929 void Controller::PasteText(const std::string& stringToPaste)
1930 {
1931   TextUpdater::PasteText(*this, stringToPaste);
1932 }
1933
1934 bool Controller::RemoveText(int                  cursorOffset,
1935                             int                  numberOfCharacters,
1936                             UpdateInputStyleType type)
1937 {
1938   return TextUpdater::RemoveText(*this, cursorOffset, numberOfCharacters, type);
1939 }
1940
1941 bool Controller::RemoveSelectedText()
1942 {
1943   return TextUpdater::RemoveSelectedText(*this);
1944 }
1945
1946 void Controller::InsertTextAnchor(int            numberOfCharacters,
1947                                   CharacterIndex previousCursorIndex)
1948 {
1949   TextUpdater::InsertTextAnchor(*this, numberOfCharacters, previousCursorIndex);
1950 }
1951
1952 void Controller::RemoveTextAnchor(int            cursorOffset,
1953                                   int            numberOfCharacters,
1954                                   CharacterIndex previousCursorIndex)
1955 {
1956   TextUpdater::RemoveTextAnchor(*this, cursorOffset, numberOfCharacters, previousCursorIndex);
1957 }
1958
1959 // private : Relayout.
1960
1961 bool Controller::DoRelayout(const Size&    size,
1962                             OperationsMask operationsRequired,
1963                             Size&          layoutSize)
1964 {
1965   return Relayouter::DoRelayout(*this, size, operationsRequired, layoutSize);
1966 }
1967
1968 void Controller::CalculateVerticalOffset(const Size& controlSize)
1969 {
1970   Relayouter::CalculateVerticalOffset(*this, controlSize);
1971 }
1972
1973 // private : Events.
1974
1975 void Controller::ProcessModifyEvents()
1976 {
1977   EventHandler::ProcessModifyEvents(*this);
1978 }
1979
1980 void Controller::TextReplacedEvent()
1981 {
1982   EventHandler::TextReplacedEvent(*this);
1983 }
1984
1985 void Controller::TextInsertedEvent()
1986 {
1987   EventHandler::TextInsertedEvent(*this);
1988 }
1989
1990 void Controller::TextDeletedEvent()
1991 {
1992   EventHandler::TextDeletedEvent(*this);
1993 }
1994
1995 bool Controller::DeleteEvent(int keyCode)
1996 {
1997   return EventHandler::DeleteEvent(*this, keyCode);
1998 }
1999
2000 // private : Helpers.
2001
2002 void Controller::ResetText()
2003 {
2004   TextUpdater::ResetText(*this);
2005 }
2006
2007 void Controller::ShowPlaceholderText()
2008 {
2009   PlaceholderHandler::ShowPlaceholderText(*this);
2010 }
2011
2012 void Controller::ClearFontData()
2013 {
2014   if(mImpl->mFontDefaults)
2015   {
2016     mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
2017   }
2018
2019   // Set flags to update the model.
2020   mImpl->mTextUpdateInfo.mCharacterIndex             = 0u;
2021   mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
2022   mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = mImpl->mModel->mLogicalModel->mText.Count();
2023
2024   mImpl->mTextUpdateInfo.mClearAll           = true;
2025   mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
2026   mImpl->mRecalculateNaturalSize             = true;
2027
2028   mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
2029                                                           VALIDATE_FONTS |
2030                                                           SHAPE_TEXT |
2031                                                           BIDI_INFO |
2032                                                           GET_GLYPH_METRICS |
2033                                                           LAYOUT |
2034                                                           UPDATE_LAYOUT_SIZE |
2035                                                           REORDER |
2036                                                           ALIGN);
2037 }
2038
2039 void Controller::ClearStyleData()
2040 {
2041   mImpl->mModel->mLogicalModel->mColorRuns.Clear();
2042   mImpl->mModel->mLogicalModel->ClearFontDescriptionRuns();
2043 }
2044
2045 void Controller::ResetCursorPosition(CharacterIndex cursorIndex)
2046 {
2047   // Reset the cursor position
2048   if(NULL != mImpl->mEventData)
2049   {
2050     mImpl->mEventData->mPrimaryCursorPosition = cursorIndex;
2051
2052     // Update the cursor if it's in editing mode.
2053     if(EventData::IsEditingState(mImpl->mEventData->mState))
2054     {
2055       mImpl->mEventData->mUpdateCursorPosition = true;
2056     }
2057   }
2058 }
2059
2060 CharacterIndex Controller::GetCursorPosition()
2061 {
2062   if(!mImpl->mEventData)
2063     return 0;
2064
2065   return mImpl->mEventData->mPrimaryCursorPosition;
2066 }
2067
2068 void Controller::ResetScrollPosition()
2069 {
2070   if(NULL != mImpl->mEventData)
2071   {
2072     // Reset the scroll position.
2073     mImpl->mModel->mScrollPosition                = Vector2::ZERO;
2074     mImpl->mEventData->mScrollAfterUpdatePosition = true;
2075   }
2076 }
2077
2078 void Controller::SetControlInterface(ControlInterface* controlInterface)
2079 {
2080   mImpl->mControlInterface = controlInterface;
2081 }
2082
2083 void Controller::SetAnchorControlInterface(AnchorControlInterface* anchorControlInterface)
2084 {
2085   mImpl->mAnchorControlInterface = anchorControlInterface;
2086 }
2087
2088 bool Controller::ShouldClearFocusOnEscape() const
2089 {
2090   return mImpl->mShouldClearFocusOnEscape;
2091 }
2092
2093 Actor Controller::CreateBackgroundActor()
2094 {
2095   return mImpl->CreateBackgroundActor();
2096 }
2097
2098 // private : Private contructors & copy operator.
2099
2100 Controller::Controller()
2101 : Controller(nullptr, nullptr, nullptr, nullptr)
2102 {
2103 }
2104
2105 Controller::Controller(ControlInterface* controlInterface)
2106 : Controller(controlInterface, nullptr, nullptr, nullptr)
2107 {
2108 }
2109
2110 Controller::Controller(ControlInterface*           controlInterface,
2111                        EditableControlInterface*   editableControlInterface,
2112                        SelectableControlInterface* selectableControlInterface,
2113                        AnchorControlInterface*     anchorControlInterface)
2114 : mImpl(new Controller::Impl(controlInterface, editableControlInterface, selectableControlInterface, anchorControlInterface))
2115 {
2116 }
2117
2118 // The copy constructor and operator are left unimplemented.
2119
2120 // protected : Destructor.
2121
2122 Controller::~Controller()
2123 {
2124   delete mImpl;
2125 }
2126
2127 } // namespace Text
2128
2129 } // namespace Toolkit
2130
2131 } // namespace Dali