Change the double tap and long press events on top of no text actions to highlight.
[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       break;
1102     }
1103
1104     case StyleChange::DEFAULT_FONT_SIZE_CHANGE:
1105     {
1106       GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
1107       break;
1108     }
1109     case StyleChange::THEME_CHANGE:
1110     {
1111       GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
1112       break;
1113     }
1114   }
1115 }
1116
1117 Vector3 TextEditor::GetNaturalSize()
1118 {
1119   return mController->GetNaturalSize();
1120 }
1121
1122 float TextEditor::GetHeightForWidth( float width )
1123 {
1124   return mController->GetHeightForWidth( width );
1125 }
1126
1127 void TextEditor::OnRelayout( const Vector2& size, RelayoutContainer& container )
1128 {
1129   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor OnRelayout\n");
1130
1131   const Text::Controller::UpdateTextType updateTextType = mController->Relayout( size );
1132
1133   if( ( Text::Controller::NONE_UPDATED != updateTextType ) ||
1134       !mRenderer )
1135   {
1136     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnRelayout %p Displaying new contents\n", mController.Get() );
1137
1138     if( mDecorator &&
1139         ( Text::Controller::NONE_UPDATED != ( Text::Controller::DECORATOR_UPDATED & updateTextType ) ) )
1140     {
1141       mDecorator->Relayout( size );
1142     }
1143
1144     if( !mRenderer )
1145     {
1146       mRenderer = Backend::Get().NewRenderer( mRenderingBackend );
1147     }
1148
1149     RenderText( updateTextType );
1150   }
1151
1152   // The text-editor emits signals when the input style changes. These changes of style are
1153   // detected during the relayout process (size negotiation), i.e after the cursor has been moved. Signals
1154   // can't be emitted during the size negotiation as the callbacks may update the UI.
1155   // The text-editor adds an idle callback to the adaptor to emit the signals after the size negotiation.
1156   if( !mController->IsInputStyleChangedSignalsQueueEmpty() )
1157   {
1158     if( Adaptor::IsAvailable() )
1159     {
1160       Adaptor& adaptor = Adaptor::Get();
1161
1162       if( NULL == mIdleCallback )
1163       {
1164         // @note: The callback manager takes the ownership of the callback object.
1165         mIdleCallback = MakeCallback( this, &TextEditor::OnIdleSignal );
1166         adaptor.AddIdle( mIdleCallback );
1167       }
1168     }
1169   }
1170 }
1171
1172 void TextEditor::RenderText( Text::Controller::UpdateTextType updateTextType )
1173 {
1174   Actor renderableActor;
1175
1176   if( Text::Controller::NONE_UPDATED != ( Text::Controller::MODEL_UPDATED & updateTextType ) )
1177   {
1178     if( mRenderer )
1179     {
1180       renderableActor = mRenderer->Render( mController->GetView(),
1181                                            mAlignmentOffset,
1182                                            DepthIndex::CONTENT );
1183     }
1184
1185     if( renderableActor != mRenderableActor )
1186     {
1187       UnparentAndReset( mRenderableActor );
1188       mRenderableActor = renderableActor;
1189     }
1190   }
1191
1192   if( mRenderableActor )
1193   {
1194     // Make sure the actors are parented correctly with/without clipping
1195     Actor self = mStencil ? mStencil : Self();
1196
1197     for( std::vector<Actor>::const_iterator it = mClippingDecorationActors.begin(),
1198            endIt = mClippingDecorationActors.end();
1199          it != endIt;
1200          ++it )
1201     {
1202       self.Add( *it );
1203     }
1204     mClippingDecorationActors.clear();
1205
1206     self.Add( mRenderableActor );
1207
1208     ApplyScrollPosition();
1209   }
1210   UpdateScrollBar();
1211 }
1212
1213 void TextEditor::OnKeyInputFocusGained()
1214 {
1215   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnKeyInputFocusGained %p\n", mController.Get() );
1216
1217   mImfManager.StatusChangedSignal().Connect( this, &TextEditor::KeyboardStatusChanged );
1218
1219   mImfManager.EventReceivedSignal().Connect( this, &TextEditor::OnImfEvent );
1220
1221   // Notify that the text editing start.
1222   mImfManager.Activate();
1223
1224   // When window gain lost focus, the imf manager is deactivated. Thus when window gain focus again, the imf manager must be activated.
1225   mImfManager.SetRestoreAfterFocusLost( true );
1226
1227    ClipboardEventNotifier notifier( ClipboardEventNotifier::Get() );
1228
1229    if ( notifier )
1230    {
1231       notifier.ContentSelectedSignal().Connect( this, &TextEditor::OnClipboardTextSelected );
1232    }
1233
1234   mController->KeyboardFocusGainEvent(); // Called in the case of no virtual keyboard to trigger this event
1235
1236   EmitKeyInputFocusSignal( true ); // Calls back into the Control hence done last.
1237 }
1238
1239 void TextEditor::OnKeyInputFocusLost()
1240 {
1241   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor:OnKeyInputFocusLost %p\n", mController.Get() );
1242
1243   mImfManager.StatusChangedSignal().Disconnect( this, &TextEditor::KeyboardStatusChanged );
1244
1245   // The text editing is finished. Therefore the imf manager don't have restore activation.
1246   mImfManager.SetRestoreAfterFocusLost( false );
1247
1248   // Notify that the text editing finish.
1249   mImfManager.Deactivate();
1250
1251   mImfManager.EventReceivedSignal().Disconnect( this, &TextEditor::OnImfEvent );
1252
1253   ClipboardEventNotifier notifier( ClipboardEventNotifier::Get() );
1254
1255   if ( notifier )
1256   {
1257     notifier.ContentSelectedSignal().Disconnect( this, &TextEditor::OnClipboardTextSelected );
1258   }
1259
1260   mController->KeyboardFocusLostEvent();
1261
1262   EmitKeyInputFocusSignal( false ); // Calls back into the Control hence done last.
1263 }
1264
1265 void TextEditor::OnTap( const TapGesture& gesture )
1266 {
1267   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnTap %p\n", mController.Get() );
1268
1269   mImfManager.Activate();
1270
1271   // Deliver the tap before the focus event to controller; this allows us to detect when focus is gained due to tap-gestures
1272   mController->TapEvent( gesture.numberOfTaps, gesture.localPoint.x, gesture.localPoint.y );
1273
1274   SetKeyInputFocus();
1275 }
1276
1277 void TextEditor::OnPan( const PanGesture& gesture )
1278 {
1279   mController->PanEvent( gesture.state, gesture.displacement );
1280 }
1281
1282 void TextEditor::OnLongPress( const LongPressGesture& gesture )
1283 {
1284   mImfManager.Activate();
1285
1286   mController->LongPressEvent( gesture.state, gesture.localPoint.x, gesture.localPoint.y );
1287
1288   SetKeyInputFocus();
1289 }
1290
1291 bool TextEditor::OnKeyEvent( const KeyEvent& event )
1292 {
1293   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnKeyEvent %p keyCode %d\n", mController.Get(), event.keyCode );
1294
1295   if( Dali::DALI_KEY_ESCAPE == event.keyCode ) // Make a Dali key code for this
1296   {
1297     // Make sure ClearKeyInputFocus when only key is up
1298     if( event.state == KeyEvent::Up )
1299     {
1300       ClearKeyInputFocus();
1301     }
1302
1303     return true;
1304   }
1305
1306   return mController->KeyEvent( event );
1307 }
1308
1309 void TextEditor::RequestTextRelayout()
1310 {
1311   RelayoutRequest();
1312 }
1313
1314 void TextEditor::TextChanged()
1315 {
1316   Dali::Toolkit::TextEditor handle( GetOwner() );
1317   mTextChangedSignal.Emit( handle );
1318 }
1319
1320 void TextEditor::MaxLengthReached()
1321 {
1322   // Nothing to do as TextEditor doesn't emit a max length reached signal.
1323 }
1324
1325 void TextEditor::InputStyleChanged( Text::InputStyle::Mask inputStyleMask )
1326 {
1327   Dali::Toolkit::TextEditor handle( GetOwner() );
1328
1329   Toolkit::TextEditor::InputStyle::Mask editorInputStyleMask = Toolkit::TextEditor::InputStyle::NONE;
1330
1331   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_COLOR ) )
1332   {
1333     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::COLOR );
1334   }
1335   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_FONT_FAMILY ) )
1336   {
1337     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_FAMILY );
1338   }
1339   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_POINT_SIZE ) )
1340   {
1341     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::POINT_SIZE );
1342   }
1343   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_FONT_WEIGHT ) )
1344   {
1345     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE );
1346   }
1347   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_FONT_WIDTH ) )
1348   {
1349     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE );
1350   }
1351   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_FONT_SLANT ) )
1352   {
1353     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::FONT_STYLE );
1354   }
1355   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_LINE_SPACING ) )
1356   {
1357     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::LINE_SPACING );
1358   }
1359   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_UNDERLINE ) )
1360   {
1361     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::UNDERLINE );
1362   }
1363   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_SHADOW ) )
1364   {
1365     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::SHADOW );
1366   }
1367   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_EMBOSS ) )
1368   {
1369     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::EMBOSS );
1370   }
1371   if( InputStyle::NONE != static_cast<InputStyle::Mask>( inputStyleMask & InputStyle::INPUT_OUTLINE ) )
1372   {
1373     editorInputStyleMask = static_cast<Toolkit::TextEditor::InputStyle::Mask>( editorInputStyleMask | Toolkit::TextEditor::InputStyle::OUTLINE );
1374   }
1375
1376   mInputStyleChangedSignal.Emit( handle, editorInputStyleMask );
1377 }
1378
1379 void TextEditor::AddDecoration( Actor& actor, bool needsClipping )
1380 {
1381   if( actor )
1382   {
1383     if( needsClipping )
1384     {
1385       mClippingDecorationActors.push_back( actor );
1386     }
1387     else
1388     {
1389       Self().Add( actor );
1390     }
1391   }
1392 }
1393
1394 void TextEditor::UpdateScrollBar()
1395 {
1396   using namespace Dali;
1397
1398   float scrollPosition;
1399   float controlSize;
1400   float layoutSize;
1401   bool latestScrolled;
1402
1403   if ( !mScrollBarEnabled )
1404   {
1405     return;
1406   }
1407   latestScrolled = mController->GetTextScrollInfo( scrollPosition, controlSize, layoutSize );
1408   if ( !latestScrolled || controlSize > layoutSize)
1409   {
1410     return;
1411   }
1412
1413   CustomActor self = Self();
1414   if( !mScrollBar )
1415   {
1416     mScrollBar = Toolkit::ScrollBar::New( Toolkit::ScrollBar::Vertical );
1417     mScrollBar.SetIndicatorHeightPolicy( Toolkit::ScrollBar::Variable );
1418     mScrollBar.SetParentOrigin( ParentOrigin::TOP_RIGHT );
1419     mScrollBar.SetAnchorPoint( AnchorPoint::TOP_RIGHT );
1420     mScrollBar.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
1421     mScrollBar.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::WIDTH );
1422
1423     // Register the scroll position property
1424     Property::Index propertyScrollPosition = self.RegisterProperty( SCROLL_BAR_POSITION, scrollPosition );
1425     // Register the minimum scroll position property
1426     Property::Index propertyMinScrollPosition = self.RegisterProperty( SCROLL_BAR_POSITION_MIN, 0.0f );
1427     // Register the maximum scroll position property
1428     Property::Index propertyMaxScrollPosition = self.RegisterProperty( SCROLL_BAR_POSITION_MAX, (layoutSize - controlSize) );
1429     // Register the scroll content size property
1430     Property::Index propertyScrollContentSize = self.RegisterProperty( SCROLL_BAR_CONTENT_SIZE, layoutSize );
1431
1432     mScrollBar.SetScrollPropertySource(self, propertyScrollPosition, propertyMinScrollPosition, propertyMaxScrollPosition, propertyScrollContentSize);
1433
1434     self.Add( mScrollBar );
1435   }
1436   else
1437   {
1438     Property::Index propertyScrollPosition = self.GetPropertyIndex( SCROLL_BAR_POSITION );
1439     Property::Index propertyMaxScrollPosition = self.GetPropertyIndex( SCROLL_BAR_POSITION_MAX );
1440     Property::Index propertyScrollContentSize = self.GetPropertyIndex( SCROLL_BAR_CONTENT_SIZE );
1441
1442     self.SetProperty( propertyScrollPosition, scrollPosition );
1443     self.SetProperty( propertyMaxScrollPosition, (layoutSize - controlSize) );
1444     self.SetProperty( propertyScrollContentSize, layoutSize );
1445   }
1446
1447   Actor indicator = mScrollBar.GetScrollIndicator();
1448   if( mAnimation )
1449   {
1450     mAnimation.Stop(); // Cancel any animation
1451   }
1452   else
1453   {
1454     mAnimation = Animation::New( mAnimationPeriod.durationSeconds );
1455   }
1456   indicator.SetOpacity(1.0f);
1457   mAnimation.AnimateTo( Property( indicator, Actor::Property::COLOR_ALPHA ), 0.0f, AlphaFunction::EASE_IN, mAnimationPeriod );
1458   mAnimation.Play();
1459 }
1460
1461 void TextEditor::OnStageConnect( Dali::Actor actor )
1462 {
1463   if ( mHasBeenStaged )
1464   {
1465     RenderText( static_cast<Text::Controller::UpdateTextType>( Text::Controller::MODEL_UPDATED | Text::Controller::DECORATOR_UPDATED ) );
1466   }
1467   else
1468   {
1469     mHasBeenStaged = true;
1470   }
1471 }
1472
1473 ImfManager::ImfCallbackData TextEditor::OnImfEvent( Dali::ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent )
1474 {
1475   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnImfEvent %p eventName %d\n", mController.Get(), imfEvent.eventName );
1476   return mController->OnImfEvent( imfManager, imfEvent );
1477 }
1478
1479 void TextEditor::GetHandleImagePropertyValue(  Property::Value& value, Text::HandleType handleType, Text::HandleImageType handleImageType )
1480 {
1481   if( mDecorator )
1482   {
1483     ResourceImage image = ResourceImage::DownCast( mDecorator->GetHandleImage( handleType, handleImageType ) );
1484
1485     if ( image )
1486     {
1487       Property::Map map;
1488       Scripting::CreatePropertyMap( image, map );
1489       value = map;
1490     }
1491   }
1492 }
1493
1494 void TextEditor::OnClipboardTextSelected( ClipboardEventNotifier& clipboard )
1495 {
1496   mController->PasteClipboardItemEvent();
1497 }
1498
1499 void TextEditor::KeyboardStatusChanged(bool keyboardShown)
1500 {
1501   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::KeyboardStatusChanged %p keyboardShown %d\n", mController.Get(), keyboardShown );
1502
1503   // Just hide the grab handle when keyboard is hidden.
1504   if (!keyboardShown )
1505   {
1506     mController->KeyboardFocusLostEvent();
1507   }
1508   else
1509   {
1510     mController->KeyboardFocusGainEvent(); // Initially called by OnKeyInputFocusGained
1511   }
1512 }
1513
1514 void TextEditor::OnStageConnection( int depth )
1515 {
1516   // Sets the depth to the visuals inside the text's decorator.
1517   mDecorator->SetTextDepth( depth );
1518
1519   // The depth of the text renderer is set in the RenderText() called from OnRelayout().
1520
1521   // Call the Control::OnStageConnection() to set the depth of the background.
1522   Control::OnStageConnection( depth );
1523 }
1524
1525 bool TextEditor::OnTouched( Actor actor, const TouchData& touch )
1526 {
1527   return true;
1528 }
1529
1530 void TextEditor::OnIdleSignal()
1531 {
1532   // Emits the change of input style signals.
1533   mController->ProcessInputStyleChangedSignals();
1534
1535   // Set the pointer to null as the callback manager deletes the callback after execute it.
1536   mIdleCallback = NULL;
1537 }
1538
1539 void TextEditor::ApplyScrollPosition()
1540 {
1541   const Vector2& scrollOffset = mController->GetTextModel()->GetScrollPosition();
1542   float scrollAmount = 0.0f;
1543
1544   if ( mScrollAnimationEnabled )
1545   {
1546     scrollAmount = mController->GetScrollAmountByUserInput();
1547   }
1548   if ( mTextVerticalScroller )
1549   {
1550     mTextVerticalScroller->CheckStartAnimation( mRenderableActor, scrollOffset.x + mAlignmentOffset, scrollOffset.y - scrollAmount, scrollAmount );
1551   }
1552   else if ( Equals( scrollAmount, 0.0f, Math::MACHINE_EPSILON_1 ))
1553   {
1554     mRenderableActor.SetPosition( scrollOffset.x + mAlignmentOffset, scrollOffset.y - scrollAmount );
1555   }
1556   else
1557   {
1558     mTextVerticalScroller = Text::TextVerticalScroller::New();
1559     if ( !Equals( mScrollAnimationDuration, 0.0f, Math::MACHINE_EPSILON_1 ))
1560     {
1561       mTextVerticalScroller->SetDuration( mScrollAnimationDuration );
1562     }
1563     mTextVerticalScroller->CheckStartAnimation( mRenderableActor, scrollOffset.x + mAlignmentOffset, scrollOffset.y - scrollAmount, scrollAmount );
1564   }
1565 }
1566
1567 TextEditor::TextEditor()
1568 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
1569   mAnimationPeriod( 0.0f, 0.0f ),
1570   mIdleCallback( NULL ),
1571   mAlignmentOffset( 0.f ),
1572   mScrollAnimationDuration( 0.f ),
1573   mRenderingBackend( DEFAULT_RENDERING_BACKEND ),
1574   mHasBeenStaged( false ),
1575   mScrollAnimationEnabled( false ),
1576   mScrollBarEnabled( false )
1577 {
1578 }
1579
1580 TextEditor::~TextEditor()
1581 {
1582   UnparentAndReset( mStencil );
1583
1584   if( ( NULL != mIdleCallback ) && Adaptor::IsAvailable() )
1585   {
1586     // Removes the callback from the callback manager in case the text-editor is destroyed before the callback is executed.
1587     Adaptor::Get().RemoveIdle( mIdleCallback );
1588   }
1589 }
1590
1591 } // namespace Internal
1592
1593 } // namespace Toolkit
1594
1595 } // namespace Dali