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