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