c08b897653a2da5b4e5db7755a2838649a7cb0cc
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / text-controls / text-editor-impl.cpp
1 /*
2  * Copyright (c) 2017 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/controls/text-controls/text-editor-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <cstring>
23 #include <limits>
24 #include <dali/public-api/adaptor-framework/key.h>
25 #include <dali/public-api/common/stage.h>
26 #include <dali/public-api/images/resource-image.h>
27 #include <dali/devel-api/object/property-helper-devel.h>
28 #include <dali/public-api/object/type-registry-helper.h>
29 #include <dali/integration-api/adaptors/adaptor.h>
30 #include <dali/integration-api/debug.h>
31
32 // INTERNAL INCLUDES
33 #include <dali-toolkit/public-api/text/rendering-backend.h>
34 #include <dali-toolkit/public-api/visuals/color-visual-properties.h>
35 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
36 #include <dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h>
37 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
38 #include <dali-toolkit/internal/text/rendering/text-backend.h>
39 #include <dali-toolkit/internal/text/text-effects-style.h>
40 #include <dali-toolkit/internal/text/text-font-style.h>
41 #include <dali-toolkit/internal/text/text-view.h>
42 #include <dali-toolkit/internal/styling/style-manager-impl.h>
43
44 using namespace Dali::Toolkit::Text;
45
46 namespace Dali
47 {
48
49 namespace Toolkit
50 {
51
52 namespace Internal
53 {
54
55 namespace // unnamed namespace
56 {
57
58 #if defined(DEBUG_ENABLED)
59 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_CONTROLS");
60 #endif
61
62 const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND;
63 const float DEFAULT_SCROLL_SPEED = 1200.f; ///< The default scroll speed for the text editor in pixels/second.
64 } // unnamed namespace
65
66 namespace
67 {
68
69 const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] =
70 {
71   { "BEGIN",  Toolkit::Text::Layout::HORIZONTAL_ALIGN_BEGIN  },
72   { "CENTER", Toolkit::Text::Layout::HORIZONTAL_ALIGN_CENTER },
73   { "END",    Toolkit::Text::Layout::HORIZONTAL_ALIGN_END    },
74 };
75 const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE ) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] );
76
77 const char* const SCROLL_BAR_POSITION("sourcePosition");
78 const char* const SCROLL_BAR_POSITION_MIN("sourcePositionMin");
79 const char* const SCROLL_BAR_POSITION_MAX("sourcePositionMax");
80 const char* const SCROLL_BAR_CONTENT_SIZE("sourceContentSize");
81
82 // Type registration
83 BaseHandle Create()
84 {
85   return Toolkit::TextEditor::New();
86 }
87
88 // Setup properties, signals and actions using the type-registry.
89 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextEditor, Toolkit::Control, Create );
90
91 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "renderingBackend",                     INTEGER,   RENDERING_BACKEND                    )
92 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "text",                                 STRING,    TEXT                                 )
93 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "textColor",                            VECTOR4,   TEXT_COLOR                           )
94 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "fontFamily",                           STRING,    FONT_FAMILY                          )
95 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "fontStyle",                            MAP,       FONT_STYLE                           )
96 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "pointSize",                            FLOAT,     POINT_SIZE                           )
97 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "horizontalAlignment",                  STRING,    HORIZONTAL_ALIGNMENT                 )
98 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "scrollThreshold",                      FLOAT,     SCROLL_THRESHOLD                     )
99 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "scrollSpeed",                          FLOAT,     SCROLL_SPEED                         )
100 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "primaryCursorColor",                   VECTOR4,   PRIMARY_CURSOR_COLOR                 )
101 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "secondaryCursorColor",                 VECTOR4,   SECONDARY_CURSOR_COLOR               )
102 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "enableCursorBlink",                    BOOLEAN,   ENABLE_CURSOR_BLINK                  )
103 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "cursorBlinkInterval",                  FLOAT,     CURSOR_BLINK_INTERVAL                )
104 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "cursorBlinkDuration",                  FLOAT,     CURSOR_BLINK_DURATION                )
105 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "cursorWidth",                          INTEGER,   CURSOR_WIDTH                         )
106 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "grabHandleImage",                      STRING,    GRAB_HANDLE_IMAGE                    )
107 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "grabHandlePressedImage",               STRING,    GRAB_HANDLE_PRESSED_IMAGE            )
108 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHandleImageLeft",             MAP,       SELECTION_HANDLE_IMAGE_LEFT          )
109 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHandleImageRight",            MAP,       SELECTION_HANDLE_IMAGE_RIGHT         )
110 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHandlePressedImageLeft",      MAP,       SELECTION_HANDLE_PRESSED_IMAGE_LEFT  )
111 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHandlePressedImageRight",     MAP,       SELECTION_HANDLE_PRESSED_IMAGE_RIGHT )
112 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHandleMarkerImageLeft",       MAP,       SELECTION_HANDLE_MARKER_IMAGE_LEFT   )
113 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHandleMarkerImageRight",      MAP,       SELECTION_HANDLE_MARKER_IMAGE_RIGHT  )
114 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHighlightColor",              VECTOR4,   SELECTION_HIGHLIGHT_COLOR            )
115 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "decorationBoundingBox",                RECTANGLE, DECORATION_BOUNDING_BOX              )
116 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "enableMarkup",                         BOOLEAN,   ENABLE_MARKUP                        )
117 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputColor",                           VECTOR4,   INPUT_COLOR                          )
118 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputFontFamily",                      STRING,    INPUT_FONT_FAMILY                    )
119 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputFontStyle",                       MAP,       INPUT_FONT_STYLE                     )
120 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputPointSize",                       FLOAT,     INPUT_POINT_SIZE                     )
121 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "lineSpacing",                          FLOAT,     LINE_SPACING                         )
122 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputLineSpacing",                     FLOAT,     INPUT_LINE_SPACING                   )
123 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "underline",                            MAP,       UNDERLINE                            )
124 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputUnderline",                       MAP,       INPUT_UNDERLINE                      )
125 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "shadow",                               MAP,       SHADOW                               )
126 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputShadow",                          MAP,       INPUT_SHADOW                         )
127 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "emboss",                               MAP,       EMBOSS                               )
128 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputEmboss",                          MAP,       INPUT_EMBOSS                         )
129 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "outline",                              MAP,       OUTLINE                              )
130 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputOutline",                         MAP,       INPUT_OUTLINE                        )
131 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "smoothScroll",                   BOOLEAN,   SMOOTH_SCROLL                        )
132 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "smoothScrollDuration",           FLOAT,     SMOOTH_SCROLL_DURATION               )
133 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "enableScrollBar",                BOOLEAN,   ENABLE_SCROLL_BAR                    )
134 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "scrollBarShowDuration",          FLOAT,     SCROLL_BAR_SHOW_DURATION             )
135 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "scrollBarFadeDuration",          FLOAT,     SCROLL_BAR_FADE_DURATION             )
136
137 DALI_SIGNAL_REGISTRATION( Toolkit, TextEditor, "textChanged",        SIGNAL_TEXT_CHANGED )
138 DALI_SIGNAL_REGISTRATION( Toolkit, TextEditor, "inputStyleChanged",  SIGNAL_INPUT_STYLE_CHANGED )
139
140 DALI_TYPE_REGISTRATION_END()
141
142 } // namespace
143
144 Toolkit::TextEditor TextEditor::New()
145 {
146   // Create the implementation, temporarily owned by this handle on stack
147   IntrusivePtr< TextEditor > impl = new TextEditor();
148
149   // Pass ownership to CustomActor handle
150   Toolkit::TextEditor handle( *impl );
151
152   // Second-phase init of the implementation
153   // This can only be done after the CustomActor connection has been made...
154   impl->Initialize();
155
156   return handle;
157 }
158
159 void TextEditor::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
160 {
161   Toolkit::TextEditor textEditor = Toolkit::TextEditor::DownCast( Dali::BaseHandle( object ) );
162
163   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor SetProperty\n");
164
165
166   if( textEditor )
167   {
168     TextEditor& impl( GetImpl( textEditor ) );
169
170     switch( index )
171     {
172       case Toolkit::TextEditor::Property::RENDERING_BACKEND:
173       {
174         int backend = value.Get< int >();
175         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p RENDERING_BACKEND %d\n", impl.mController.Get(), backend );
176
177         if( impl.mRenderingBackend != backend )
178         {
179           impl.mRenderingBackend = backend;
180           impl.mRenderer.Reset();
181           impl.RequestTextRelayout();
182         }
183         break;
184       }
185       case Toolkit::TextEditor::Property::TEXT:
186       {
187         if( impl.mController )
188         {
189           const std::string& text = value.Get< std::string >();
190           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p TEXT %s\n", impl.mController.Get(), text.c_str() );
191
192           impl.mController->SetText( text );
193         }
194         break;
195       }
196       case Toolkit::TextEditor::Property::TEXT_COLOR:
197       {
198         if( impl.mController )
199         {
200           const Vector4& textColor = value.Get< Vector4 >();
201           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p TEXT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), textColor.r, textColor.g, textColor.b, textColor.a );
202
203           if( impl.mController->GetDefaultColor() != textColor )
204           {
205             impl.mController->SetDefaultColor( textColor );
206             impl.mController->SetInputColor( textColor );
207             impl.mRenderer.Reset();
208           }
209         }
210         break;
211       }
212       case Toolkit::TextEditor::Property::FONT_FAMILY:
213       {
214         if( impl.mController )
215         {
216           const std::string& fontFamily = value.Get< std::string >();
217           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p FONT_FAMILY %s\n", impl.mController.Get(), fontFamily.c_str() );
218           impl.mController->SetDefaultFontFamily( fontFamily );
219         }
220         break;
221       }
222       case Toolkit::TextEditor::Property::FONT_STYLE:
223       {
224         SetFontStyleProperty( impl.mController, value, Text::FontStyle::DEFAULT );
225         break;
226       }
227       case Toolkit::TextEditor::Property::POINT_SIZE:
228       {
229         if( impl.mController )
230         {
231           const float pointSize = value.Get< float >();
232           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p POINT_SIZE %f\n", impl.mController.Get(), pointSize );
233
234           if( !Equals( impl.mController->GetDefaultPointSize(), pointSize ) )
235           {
236             impl.mController->SetDefaultPointSize( pointSize );
237           }
238         }
239         break;
240       }
241       case Toolkit::TextEditor::Property::HORIZONTAL_ALIGNMENT:
242       {
243         if( impl.mController )
244         {
245           const std::string& alignStr = value.Get< std::string >();
246           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p HORIZONTAL_ALIGNMENT %s\n", impl.mController.Get(), alignStr.c_str() );
247
248           Layout::HorizontalAlignment alignment( Layout::HORIZONTAL_ALIGN_BEGIN );
249           if( Scripting::GetEnumeration< Layout::HorizontalAlignment >( alignStr.c_str(),
250                                                                         HORIZONTAL_ALIGNMENT_STRING_TABLE,
251                                                                         HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT,
252                                                                         alignment ) )
253           {
254             impl.mController->SetHorizontalAlignment( alignment );
255           }
256         }
257         break;
258       }
259       case Toolkit::TextEditor::Property::SCROLL_THRESHOLD:
260       {
261         const float threshold = value.Get< float >();
262         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p SCROLL_THRESHOLD %f\n", impl.mController.Get(), threshold );
263
264         if( impl.mDecorator )
265         {
266           impl.mDecorator->SetScrollThreshold( threshold );
267         }
268         break;
269       }
270       case Toolkit::TextEditor::Property::SCROLL_SPEED:
271       {
272         const float speed = value.Get< float >();
273         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p SCROLL_SPEED %f\n", impl.mController.Get(), speed );
274
275         if( impl.mDecorator )
276         {
277           impl.mDecorator->SetScrollSpeed( speed );
278         }
279         break;
280       }
281       case Toolkit::TextEditor::Property::PRIMARY_CURSOR_COLOR:
282       {
283         if( impl.mDecorator )
284         {
285           const Vector4& color = value.Get< Vector4 >();
286           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p PRIMARY_CURSOR_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a );
287
288           impl.mDecorator->SetCursorColor( PRIMARY_CURSOR, color );
289           impl.RequestTextRelayout();
290         }
291         break;
292       }
293       case Toolkit::TextEditor::Property::SECONDARY_CURSOR_COLOR:
294       {
295         if( impl.mDecorator )
296         {
297           const Vector4& color = value.Get< Vector4 >();
298           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p SECONDARY_CURSOR_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a );
299
300           impl.mDecorator->SetCursorColor( SECONDARY_CURSOR, color );
301           impl.RequestTextRelayout();
302         }
303         break;
304       }
305       case Toolkit::TextEditor::Property::ENABLE_CURSOR_BLINK:
306       {
307         if( impl.mController )
308         {
309           const bool enable = value.Get< bool >();
310           DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p ENABLE_CURSOR_BLINK %d\n", impl.mController.Get(), enable );
311
312           impl.mController->SetEnableCursorBlink( enable );
313           impl.RequestTextRelayout();
314         }
315         break;
316       }
317       case Toolkit::TextEditor::Property::CURSOR_BLINK_INTERVAL:
318       {
319         if( impl.mDecorator )
320         {
321           const float interval = value.Get< float >();
322           DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p CURSOR_BLINK_INTERVAL %f\n", impl.mController.Get(), interval );
323
324           impl.mDecorator->SetCursorBlinkInterval( interval );
325         }
326         break;
327       }
328       case Toolkit::TextEditor::Property::CURSOR_BLINK_DURATION:
329       {
330         if( impl.mDecorator )
331         {
332           const float duration = value.Get< float >();
333           DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p CURSOR_BLINK_DURATION %f\n", impl.mController.Get(), duration );
334
335           impl.mDecorator->SetCursorBlinkDuration( duration );
336         }
337         break;
338       }
339       case Toolkit::TextEditor::Property::CURSOR_WIDTH:
340       {
341         if( impl.mDecorator )
342         {
343           const int width = value.Get< int >();
344           DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p CURSOR_WIDTH %d\n", impl.mController.Get(), width );
345
346           impl.mDecorator->SetCursorWidth( width );
347           impl.mController->GetLayoutEngine().SetCursorWidth( width );
348         }
349         break;
350       }
351       case Toolkit::TextEditor::Property::GRAB_HANDLE_IMAGE:
352       {
353         const ResourceImage image = ResourceImage::New( value.Get< std::string >() );
354         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p GRAB_HANDLE_IMAGE %s\n", impl.mController.Get(), image.GetUrl().c_str() );
355
356         if( impl.mDecorator )
357         {
358           impl.mDecorator->SetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_RELEASED, image );
359           impl.RequestTextRelayout();
360         }
361         break;
362       }
363       case Toolkit::TextEditor::Property::GRAB_HANDLE_PRESSED_IMAGE:
364       {
365         const ResourceImage image = ResourceImage::New( value.Get< std::string >() );
366         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p GRAB_HANDLE_PRESSED_IMAGE %s\n", impl.mController.Get(), image.GetUrl().c_str() );
367
368         if( impl.mDecorator )
369         {
370           impl.mDecorator->SetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_PRESSED, image );
371           impl.RequestTextRelayout();
372         }
373         break;
374       }
375       case Toolkit::TextEditor::Property::SELECTION_HANDLE_IMAGE_LEFT:
376       {
377         const Image image = Scripting::NewImage( value );
378
379         if( impl.mDecorator && image )
380         {
381           impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED, image );
382           impl.RequestTextRelayout();
383         }
384         break;
385       }
386       case Toolkit::TextEditor::Property::SELECTION_HANDLE_IMAGE_RIGHT:
387       {
388         const Image image = Scripting::NewImage( value );
389
390         if( impl.mDecorator && image )
391         {
392           impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED, image );
393           impl.RequestTextRelayout();
394         }
395         break;
396       }
397       case Toolkit::TextEditor::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT:
398       {
399         const Image image = Scripting::NewImage( value );
400
401         if( impl.mDecorator && image )
402         {
403           impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED, image );
404           impl.RequestTextRelayout();
405         }
406         break;
407       }
408       case Toolkit::TextEditor::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT:
409       {
410         const Image image = Scripting::NewImage( value );
411
412         if( impl.mDecorator && image )
413         {
414           impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED, image );
415           impl.RequestTextRelayout();
416         }
417         break;
418       }
419       case Toolkit::TextEditor::Property::SELECTION_HANDLE_MARKER_IMAGE_LEFT:
420       {
421         const Image image = Scripting::NewImage( value );
422
423         if( impl.mDecorator && image )
424         {
425           impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED, image );
426           impl.RequestTextRelayout();
427         }
428         break;
429       }
430       case Toolkit::TextEditor::Property::SELECTION_HANDLE_MARKER_IMAGE_RIGHT:
431       {
432         const Image image = Scripting::NewImage( value );
433
434         if( impl.mDecorator && image )
435         {
436           impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED, image );
437           impl.RequestTextRelayout();
438         }
439         break;
440       }
441       case Toolkit::TextEditor::Property::SELECTION_HIGHLIGHT_COLOR:
442       {
443         const Vector4 color = value.Get< Vector4 >();
444         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p SELECTION_HIGHLIGHT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), color.r, color.g, color.b, color.a );
445
446         if( impl.mDecorator )
447         {
448           impl.mDecorator->SetHighlightColor( color );
449           impl.RequestTextRelayout();
450         }
451         break;
452       }
453       case Toolkit::TextEditor::Property::DECORATION_BOUNDING_BOX:
454       {
455         if( impl.mDecorator )
456         {
457           const Rect<int>& box = value.Get< Rect<int> >();
458           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p DECORATION_BOUNDING_BOX %d,%d %dx%d\n", impl.mController.Get(), box.x, box.y, box.width, box.height );
459
460           impl.mDecorator->SetBoundingBox( box );
461           impl.RequestTextRelayout();
462         }
463         break;
464       }
465       case Toolkit::TextEditor::Property::ENABLE_MARKUP:
466       {
467         if( impl.mController )
468         {
469           const bool enableMarkup = value.Get<bool>();
470           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p ENABLE_MARKUP %d\n", impl.mController.Get(), enableMarkup );
471
472           impl.mController->SetMarkupProcessorEnabled( enableMarkup );
473         }
474         break;
475       }
476       case Toolkit::TextEditor::Property::INPUT_COLOR:
477       {
478         if( impl.mController )
479         {
480           const Vector4& inputColor = value.Get< Vector4 >();
481           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p INPUT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), inputColor.r, inputColor.g, inputColor.b, inputColor.a );
482
483           impl.mController->SetInputColor( inputColor );
484         }
485         break;
486       }
487       case Toolkit::TextEditor::Property::INPUT_FONT_FAMILY:
488       {
489         if( impl.mController )
490         {
491           const std::string& fontFamily = value.Get< std::string >();
492           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p INPUT_FONT_FAMILY %s\n", impl.mController.Get(), fontFamily.c_str() );
493           impl.mController->SetInputFontFamily( fontFamily );
494         }
495         break;
496       }
497       case Toolkit::TextEditor::Property::INPUT_FONT_STYLE:
498       {
499         SetFontStyleProperty( impl.mController, value, Text::FontStyle::INPUT );
500         break;
501       }
502       case Toolkit::TextEditor::Property::INPUT_POINT_SIZE:
503       {
504         if( impl.mController )
505         {
506           const float pointSize = value.Get< float >();
507           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p INPUT_POINT_SIZE %f\n", impl.mController.Get(), pointSize );
508           impl.mController->SetInputFontPointSize( pointSize );
509         }
510         break;
511       }
512       case Toolkit::TextEditor::Property::LINE_SPACING:
513       {
514         if( impl.mController )
515         {
516           const float lineSpacing = value.Get<float>();
517           impl.mController->SetDefaultLineSpacing( lineSpacing );
518           impl.mRenderer.Reset();
519         }
520         break;
521       }
522       case Toolkit::TextEditor::Property::INPUT_LINE_SPACING:
523       {
524         if( impl.mController )
525         {
526           const float lineSpacing = value.Get<float>();
527           impl.mController->SetInputLineSpacing( lineSpacing );
528           impl.mRenderer.Reset();
529         }
530         break;
531       }
532       case Toolkit::TextEditor::Property::UNDERLINE:
533       {
534         const bool update = SetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
535         if( update )
536         {
537           impl.mRenderer.Reset();
538         }
539         break;
540       }
541       case Toolkit::TextEditor::Property::INPUT_UNDERLINE:
542       {
543         const bool update = SetUnderlineProperties( impl.mController, value, Text::EffectStyle::INPUT );
544         if( update )
545         {
546           impl.mRenderer.Reset();
547         }
548         break;
549       }
550       case Toolkit::TextEditor::Property::SHADOW:
551       {
552         const bool update = SetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
553         if( update )
554         {
555           impl.mRenderer.Reset();
556         }
557         break;
558       }
559       case Toolkit::TextEditor::Property::INPUT_SHADOW:
560       {
561         const bool update = SetShadowProperties( impl.mController, value, Text::EffectStyle::INPUT );
562         if( update )
563         {
564           impl.mRenderer.Reset();
565         }
566         break;
567       }
568       case Toolkit::TextEditor::Property::EMBOSS:
569       {
570         const bool update = SetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
571         if( update )
572         {
573           impl.mRenderer.Reset();
574         }
575         break;
576       }
577       case Toolkit::TextEditor::Property::INPUT_EMBOSS:
578       {
579         const bool update = SetEmbossProperties( impl.mController, value, Text::EffectStyle::INPUT );
580         if( update )
581         {
582           impl.mRenderer.Reset();
583         }
584         break;
585       }
586       case Toolkit::TextEditor::Property::OUTLINE:
587       {
588         const bool update = SetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
589         if( update )
590         {
591           impl.mRenderer.Reset();
592         }
593         break;
594       }
595       case Toolkit::TextEditor::Property::INPUT_OUTLINE:
596       {
597         const bool update = SetOutlineProperties( impl.mController, value, Text::EffectStyle::INPUT );
598         if( update )
599         {
600           impl.mRenderer.Reset();
601         }
602         break;
603       }
604       case Toolkit::DevelTextEditor::Property::SMOOTH_SCROLL:
605       {
606         const bool enable = value.Get< bool >();
607         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor SMOOTH_SCROLL %d\n", enable );
608
609         impl.mScrollAnimationEnabled = enable;
610         break;
611       }
612       case Toolkit::DevelTextEditor::Property::SMOOTH_SCROLL_DURATION:
613       {
614         const float duration = value.Get< float >();
615         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor SMOOTH_SCROLL_DURATION %f\n", duration );
616
617         impl.mScrollAnimationDuration = duration;
618         if ( impl.mTextVerticalScroller )
619         {
620           impl.mTextVerticalScroller->SetDuration( duration );
621         }
622         break;
623       }
624       case Toolkit::DevelTextEditor::Property::ENABLE_SCROLL_BAR:
625       {
626         const bool enable = value.Get< bool >();
627         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor SHOW_SCROLL_BAR %d\n", enable );
628
629         impl.mScrollBarEnabled = enable;
630         break;
631       }
632       case Toolkit::DevelTextEditor::Property::SCROLL_BAR_SHOW_DURATION:
633       {
634         const float duration = value.Get< float >();
635         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor SCROLL_BAR_SHOW_DURATION %f\n", duration );
636
637         impl.mAnimationPeriod.delaySeconds = duration;
638         break;
639       }
640       case Toolkit::DevelTextEditor::Property::SCROLL_BAR_FADE_DURATION:
641       {
642         const float duration = value.Get< float >();
643         DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor SCROLL_BAR_FADE_DURATION %f\n", duration );
644
645         impl.mAnimationPeriod.durationSeconds = duration;
646         break;
647       }
648     } // switch
649   } // texteditor
650 }
651
652 Property::Value TextEditor::GetProperty( BaseObject* object, Property::Index index )
653 {
654   Property::Value value;
655
656   Toolkit::TextEditor textEditor = Toolkit::TextEditor::DownCast( Dali::BaseHandle( object ) );
657
658   if( textEditor )
659   {
660     TextEditor& impl( GetImpl( textEditor ) );
661
662     switch( index )
663     {
664       case Toolkit::TextEditor::Property::RENDERING_BACKEND:
665       {
666         value = impl.mRenderingBackend;
667         break;
668       }
669       case Toolkit::TextEditor::Property::TEXT:
670       {
671         if( impl.mController )
672         {
673           std::string text;
674           impl.mController->GetText( text );
675           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p returning text: %s\n", impl.mController.Get(), text.c_str() );
676           value = text;
677         }
678         break;
679       }
680       case Toolkit::TextEditor::Property::TEXT_COLOR:
681       {
682         if ( impl.mController )
683         {
684           value = impl.mController->GetDefaultColor();
685         }
686         break;
687       }
688       case Toolkit::TextEditor::Property::FONT_FAMILY:
689       {
690         if( impl.mController )
691         {
692           value = impl.mController->GetDefaultFontFamily();
693         }
694         break;
695       }
696       case Toolkit::TextEditor::Property::FONT_STYLE:
697       {
698         GetFontStyleProperty( impl.mController, value, Text::FontStyle::DEFAULT );
699         break;
700       }
701       case Toolkit::TextEditor::Property::POINT_SIZE:
702       {
703         if( impl.mController )
704         {
705           value = impl.mController->GetDefaultPointSize();
706         }
707         break;
708       }
709       case Toolkit::TextEditor::Property::HORIZONTAL_ALIGNMENT:
710       {
711         if( impl.mController )
712         {
713           const char* name = Scripting::GetEnumerationName< Toolkit::Text::Layout::HorizontalAlignment >( impl.mController->GetHorizontalAlignment(),
714                                                                                                           HORIZONTAL_ALIGNMENT_STRING_TABLE,
715                                                                                                           HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT );
716           if( name )
717           {
718             value = std::string( name );
719           }
720         }
721         break;
722       }
723       case Toolkit::TextEditor::Property::SCROLL_THRESHOLD:
724       {
725         if( impl.mDecorator )
726         {
727           value = impl.mDecorator->GetScrollThreshold();
728         }
729         break;
730       }
731       case Toolkit::TextEditor::Property::SCROLL_SPEED:
732       {
733         if( impl.mDecorator )
734         {
735           value = impl.mDecorator->GetScrollSpeed();
736         }
737         break;
738       }
739       case Toolkit::TextEditor::Property::PRIMARY_CURSOR_COLOR:
740       {
741         if( impl.mDecorator )
742         {
743           value = impl.mDecorator->GetColor( PRIMARY_CURSOR );
744         }
745         break;
746       }
747       case Toolkit::TextEditor::Property::SECONDARY_CURSOR_COLOR:
748       {
749         if( impl.mDecorator )
750         {
751           value = impl.mDecorator->GetColor( SECONDARY_CURSOR );
752         }
753         break;
754       }
755       case Toolkit::TextEditor::Property::ENABLE_CURSOR_BLINK:
756       {
757         value = impl.mController->GetEnableCursorBlink();
758         break;
759       }
760       case Toolkit::TextEditor::Property::CURSOR_BLINK_INTERVAL:
761       {
762         if( impl.mDecorator )
763         {
764           value = impl.mDecorator->GetCursorBlinkInterval();
765         }
766         break;
767       }
768       case Toolkit::TextEditor::Property::CURSOR_BLINK_DURATION:
769       {
770         if( impl.mDecorator )
771         {
772           value = impl.mDecorator->GetCursorBlinkDuration();
773         }
774         break;
775       }
776       case Toolkit::TextEditor::Property::CURSOR_WIDTH:
777       {
778         if( impl.mDecorator )
779         {
780           value = impl.mDecorator->GetCursorWidth();
781         }
782         break;
783       }
784       case Toolkit::TextEditor::Property::GRAB_HANDLE_IMAGE:
785       {
786         if( impl.mDecorator )
787         {
788           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_RELEASED ) );
789           if( image )
790           {
791             value = image.GetUrl();
792           }
793         }
794         break;
795       }
796       case Toolkit::TextEditor::Property::GRAB_HANDLE_PRESSED_IMAGE:
797       {
798         if( impl.mDecorator )
799         {
800           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_PRESSED ) );
801           if( image )
802           {
803             value = image.GetUrl();
804           }
805         }
806         break;
807       }
808       case Toolkit::TextEditor::Property::SELECTION_HANDLE_IMAGE_LEFT:
809       {
810         impl.GetHandleImagePropertyValue( value, LEFT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED );
811         break;
812       }
813       case Toolkit::TextEditor::Property::SELECTION_HANDLE_IMAGE_RIGHT:
814       {
815         impl.GetHandleImagePropertyValue( value, RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED ) ;
816         break;
817       }
818       case Toolkit::TextEditor::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT:
819       {
820         impl.GetHandleImagePropertyValue( value, LEFT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED );
821         break;
822       }
823       case Toolkit::TextEditor::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT:
824       {
825         impl.GetHandleImagePropertyValue( value, RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED );
826         break;
827       }
828       case Toolkit::TextEditor::Property::SELECTION_HANDLE_MARKER_IMAGE_LEFT:
829       {
830         impl.GetHandleImagePropertyValue( value, LEFT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED );
831         break;
832       }
833       case Toolkit::TextEditor::Property::SELECTION_HANDLE_MARKER_IMAGE_RIGHT:
834       {
835         impl.GetHandleImagePropertyValue( value, RIGHT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED );
836         break;
837       }
838       case Toolkit::TextEditor::Property::SELECTION_HIGHLIGHT_COLOR:
839       {
840         if( impl.mDecorator )
841         {
842           value = impl.mDecorator->GetHighlightColor();
843         }
844         break;
845       }
846       case Toolkit::TextEditor::Property::DECORATION_BOUNDING_BOX:
847       {
848         if( impl.mDecorator )
849         {
850           Rect<int> boundingBox;
851           impl.mDecorator->GetBoundingBox( boundingBox );
852           value = boundingBox;
853         }
854         break;
855       }
856       case Toolkit::TextEditor::Property::ENABLE_MARKUP:
857       {
858         if( impl.mController )
859         {
860           value = impl.mController->IsMarkupProcessorEnabled();
861         }
862         break;
863       }
864       case Toolkit::TextEditor::Property::INPUT_COLOR:
865       {
866         if( impl.mController )
867         {
868           value = impl.mController->GetInputColor();
869         }
870         break;
871       }
872       case Toolkit::TextEditor::Property::INPUT_FONT_FAMILY:
873       {
874         if( impl.mController )
875         {
876           value = impl.mController->GetInputFontFamily();
877         }
878         break;
879       }
880       case Toolkit::TextEditor::Property::INPUT_FONT_STYLE:
881       {
882         GetFontStyleProperty( impl.mController, value, Text::FontStyle::INPUT );
883         break;
884       }
885       case Toolkit::TextEditor::Property::INPUT_POINT_SIZE:
886       {
887         if( impl.mController )
888         {
889           value = impl.mController->GetInputFontPointSize();
890         }
891         break;
892       }
893       case Toolkit::TextEditor::Property::LINE_SPACING:
894       {
895         if( impl.mController )
896         {
897           value = impl.mController->GetDefaultLineSpacing();
898         }
899         break;
900       }
901       case Toolkit::TextEditor::Property::INPUT_LINE_SPACING:
902       {
903         if( impl.mController )
904         {
905           value = impl.mController->GetInputLineSpacing();
906         }
907         break;
908       }
909       case Toolkit::TextEditor::Property::UNDERLINE:
910       {
911         GetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
912         break;
913       }
914       case Toolkit::TextEditor::Property::INPUT_UNDERLINE:
915       {
916         GetUnderlineProperties( impl.mController, value, Text::EffectStyle::INPUT );
917         break;
918       }
919       case Toolkit::TextEditor::Property::SHADOW:
920       {
921         GetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
922         break;
923       }
924       case Toolkit::TextEditor::Property::INPUT_SHADOW:
925       {
926         GetShadowProperties( impl.mController, value, Text::EffectStyle::INPUT );
927         break;
928       }
929       case Toolkit::TextEditor::Property::EMBOSS:
930       {
931         GetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
932         break;
933       }
934       case Toolkit::TextEditor::Property::INPUT_EMBOSS:
935       {
936         GetEmbossProperties( impl.mController, value, Text::EffectStyle::INPUT );
937         break;
938       }
939       case Toolkit::TextEditor::Property::OUTLINE:
940       {
941         GetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
942         break;
943       }
944       case Toolkit::TextEditor::Property::INPUT_OUTLINE:
945       {
946         GetOutlineProperties( impl.mController, value, Text::EffectStyle::INPUT );
947         break;
948       }
949       case Toolkit::DevelTextEditor::Property::SMOOTH_SCROLL:
950       {
951         value = impl.mScrollAnimationEnabled;
952         break;
953       }
954       case Toolkit::DevelTextEditor::Property::SMOOTH_SCROLL_DURATION:
955       {
956         value = impl.mScrollAnimationDuration;
957         break;
958       }
959       case Toolkit::DevelTextEditor::Property::ENABLE_SCROLL_BAR:
960       {
961         value = impl.mScrollBarEnabled;
962         break;
963       }
964       case Toolkit::DevelTextEditor::Property::SCROLL_BAR_SHOW_DURATION:
965       {
966         value = impl.mAnimationPeriod.delaySeconds;
967         break;
968       }
969       case Toolkit::DevelTextEditor::Property::SCROLL_BAR_FADE_DURATION:
970       {
971         value = impl.mAnimationPeriod.durationSeconds;
972         break;
973       }
974     } //switch
975   }
976
977   return value;
978 }
979
980 bool TextEditor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
981 {
982   Dali::BaseHandle handle( object );
983
984   bool connected( true );
985   Toolkit::TextEditor editor = Toolkit::TextEditor::DownCast( handle );
986
987   if( 0 == strcmp( signalName.c_str(), SIGNAL_TEXT_CHANGED ) )
988   {
989     editor.TextChangedSignal().Connect( tracker, functor );
990   }
991   else if( 0 == strcmp( signalName.c_str(), SIGNAL_INPUT_STYLE_CHANGED ) )
992   {
993     editor.InputStyleChangedSignal().Connect( tracker, functor );
994   }
995   else
996   {
997     // signalName does not match any signal
998     connected = false;
999   }
1000
1001   return connected;
1002 }
1003
1004 Toolkit::TextEditor::TextChangedSignalType& TextEditor::TextChangedSignal()
1005 {
1006   return mTextChangedSignal;
1007 }
1008
1009 Toolkit::TextEditor::InputStyleChangedSignalType& TextEditor::InputStyleChangedSignal()
1010 {
1011   return mInputStyleChangedSignal;
1012 }
1013
1014 void TextEditor::OnInitialize()
1015 {
1016   Actor self = Self();
1017
1018   mController = Text::Controller::New( this, this );
1019
1020   mDecorator = Text::Decorator::New( *mController,
1021                                      *mController );
1022
1023   mController->GetLayoutEngine().SetLayout( Layout::Engine::MULTI_LINE_BOX );
1024
1025   // Enables the text input.
1026   mController->EnableTextInput( mDecorator );
1027
1028   // Enables the vertical scrolling after the text input has been enabled.
1029   mController->SetVerticalScrollEnabled( true );
1030
1031   // Disables the horizontal scrolling.
1032   mController->SetHorizontalScrollEnabled( false );
1033
1034   // Sets the maximum number of characters.
1035   mController->SetMaximumNumberOfCharacters( std::numeric_limits<Length>::max() );
1036
1037   // Enable the smooth handle panning.
1038   mController->SetSmoothHandlePanEnabled( true );
1039
1040   mController->SetNoTextDoubleTapAction( Controller::NoTextTap::HIGHLIGHT );
1041   mController->SetNoTextLongPressAction( Controller::NoTextTap::HIGHLIGHT );
1042
1043   // Forward input events to controller
1044   EnableGestureDetection( static_cast<Gesture::Type>( Gesture::Tap | Gesture::Pan | Gesture::LongPress ) );
1045   GetTapGestureDetector().SetMaximumTapsRequired( 2 );
1046
1047   mImfManager = ImfManager::Get();
1048
1049   self.TouchSignal().Connect( this, &TextEditor::OnTouched );
1050
1051   // Set BoundingBox to stage size if not already set.
1052   Rect<int> boundingBox;
1053   mDecorator->GetBoundingBox( boundingBox );
1054
1055   if( boundingBox.IsEmpty() )
1056   {
1057     Vector2 stageSize = Dali::Stage::GetCurrent().GetSize();
1058     mDecorator->SetBoundingBox( Rect<int>( 0.0f, 0.0f, stageSize.width, stageSize.height ) );
1059   }
1060
1061   // Whether to flip the selection handles as soon as they cross.
1062   mDecorator->FlipSelectionHandlesOnCrossEnabled( true );
1063
1064   // Set the default scroll speed.
1065   mDecorator->SetScrollSpeed( DEFAULT_SCROLL_SPEED );
1066
1067   // Fill-parent area by default
1068   self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
1069   self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
1070   self.OnStageSignal().Connect( this, &TextEditor::OnStageConnect );
1071
1072   // Creates an extra control to be used as stencil buffer.
1073   mStencil = Control::New();
1074   mStencil.SetAnchorPoint( AnchorPoint::CENTER );
1075   mStencil.SetParentOrigin( ParentOrigin::CENTER );
1076
1077   // Creates a background visual. Even if the color is transparent it updates the stencil.
1078   mStencil.SetProperty( Toolkit::Control::Property::BACKGROUND,
1079                         Property::Map().Add( Toolkit::Visual::Property::TYPE, DevelVisual::COLOR ).
1080                         Add( ColorVisual::Property::MIX_COLOR, Color::TRANSPARENT ) );
1081
1082   // Enable the clipping property.
1083   mStencil.SetProperty( Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN );
1084   mStencil.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
1085
1086   self.Add( mStencil );
1087 }
1088
1089 void TextEditor::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
1090 {
1091   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnStyleChange\n");
1092
1093   switch ( change )
1094   {
1095     case StyleChange::DEFAULT_FONT_CHANGE:
1096     {
1097       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnStyleChange DEFAULT_FONT_CHANGE\n");
1098       const std::string& newFont = GetImpl( styleManager ).GetDefaultFontFamily();
1099       // Property system did not set the font so should update it.
1100       mController->UpdateAfterFontChange( newFont );
1101       RelayoutRequest();
1102       break;
1103     }
1104
1105     case StyleChange::DEFAULT_FONT_SIZE_CHANGE:
1106     {
1107       GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
1108       RelayoutRequest();
1109       break;
1110     }
1111     case StyleChange::THEME_CHANGE:
1112     {
1113       // Nothing to do, let control base class handle this
1114       break;
1115     }
1116   }
1117
1118   // Up call to Control
1119   Control::OnStyleChange( styleManager, change );
1120 }
1121
1122 Vector3 TextEditor::GetNaturalSize()
1123 {
1124   return mController->GetNaturalSize();
1125 }
1126
1127 float TextEditor::GetHeightForWidth( float width )
1128 {
1129   return mController->GetHeightForWidth( width );
1130 }
1131
1132 void TextEditor::OnRelayout( const Vector2& size, RelayoutContainer& container )
1133 {
1134   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor OnRelayout\n");
1135
1136   const Text::Controller::UpdateTextType updateTextType = mController->Relayout( size );
1137
1138   if( ( Text::Controller::NONE_UPDATED != updateTextType ) ||
1139       !mRenderer )
1140   {
1141     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnRelayout %p Displaying new contents\n", mController.Get() );
1142
1143     if( mDecorator &&
1144         ( Text::Controller::NONE_UPDATED != ( Text::Controller::DECORATOR_UPDATED & updateTextType ) ) )
1145     {
1146       mDecorator->Relayout( size );
1147     }
1148
1149     if( !mRenderer )
1150     {
1151       mRenderer = Backend::Get().NewRenderer( mRenderingBackend );
1152     }
1153
1154     RenderText( updateTextType );
1155   }
1156
1157   // The text-editor emits signals when the input style changes. These changes of style are
1158   // detected during the relayout process (size negotiation), i.e after the cursor has been moved. Signals
1159   // can't be emitted during the size negotiation as the callbacks may update the UI.
1160   // The text-editor adds an idle callback to the adaptor to emit the signals after the size negotiation.
1161   if( !mController->IsInputStyleChangedSignalsQueueEmpty() )
1162   {
1163     if( Adaptor::IsAvailable() )
1164     {
1165       Adaptor& adaptor = Adaptor::Get();
1166
1167       if( NULL == mIdleCallback )
1168       {
1169         // @note: The callback manager takes the ownership of the callback object.
1170         mIdleCallback = MakeCallback( this, &TextEditor::OnIdleSignal );
1171         adaptor.AddIdle( mIdleCallback );
1172       }
1173     }
1174   }
1175 }
1176
1177 void TextEditor::RenderText( Text::Controller::UpdateTextType updateTextType )
1178 {
1179   Actor renderableActor;
1180
1181   if( Text::Controller::NONE_UPDATED != ( Text::Controller::MODEL_UPDATED & updateTextType ) )
1182   {
1183     if( mRenderer )
1184     {
1185       renderableActor = mRenderer->Render( mController->GetView(),
1186                                            mAlignmentOffset,
1187                                            DepthIndex::CONTENT );
1188     }
1189
1190     if( renderableActor != mRenderableActor )
1191     {
1192       UnparentAndReset( mRenderableActor );
1193       mRenderableActor = renderableActor;
1194     }
1195   }
1196
1197   if( mRenderableActor )
1198   {
1199     // Make sure the actors are parented correctly with/without clipping
1200     Actor self = mStencil ? mStencil : Self();
1201
1202     for( std::vector<Actor>::const_iterator it = mClippingDecorationActors.begin(),
1203            endIt = mClippingDecorationActors.end();
1204          it != endIt;
1205          ++it )
1206     {
1207       self.Add( *it );
1208     }
1209     mClippingDecorationActors.clear();
1210
1211     self.Add( mRenderableActor );
1212
1213     ApplyScrollPosition();
1214   }
1215   UpdateScrollBar();
1216 }
1217
1218 void TextEditor::OnKeyInputFocusGained()
1219 {
1220   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnKeyInputFocusGained %p\n", mController.Get() );
1221
1222   mImfManager.StatusChangedSignal().Connect( this, &TextEditor::KeyboardStatusChanged );
1223
1224   mImfManager.EventReceivedSignal().Connect( this, &TextEditor::OnImfEvent );
1225
1226   // Notify that the text editing start.
1227   mImfManager.Activate();
1228
1229   // When window gain lost focus, the imf manager is deactivated. Thus when window gain focus again, the imf manager must be activated.
1230   mImfManager.SetRestoreAfterFocusLost( true );
1231
1232    ClipboardEventNotifier notifier( ClipboardEventNotifier::Get() );
1233
1234    if ( notifier )
1235    {
1236       notifier.ContentSelectedSignal().Connect( this, &TextEditor::OnClipboardTextSelected );
1237    }
1238
1239   mController->KeyboardFocusGainEvent(); // Called in the case of no virtual keyboard to trigger this event
1240
1241   EmitKeyInputFocusSignal( true ); // Calls back into the Control hence done last.
1242 }
1243
1244 void TextEditor::OnKeyInputFocusLost()
1245 {
1246   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor:OnKeyInputFocusLost %p\n", mController.Get() );
1247
1248   mImfManager.StatusChangedSignal().Disconnect( this, &TextEditor::KeyboardStatusChanged );
1249
1250   // The text editing is finished. Therefore the imf manager don't have restore activation.
1251   mImfManager.SetRestoreAfterFocusLost( false );
1252
1253   // Notify that the text editing finish.
1254   mImfManager.Deactivate();
1255
1256   mImfManager.EventReceivedSignal().Disconnect( this, &TextEditor::OnImfEvent );
1257
1258   ClipboardEventNotifier notifier( ClipboardEventNotifier::Get() );
1259
1260   if ( notifier )
1261   {
1262     notifier.ContentSelectedSignal().Disconnect( this, &TextEditor::OnClipboardTextSelected );
1263   }
1264
1265   mController->KeyboardFocusLostEvent();
1266
1267   EmitKeyInputFocusSignal( false ); // Calls back into the Control hence done last.
1268 }
1269
1270 void TextEditor::OnTap( const TapGesture& gesture )
1271 {
1272   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnTap %p\n", mController.Get() );
1273
1274   mImfManager.Activate();
1275
1276   // Deliver the tap before the focus event to controller; this allows us to detect when focus is gained due to tap-gestures
1277   mController->TapEvent( gesture.numberOfTaps, gesture.localPoint.x, gesture.localPoint.y );
1278
1279   SetKeyInputFocus();
1280 }
1281
1282 void TextEditor::OnPan( const PanGesture& gesture )
1283 {
1284   mController->PanEvent( gesture.state, gesture.displacement );
1285 }
1286
1287 void TextEditor::OnLongPress( const LongPressGesture& gesture )
1288 {
1289   mImfManager.Activate();
1290
1291   mController->LongPressEvent( gesture.state, gesture.localPoint.x, gesture.localPoint.y );
1292
1293   SetKeyInputFocus();
1294 }
1295
1296 bool TextEditor::OnKeyEvent( const KeyEvent& event )
1297 {
1298   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnKeyEvent %p keyCode %d\n", mController.Get(), event.keyCode );
1299
1300   if( Dali::DALI_KEY_ESCAPE == event.keyCode ) // Make a Dali key code for this
1301   {
1302     // Make sure ClearKeyInputFocus when only key is up
1303     if( event.state == KeyEvent::Up )
1304     {
1305       ClearKeyInputFocus();
1306     }
1307
1308     return true;
1309   }
1310
1311   return mController->KeyEvent( event );
1312 }
1313
1314 void TextEditor::RequestTextRelayout()
1315 {
1316   RelayoutRequest();
1317 }
1318
1319 void TextEditor::TextChanged()
1320 {
1321   Dali::Toolkit::TextEditor handle( GetOwner() );
1322   mTextChangedSignal.Emit( handle );
1323 }
1324
1325 void TextEditor::MaxLengthReached()
1326 {
1327   // Nothing to do as TextEditor doesn't emit a max length reached signal.
1328 }
1329
1330 void TextEditor::InputStyleChanged( Text::InputStyle::Mask inputStyleMask )
1331 {
1332   Dali::Toolkit::TextEditor handle( GetOwner() );
1333
1334   Toolkit::TextEditor::InputStyle::Mask editorInputStyleMask = Toolkit::TextEditor::InputStyle::NONE;
1335
1336   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_COLOR ) )
1337   {
1338     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::COLOR );
1339   }
1340   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_FONT_FAMILY ) )
1341   {
1342     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_FAMILY );
1343   }
1344   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_POINT_SIZE ) )
1345   {
1346     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::POINT_SIZE );
1347   }
1348   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_FONT_WEIGHT ) )
1349   {
1350     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE );
1351   }
1352   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_FONT_WIDTH ) )
1353   {
1354     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE );
1355   }
1356   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_FONT_SLANT ) )
1357   {
1358     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE );
1359   }
1360   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_LINE_SPACING ) )
1361   {
1362     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::LINE_SPACING );
1363   }
1364   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_UNDERLINE ) )
1365   {
1366     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::UNDERLINE );
1367   }
1368   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_SHADOW ) )
1369   {
1370     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::SHADOW );
1371   }
1372   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_EMBOSS ) )
1373   {
1374     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::EMBOSS );
1375   }
1376   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_OUTLINE ) )
1377   {
1378     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::OUTLINE );
1379   }
1380
1381   mInputStyleChangedSignal.Emit( handle, editorInputStyleMask );
1382 }
1383
1384 void TextEditor::AddDecoration( Actor& actor, bool needsClipping )
1385 {
1386   if( actor )
1387   {
1388     if( needsClipping )
1389     {
1390       mClippingDecorationActors.push_back( actor );
1391     }
1392     else
1393     {
1394       Self().Add( actor );
1395     }
1396   }
1397 }
1398
1399 void TextEditor::UpdateScrollBar()
1400 {
1401   using namespace Dali;
1402
1403   float scrollPosition;
1404   float controlSize;
1405   float layoutSize;
1406   bool latestScrolled;
1407
1408   if ( !mScrollBarEnabled )
1409   {
1410     return;
1411   }
1412   latestScrolled = mController->GetTextScrollInfo( scrollPosition, controlSize, layoutSize );
1413   if ( !latestScrolled || controlSize > layoutSize)
1414   {
1415     return;
1416   }
1417
1418   CustomActor self = Self();
1419   if( !mScrollBar )
1420   {
1421     mScrollBar = Toolkit::ScrollBar::New( Toolkit::ScrollBar::Vertical );
1422     mScrollBar.SetIndicatorHeightPolicy( Toolkit::ScrollBar::Variable );
1423     mScrollBar.SetParentOrigin( ParentOrigin::TOP_RIGHT );
1424     mScrollBar.SetAnchorPoint( AnchorPoint::TOP_RIGHT );
1425     mScrollBar.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
1426     mScrollBar.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::WIDTH );
1427
1428     // Register the scroll position property
1429     Property::Index propertyScrollPosition = self.RegisterProperty( SCROLL_BAR_POSITION, scrollPosition );
1430     // Register the minimum scroll position property
1431     Property::Index propertyMinScrollPosition = self.RegisterProperty( SCROLL_BAR_POSITION_MIN, 0.0f );
1432     // Register the maximum scroll position property
1433     Property::Index propertyMaxScrollPosition = self.RegisterProperty( SCROLL_BAR_POSITION_MAX, (layoutSize - controlSize) );
1434     // Register the scroll content size property
1435     Property::Index propertyScrollContentSize = self.RegisterProperty( SCROLL_BAR_CONTENT_SIZE, layoutSize );
1436
1437     mScrollBar.SetScrollPropertySource(self, propertyScrollPosition, propertyMinScrollPosition, propertyMaxScrollPosition, propertyScrollContentSize);
1438
1439     self.Add( mScrollBar );
1440   }
1441   else
1442   {
1443     Property::Index propertyScrollPosition = self.GetPropertyIndex( SCROLL_BAR_POSITION );
1444     Property::Index propertyMaxScrollPosition = self.GetPropertyIndex( SCROLL_BAR_POSITION_MAX );
1445     Property::Index propertyScrollContentSize = self.GetPropertyIndex( SCROLL_BAR_CONTENT_SIZE );
1446
1447     self.SetProperty( propertyScrollPosition, scrollPosition );
1448     self.SetProperty( propertyMaxScrollPosition, (layoutSize - controlSize) );
1449     self.SetProperty( propertyScrollContentSize, layoutSize );
1450   }
1451
1452   Actor indicator = mScrollBar.GetScrollIndicator();
1453   if( mAnimation )
1454   {
1455     mAnimation.Stop(); // Cancel any animation
1456   }
1457   else
1458   {
1459     mAnimation = Animation::New( mAnimationPeriod.durationSeconds );
1460   }
1461   indicator.SetOpacity(1.0f);
1462   mAnimation.AnimateTo( Property( indicator, Actor::Property::COLOR_ALPHA ), 0.0f, AlphaFunction::EASE_IN, mAnimationPeriod );
1463   mAnimation.Play();
1464 }
1465
1466 void TextEditor::OnStageConnect( Dali::Actor actor )
1467 {
1468   if ( mHasBeenStaged )
1469   {
1470     RenderText( static_cast<Text::Controller::UpdateTextType>( Text::Controller::MODEL_UPDATED | Text::Controller::DECORATOR_UPDATED ) );
1471   }
1472   else
1473   {
1474     mHasBeenStaged = true;
1475   }
1476 }
1477
1478 ImfManager::ImfCallbackData TextEditor::OnImfEvent( Dali::ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent )
1479 {
1480   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnImfEvent %p eventName %d\n", mController.Get(), imfEvent.eventName );
1481   return mController->OnImfEvent( imfManager, imfEvent );
1482 }
1483
1484 void TextEditor::GetHandleImagePropertyValue(  Property::Value& value, Text::HandleType handleType, Text::HandleImageType handleImageType )
1485 {
1486   if( mDecorator )
1487   {
1488     ResourceImage image = ResourceImage::DownCast( mDecorator->GetHandleImage( handleType, handleImageType ) );
1489
1490     if ( image )
1491     {
1492       Property::Map map;
1493       Scripting::CreatePropertyMap( image, map );
1494       value = map;
1495     }
1496   }
1497 }
1498
1499 void TextEditor::OnClipboardTextSelected( ClipboardEventNotifier& clipboard )
1500 {
1501   mController->PasteClipboardItemEvent();
1502 }
1503
1504 void TextEditor::KeyboardStatusChanged(bool keyboardShown)
1505 {
1506   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::KeyboardStatusChanged %p keyboardShown %d\n", mController.Get(), keyboardShown );
1507
1508   // Just hide the grab handle when keyboard is hidden.
1509   if (!keyboardShown )
1510   {
1511     mController->KeyboardFocusLostEvent();
1512   }
1513   else
1514   {
1515     mController->KeyboardFocusGainEvent(); // Initially called by OnKeyInputFocusGained
1516   }
1517 }
1518
1519 void TextEditor::OnStageConnection( int depth )
1520 {
1521   // Sets the depth to the visuals inside the text's decorator.
1522   mDecorator->SetTextDepth( depth );
1523
1524   // The depth of the text renderer is set in the RenderText() called from OnRelayout().
1525
1526   // Call the Control::OnStageConnection() to set the depth of the background.
1527   Control::OnStageConnection( depth );
1528 }
1529
1530 bool TextEditor::OnTouched( Actor actor, const TouchData& touch )
1531 {
1532   return true;
1533 }
1534
1535 void TextEditor::OnIdleSignal()
1536 {
1537   // Emits the change of input style signals.
1538   mController->ProcessInputStyleChangedSignals();
1539
1540   // Set the pointer to null as the callback manager deletes the callback after execute it.
1541   mIdleCallback = NULL;
1542 }
1543
1544 void TextEditor::ApplyScrollPosition()
1545 {
1546   const Vector2& scrollOffset = mController->GetTextModel()->GetScrollPosition();
1547   float scrollAmount = 0.0f;
1548
1549   if ( mScrollAnimationEnabled )
1550   {
1551     scrollAmount = mController->GetScrollAmountByUserInput();
1552   }
1553   if ( mTextVerticalScroller )
1554   {
1555     mTextVerticalScroller->CheckStartAnimation( mRenderableActor, scrollOffset.x + mAlignmentOffset, scrollOffset.y - scrollAmount, scrollAmount );
1556   }
1557   else if ( Equals( scrollAmount, 0.0f, Math::MACHINE_EPSILON_1 ))
1558   {
1559     mRenderableActor.SetPosition( scrollOffset.x + mAlignmentOffset, scrollOffset.y - scrollAmount );
1560   }
1561   else
1562   {
1563     mTextVerticalScroller = Text::TextVerticalScroller::New();
1564     if ( !Equals( mScrollAnimationDuration, 0.0f, Math::MACHINE_EPSILON_1 ))
1565     {
1566       mTextVerticalScroller->SetDuration( mScrollAnimationDuration );
1567     }
1568     mTextVerticalScroller->CheckStartAnimation( mRenderableActor, scrollOffset.x + mAlignmentOffset, scrollOffset.y - scrollAmount, scrollAmount );
1569   }
1570 }
1571
1572 TextEditor::TextEditor()
1573 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
1574   mAnimationPeriod( 0.0f, 0.0f ),
1575   mIdleCallback( NULL ),
1576   mAlignmentOffset( 0.f ),
1577   mScrollAnimationDuration( 0.f ),
1578   mRenderingBackend( DEFAULT_RENDERING_BACKEND ),
1579   mHasBeenStaged( false ),
1580   mScrollAnimationEnabled( false ),
1581   mScrollBarEnabled( false )
1582 {
1583 }
1584
1585 TextEditor::~TextEditor()
1586 {
1587   UnparentAndReset( mStencil );
1588
1589   if( ( NULL != mIdleCallback ) && Adaptor::IsAvailable() )
1590   {
1591     // Removes the callback from the callback manager in case the text-editor is destroyed before the callback is executed.
1592     Adaptor::Get().RemoveIdle( mIdleCallback );
1593   }
1594 }
1595
1596 } // namespace Internal
1597
1598 } // namespace Toolkit
1599
1600 } // namespace Dali