660e823254b93a0e202da0d56b1dd91dab025283
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / text-controls / text-editor-impl.cpp
1 /*
2  * Copyright (c) 2016 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/adaptor-framework/virtual-keyboard.h>
28 #include <dali/devel-api/object/type-registry-helper.h>
29 #include <dali/integration-api/debug.h>
30
31 // INTERNAL INCLUDES
32 #include <dali-toolkit/public-api/text/rendering-backend.h>
33 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
34 #include <dali-toolkit/internal/text/rendering/text-backend.h>
35 #include <dali-toolkit/internal/text/text-font-style.h>
36 #include <dali-toolkit/internal/text/text-view.h>
37 #include <dali-toolkit/internal/styling/style-manager-impl.h>
38
39 using namespace Dali::Toolkit::Text;
40
41 namespace Dali
42 {
43
44 namespace Toolkit
45 {
46
47 namespace Internal
48 {
49
50 namespace // unnamed namespace
51 {
52
53 #if defined(DEBUG_ENABLED)
54   Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_CONTROLS");
55 #endif
56
57   const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND;
58 } // unnamed namespace
59
60 namespace
61 {
62
63 const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] =
64 {
65   { "BEGIN",  Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_BEGIN  },
66   { "CENTER", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_CENTER },
67   { "END",    Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_END    },
68 };
69 const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE ) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] );
70
71 // Type registration
72 BaseHandle Create()
73 {
74   return Toolkit::TextEditor::New();
75 }
76
77 // Setup properties, signals and actions using the type-registry.
78 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextEditor, Toolkit::Control, Create );
79
80 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "renderingBackend",                     INTEGER,   RENDERING_BACKEND                    )
81 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "text",                                 STRING,    TEXT                                 )
82 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "textColor",                            VECTOR4,   TEXT_COLOR                           )
83 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "fontFamily",                           STRING,    FONT_FAMILY                          )
84 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "fontStyle",                            STRING,    FONT_STYLE                           )
85 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "pointSize",                            FLOAT,     POINT_SIZE                           )
86 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "horizontalAlignment",                  STRING,    HORIZONTAL_ALIGNMENT                 )
87 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "scrollThreshold",                      FLOAT,     SCROLL_THRESHOLD                     )
88 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "scrollSpeed",                          FLOAT,     SCROLL_SPEED                         )
89 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "primaryCursorColor",                   VECTOR4,   PRIMARY_CURSOR_COLOR                 )
90 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "secondaryCursorColor",                 VECTOR4,   SECONDARY_CURSOR_COLOR               )
91 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "enableCursorBlink",                    BOOLEAN,   ENABLE_CURSOR_BLINK                  )
92 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "cursorBlinkInterval",                  FLOAT,     CURSOR_BLINK_INTERVAL                )
93 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "cursorBlinkDuration",                  FLOAT,     CURSOR_BLINK_DURATION                )
94 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "cursorWidth",                          INTEGER,   CURSOR_WIDTH                         )
95 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "grabHandleImage",                      STRING,    GRAB_HANDLE_IMAGE                    )
96 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "grabHandlePressedImage",               STRING,    GRAB_HANDLE_PRESSED_IMAGE            )
97 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHandleImageLeft",             MAP,       SELECTION_HANDLE_IMAGE_LEFT          )
98 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHandleImageRight",            MAP,       SELECTION_HANDLE_IMAGE_RIGHT         )
99 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHandlePressedImageLeft",      MAP,       SELECTION_HANDLE_PRESSED_IMAGE_LEFT  )
100 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHandlePressedImageRight",     MAP,       SELECTION_HANDLE_PRESSED_IMAGE_RIGHT )
101 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHandleMarkerImageLeft",       MAP,       SELECTION_HANDLE_MARKER_IMAGE_LEFT   )
102 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHandleMarkerImageRight",      MAP,       SELECTION_HANDLE_MARKER_IMAGE_RIGHT  )
103 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectionHighlightColor",              VECTOR4,   SELECTION_HIGHLIGHT_COLOR            )
104 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "decorationBoundingBox",                RECTANGLE, DECORATION_BOUNDING_BOX              )
105 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "enableMarkup",                         BOOLEAN,   ENABLE_MARKUP                        )
106 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputColor",                           VECTOR4,   INPUT_COLOR                          )
107 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputFontFamily",                      STRING,    INPUT_FONT_FAMILY                    )
108 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputFontStyle",                       STRING,    INPUT_FONT_STYLE                     )
109 DALI_PROPERTY_REGISTRATION( Toolkit, TextEditor, "inputPointSize",                       FLOAT,     INPUT_POINT_SIZE                     )
110
111 DALI_SIGNAL_REGISTRATION( Toolkit, TextEditor, "textChanged",        SIGNAL_TEXT_CHANGED )
112
113 DALI_TYPE_REGISTRATION_END()
114
115 } // namespace
116
117 Toolkit::TextEditor TextEditor::New()
118 {
119   // Create the implementation, temporarily owned by this handle on stack
120   IntrusivePtr< TextEditor > impl = new TextEditor();
121
122   // Pass ownership to CustomActor handle
123   Toolkit::TextEditor handle( *impl );
124
125   // Second-phase init of the implementation
126   // This can only be done after the CustomActor connection has been made...
127   impl->Initialize();
128
129   return handle;
130 }
131
132 void TextEditor::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
133 {
134   Toolkit::TextEditor textEditor = Toolkit::TextEditor::DownCast( Dali::BaseHandle( object ) );
135
136   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor SetProperty\n");
137
138
139   if( textEditor )
140   {
141     TextEditor& impl( GetImpl( textEditor ) );
142
143     switch( index )
144     {
145       case Toolkit::TextEditor::Property::RENDERING_BACKEND:
146       {
147         int backend = value.Get< int >();
148         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p RENDERING_BACKEND %d\n", impl.mController.Get(), backend );
149
150         if( impl.mRenderingBackend != backend )
151         {
152           impl.mRenderingBackend = backend;
153           impl.mRenderer.Reset();
154           impl.RequestTextRelayout();
155         }
156         break;
157       }
158       case Toolkit::TextEditor::Property::TEXT:
159       {
160         if( impl.mController )
161         {
162           const std::string text = value.Get< std::string >();
163           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p TEXT %s\n", impl.mController.Get(), text.c_str() );
164
165           impl.mController->SetText( text );
166         }
167         break;
168       }
169       case Toolkit::TextEditor::Property::TEXT_COLOR:
170       {
171         if( impl.mController )
172         {
173           const Vector4 textColor = value.Get< Vector4 >();
174           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 );
175
176           if( impl.mController->GetTextColor() != textColor )
177           {
178             impl.mController->SetTextColor( textColor );
179             impl.mController->SetInputColor( textColor );
180             impl.mRenderer.Reset();
181           }
182         }
183         break;
184       }
185       case Toolkit::TextEditor::Property::FONT_FAMILY:
186       {
187         if( impl.mController )
188         {
189           const std::string fontFamily = value.Get< std::string >();
190           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p FONT_FAMILY %s\n", impl.mController.Get(), fontFamily.c_str() );
191           impl.mController->SetDefaultFontFamily( fontFamily );
192         }
193         break;
194       }
195       case Toolkit::TextEditor::Property::FONT_STYLE:
196       {
197         SetFontStyleProperty( impl.mController, value, Text::FontStyle::DEFAULT );
198         break;
199       }
200       case Toolkit::TextEditor::Property::POINT_SIZE:
201       {
202         if( impl.mController )
203         {
204           const float pointSize = value.Get< float >();
205           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p POINT_SIZE %f\n", impl.mController.Get(), pointSize );
206
207           if( !Equals( impl.mController->GetDefaultPointSize(), pointSize ) )
208           {
209             impl.mController->SetDefaultPointSize( pointSize );
210           }
211         }
212         break;
213       }
214       case Toolkit::TextEditor::Property::HORIZONTAL_ALIGNMENT:
215       {
216         if( impl.mController )
217         {
218           const std::string alignStr = value.Get< std::string >();
219           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p HORIZONTAL_ALIGNMENT %s\n", impl.mController.Get(), alignStr.c_str() );
220
221           LayoutEngine::HorizontalAlignment alignment( LayoutEngine::HORIZONTAL_ALIGN_BEGIN );
222           if( Scripting::GetEnumeration< LayoutEngine::HorizontalAlignment >( alignStr.c_str(),
223                                                                               HORIZONTAL_ALIGNMENT_STRING_TABLE,
224                                                                               HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT,
225                                                                               alignment ) )
226           {
227             impl.mController->SetHorizontalAlignment( alignment );
228           }
229         }
230         break;
231       }
232       case Toolkit::TextEditor::Property::SCROLL_THRESHOLD:
233       {
234         const float threshold = value.Get< float >();
235         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p SCROLL_THRESHOLD %f\n", impl.mController.Get(), threshold );
236
237         if( impl.mDecorator )
238         {
239           impl.mDecorator->SetScrollThreshold( threshold );
240         }
241         break;
242       }
243       case Toolkit::TextEditor::Property::SCROLL_SPEED:
244       {
245         const float speed = value.Get< float >();
246         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p SCROLL_SPEED %f\n", impl.mController.Get(), speed );
247
248         if( impl.mDecorator )
249         {
250           impl.mDecorator->SetScrollSpeed( speed );
251         }
252         break;
253       }
254       case Toolkit::TextEditor::Property::PRIMARY_CURSOR_COLOR:
255       {
256         if( impl.mDecorator )
257         {
258           const Vector4 color = value.Get< Vector4 >();
259           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 );
260
261           impl.mDecorator->SetCursorColor( PRIMARY_CURSOR, color );
262           impl.RequestTextRelayout();
263         }
264         break;
265       }
266       case Toolkit::TextEditor::Property::SECONDARY_CURSOR_COLOR:
267       {
268         if( impl.mDecorator )
269         {
270           const Vector4 color = value.Get< Vector4 >();
271           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 );
272
273           impl.mDecorator->SetCursorColor( SECONDARY_CURSOR, color );
274           impl.RequestTextRelayout();
275         }
276         break;
277       }
278       case Toolkit::TextEditor::Property::ENABLE_CURSOR_BLINK:
279       {
280         if( impl.mController )
281         {
282           const bool enable = value.Get< bool >();
283           DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p ENABLE_CURSOR_BLINK %d\n", impl.mController.Get(), enable );
284
285           impl.mController->SetEnableCursorBlink( enable );
286           impl.RequestTextRelayout();
287         }
288         break;
289       }
290       case Toolkit::TextEditor::Property::CURSOR_BLINK_INTERVAL:
291       {
292         if( impl.mDecorator )
293         {
294           const float interval = value.Get< float >();
295           DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p CURSOR_BLINK_INTERVAL %f\n", impl.mController.Get(), interval );
296
297           impl.mDecorator->SetCursorBlinkInterval( interval );
298         }
299         break;
300       }
301       case Toolkit::TextEditor::Property::CURSOR_BLINK_DURATION:
302       {
303         if( impl.mDecorator )
304         {
305           const float duration = value.Get< float >();
306           DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p CURSOR_BLINK_DURATION %f\n", impl.mController.Get(), duration );
307
308           impl.mDecorator->SetCursorBlinkDuration( duration );
309         }
310         break;
311       }
312       case Toolkit::TextEditor::Property::CURSOR_WIDTH:
313       {
314         if( impl.mDecorator )
315         {
316           const int width = value.Get< int >();
317           DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p CURSOR_WIDTH %d\n", impl.mController.Get(), width );
318
319           impl.mDecorator->SetCursorWidth( width );
320           impl.mController->GetLayoutEngine().SetCursorWidth( width );
321         }
322         break;
323       }
324       case Toolkit::TextEditor::Property::GRAB_HANDLE_IMAGE:
325       {
326         const ResourceImage image = ResourceImage::New( value.Get< std::string >() );
327         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p GRAB_HANDLE_IMAGE %s\n", impl.mController.Get(), image.GetUrl().c_str() );
328
329         if( impl.mDecorator )
330         {
331           impl.mDecorator->SetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_RELEASED, image );
332           impl.RequestTextRelayout();
333         }
334         break;
335       }
336       case Toolkit::TextEditor::Property::GRAB_HANDLE_PRESSED_IMAGE:
337       {
338         const ResourceImage image = ResourceImage::New( value.Get< std::string >() );
339         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor %p GRAB_HANDLE_PRESSED_IMAGE %s\n", impl.mController.Get(), image.GetUrl().c_str() );
340
341         if( impl.mDecorator )
342         {
343           impl.mDecorator->SetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_PRESSED, image );
344           impl.RequestTextRelayout();
345         }
346         break;
347       }
348       case Toolkit::TextEditor::Property::SELECTION_HANDLE_IMAGE_LEFT:
349       {
350         const Image image = Scripting::NewImage( value );
351
352         if( impl.mDecorator && image )
353         {
354           impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED, image );
355           impl.RequestTextRelayout();
356         }
357         break;
358       }
359       case Toolkit::TextEditor::Property::SELECTION_HANDLE_IMAGE_RIGHT:
360       {
361         const Image image = Scripting::NewImage( value );
362
363         if( impl.mDecorator && image )
364         {
365           impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED, image );
366           impl.RequestTextRelayout();
367         }
368         break;
369       }
370       case Toolkit::TextEditor::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT:
371       {
372         const Image image = Scripting::NewImage( value );
373
374         if( impl.mDecorator && image )
375         {
376           impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED, image );
377           impl.RequestTextRelayout();
378         }
379         break;
380       }
381       case Toolkit::TextEditor::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT:
382       {
383         const Image image = Scripting::NewImage( value );
384
385         if( impl.mDecorator && image )
386         {
387           impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED, image );
388           impl.RequestTextRelayout();
389         }
390         break;
391       }
392       case Toolkit::TextEditor::Property::SELECTION_HANDLE_MARKER_IMAGE_LEFT:
393       {
394         const Image image = Scripting::NewImage( value );
395
396         if( impl.mDecorator && image )
397         {
398           impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED, image );
399           impl.RequestTextRelayout();
400         }
401         break;
402       }
403       case Toolkit::TextEditor::Property::SELECTION_HANDLE_MARKER_IMAGE_RIGHT:
404       {
405         const Image image = Scripting::NewImage( value );
406
407         if( impl.mDecorator && image )
408         {
409           impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED, image );
410           impl.RequestTextRelayout();
411         }
412         break;
413       }
414       case Toolkit::TextEditor::Property::SELECTION_HIGHLIGHT_COLOR:
415       {
416         const Vector4 color = value.Get< Vector4 >();
417         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 );
418
419         if( impl.mDecorator )
420         {
421           impl.mDecorator->SetHighlightColor( color );
422           impl.RequestTextRelayout();
423         }
424         break;
425       }
426       case Toolkit::TextEditor::Property::DECORATION_BOUNDING_BOX:
427       {
428         if( impl.mDecorator )
429         {
430           const Rect<int> box = value.Get< Rect<int> >();
431           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 );
432
433           impl.mDecorator->SetBoundingBox( box );
434           impl.RequestTextRelayout();
435         }
436         break;
437       }
438       case Toolkit::TextEditor::Property::ENABLE_MARKUP:
439       {
440         if( impl.mController )
441         {
442           const bool enableMarkup = value.Get<bool>();
443           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p ENABLE_MARKUP %d\n", impl.mController.Get(), enableMarkup );
444
445           impl.mController->SetMarkupProcessorEnabled( enableMarkup );
446         }
447         break;
448       }
449       case Toolkit::TextEditor::Property::INPUT_COLOR:
450       {
451         if( impl.mController )
452         {
453           const Vector4 inputColor = value.Get< Vector4 >();
454           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 );
455
456           impl.mController->SetInputColor( inputColor );
457         }
458         break;
459       }
460       case Toolkit::TextEditor::Property::INPUT_FONT_FAMILY:
461       {
462         if( impl.mController )
463         {
464           const std::string fontFamily = value.Get< std::string >();
465           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p INPUT_FONT_FAMILY %s\n", impl.mController.Get(), fontFamily.c_str() );
466           impl.mController->SetInputFontFamily( fontFamily );
467         }
468         break;
469       }
470       case Toolkit::TextEditor::Property::INPUT_FONT_STYLE:
471       {
472         SetFontStyleProperty( impl.mController, value, Text::FontStyle::INPUT );
473         break;
474       }
475       case Toolkit::TextEditor::Property::INPUT_POINT_SIZE:
476       {
477         if( impl.mController )
478         {
479           const float pointSize = value.Get< float >();
480           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p INPUT_POINT_SIZE %f\n", impl.mController.Get(), pointSize );
481           impl.mController->SetInputFontPointSize( pointSize );
482         }
483         break;
484       }
485     } // switch
486   } // texteditor
487 }
488
489 Property::Value TextEditor::GetProperty( BaseObject* object, Property::Index index )
490 {
491   Property::Value value;
492
493   Toolkit::TextEditor textEditor = Toolkit::TextEditor::DownCast( Dali::BaseHandle( object ) );
494
495   if( textEditor )
496   {
497     TextEditor& impl( GetImpl( textEditor ) );
498
499     switch( index )
500     {
501       case Toolkit::TextEditor::Property::RENDERING_BACKEND:
502       {
503         value = impl.mRenderingBackend;
504         break;
505       }
506       case Toolkit::TextEditor::Property::TEXT:
507       {
508         if( impl.mController )
509         {
510           std::string text;
511           impl.mController->GetText( text );
512           DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p returning text: %s\n", impl.mController.Get(), text.c_str() );
513           value = text;
514         }
515         break;
516       }
517       case Toolkit::TextEditor::Property::TEXT_COLOR:
518       {
519         if ( impl.mController )
520         {
521           value = impl.mController->GetTextColor();
522         }
523         break;
524       }
525       case Toolkit::TextEditor::Property::FONT_FAMILY:
526       {
527         if( impl.mController )
528         {
529           value = impl.mController->GetDefaultFontFamily();
530         }
531         break;
532       }
533       case Toolkit::TextEditor::Property::FONT_STYLE:
534       {
535         GetFontStyleProperty( impl.mController, value, Text::FontStyle::DEFAULT );
536         break;
537       }
538       case Toolkit::TextEditor::Property::POINT_SIZE:
539       {
540         if( impl.mController )
541         {
542           value = impl.mController->GetDefaultPointSize();
543         }
544         break;
545       }
546       case Toolkit::TextEditor::Property::HORIZONTAL_ALIGNMENT:
547       {
548         if( impl.mController )
549         {
550           const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( impl.mController->GetLayoutEngine().GetHorizontalAlignment(),
551                                                                                                                 HORIZONTAL_ALIGNMENT_STRING_TABLE,
552                                                                                                                 HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT );
553           if( name )
554           {
555             value = std::string( name );
556           }
557         }
558         break;
559       }
560       case Toolkit::TextEditor::Property::SCROLL_THRESHOLD:
561       {
562         if( impl.mDecorator )
563         {
564           value = impl.mDecorator->GetScrollThreshold();
565         }
566         break;
567       }
568       case Toolkit::TextEditor::Property::SCROLL_SPEED:
569       {
570         if( impl.mDecorator )
571         {
572           value = impl.mDecorator->GetScrollSpeed();
573         }
574         break;
575       }
576       case Toolkit::TextEditor::Property::PRIMARY_CURSOR_COLOR:
577       {
578         if( impl.mDecorator )
579         {
580           value = impl.mDecorator->GetColor( PRIMARY_CURSOR );
581         }
582         break;
583       }
584       case Toolkit::TextEditor::Property::SECONDARY_CURSOR_COLOR:
585       {
586         if( impl.mDecorator )
587         {
588           value = impl.mDecorator->GetColor( SECONDARY_CURSOR );
589         }
590         break;
591       }
592       case Toolkit::TextEditor::Property::ENABLE_CURSOR_BLINK:
593       {
594         value = impl.mController->GetEnableCursorBlink();
595         break;
596       }
597       case Toolkit::TextEditor::Property::CURSOR_BLINK_INTERVAL:
598       {
599         if( impl.mDecorator )
600         {
601           value = impl.mDecorator->GetCursorBlinkInterval();
602         }
603         break;
604       }
605       case Toolkit::TextEditor::Property::CURSOR_BLINK_DURATION:
606       {
607         if( impl.mDecorator )
608         {
609           value = impl.mDecorator->GetCursorBlinkDuration();
610         }
611         break;
612       }
613       case Toolkit::TextEditor::Property::CURSOR_WIDTH:
614       {
615         if( impl.mDecorator )
616         {
617           value = impl.mDecorator->GetCursorWidth();
618         }
619         break;
620       }
621       case Toolkit::TextEditor::Property::GRAB_HANDLE_IMAGE:
622       {
623         if( impl.mDecorator )
624         {
625           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_RELEASED ) );
626           if( image )
627           {
628             value = image.GetUrl();
629           }
630         }
631         break;
632       }
633       case Toolkit::TextEditor::Property::GRAB_HANDLE_PRESSED_IMAGE:
634       {
635         if( impl.mDecorator )
636         {
637           ResourceImage image = ResourceImage::DownCast( impl.mDecorator->GetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_PRESSED ) );
638           if( image )
639           {
640             value = image.GetUrl();
641           }
642         }
643         break;
644       }
645       case Toolkit::TextEditor::Property::SELECTION_HANDLE_IMAGE_LEFT:
646       {
647         impl.GetHandleImagePropertyValue( value, LEFT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED );
648         break;
649       }
650       case Toolkit::TextEditor::Property::SELECTION_HANDLE_IMAGE_RIGHT:
651       {
652         impl.GetHandleImagePropertyValue( value, RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED ) ;
653         break;
654       }
655       case Toolkit::TextEditor::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT:
656       {
657         impl.GetHandleImagePropertyValue( value, LEFT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED );
658         break;
659       }
660       case Toolkit::TextEditor::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT:
661       {
662         impl.GetHandleImagePropertyValue( value, RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED );
663         break;
664       }
665       case Toolkit::TextEditor::Property::SELECTION_HANDLE_MARKER_IMAGE_LEFT:
666       {
667         impl.GetHandleImagePropertyValue( value, LEFT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED );
668         break;
669       }
670       case Toolkit::TextEditor::Property::SELECTION_HANDLE_MARKER_IMAGE_RIGHT:
671       {
672         impl.GetHandleImagePropertyValue( value, RIGHT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED );
673         break;
674       }
675       case Toolkit::TextEditor::Property::SELECTION_HIGHLIGHT_COLOR:
676       {
677         if( impl.mDecorator )
678         {
679           value = impl.mDecorator->GetHighlightColor();
680         }
681         break;
682       }
683       case Toolkit::TextEditor::Property::DECORATION_BOUNDING_BOX:
684       {
685         if( impl.mDecorator )
686         {
687           Rect<int> boundingBox;
688           impl.mDecorator->GetBoundingBox( boundingBox );
689           value = boundingBox;
690         }
691         break;
692       }
693       case Toolkit::TextEditor::Property::ENABLE_MARKUP:
694       {
695         if( impl.mController )
696         {
697           value = impl.mController->IsMarkupProcessorEnabled();
698         }
699         break;
700       }
701       case Toolkit::TextEditor::Property::INPUT_COLOR:
702       {
703         if( impl.mController )
704         {
705           value = impl.mController->GetInputColor();
706         }
707         break;
708       }
709       case Toolkit::TextEditor::Property::INPUT_FONT_FAMILY:
710       {
711         if( impl.mController )
712         {
713           value = impl.mController->GetInputFontFamily();
714         }
715         break;
716       }
717       case Toolkit::TextEditor::Property::INPUT_FONT_STYLE:
718       {
719         GetFontStyleProperty( impl.mController, value, Text::FontStyle::INPUT );
720         break;
721       }
722       case Toolkit::TextEditor::Property::INPUT_POINT_SIZE:
723       {
724         if( impl.mController )
725         {
726           value = impl.mController->GetInputFontPointSize();
727         }
728         break;
729       }
730     } //switch
731   }
732
733   return value;
734 }
735
736 bool TextEditor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
737 {
738   Dali::BaseHandle handle( object );
739
740   bool connected( true );
741   Toolkit::TextEditor editor = Toolkit::TextEditor::DownCast( handle );
742
743   if( 0 == strcmp( signalName.c_str(), SIGNAL_TEXT_CHANGED ) )
744   {
745     editor.TextChangedSignal().Connect( tracker, functor );
746   }
747   else
748   {
749     // signalName does not match any signal
750     connected = false;
751   }
752
753   return connected;
754 }
755
756 Toolkit::TextEditor::TextChangedSignalType& TextEditor::TextChangedSignal()
757 {
758   return mTextChangedSignal;
759 }
760
761 void TextEditor::OnInitialize()
762 {
763   Actor self = Self();
764
765   mController = Text::Controller::New( *this );
766
767   mDecorator = Text::Decorator::New( *mController,
768                                      *mController );
769
770   mController->GetLayoutEngine().SetLayout( LayoutEngine::MULTI_LINE_BOX );
771
772   mController->EnableTextInput( mDecorator );
773
774   mController->SetMaximumNumberOfCharacters( std::numeric_limits<Length>::max() );
775
776   // Forward input events to controller
777   EnableGestureDetection( static_cast<Gesture::Type>( Gesture::Tap | Gesture::Pan | Gesture::LongPress ) );
778   GetTapGestureDetector().SetMaximumTapsRequired( 2 );
779
780   self.TouchedSignal().Connect( this, &TextEditor::OnTouched );
781
782   // Set BoundingBox to stage size if not already set.
783   Rect<int> boundingBox;
784   mDecorator->GetBoundingBox( boundingBox );
785
786   if( boundingBox.IsEmpty() )
787   {
788     Vector2 stageSize = Dali::Stage::GetCurrent().GetSize();
789     mDecorator->SetBoundingBox( Rect<int>( 0.0f, 0.0f, stageSize.width, stageSize.height ) );
790   }
791
792   // Flip vertically the 'left' selection handle
793   mDecorator->FlipHandleVertically( LEFT_SELECTION_HANDLE, true );
794
795   // Fill-parent area by default
796   self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
797   self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
798   self.OnStageSignal().Connect( this, &TextEditor::OnStageConnect );
799 }
800
801 void TextEditor::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
802 {
803   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnStyleChange\n");
804
805   switch ( change )
806   {
807     case StyleChange::DEFAULT_FONT_CHANGE:
808     {
809       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnStyleChange DEFAULT_FONT_CHANGE\n");
810       const std::string& newFont = GetImpl( styleManager ).GetDefaultFontFamily();
811       // Property system did not set the font so should update it.
812       mController->UpdateAfterFontChange( newFont );
813       break;
814     }
815
816     case StyleChange::DEFAULT_FONT_SIZE_CHANGE:
817     {
818       DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor::OnStyleChange StyleChange::DEFAULT_FONT_SIZE_CHANGE (%f)\n", mController->GetDefaultPointSize() );
819
820       if ( (mController->GetDefaultPointSize() <= 0.0f) ) // If DefaultPointSize not set by Property system it will be 0.0f
821       {
822         // Property system did not set the PointSize so should update it.
823         // todo instruct text-controller to update model
824       }
825       break;
826     }
827     case StyleChange::THEME_CHANGE:
828     {
829       GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
830       break;
831     }
832   }
833 }
834
835 Vector3 TextEditor::GetNaturalSize()
836 {
837   return mController->GetNaturalSize();
838 }
839
840 float TextEditor::GetHeightForWidth( float width )
841 {
842   return mController->GetHeightForWidth( width );
843 }
844
845 void TextEditor::OnRelayout( const Vector2& size, RelayoutContainer& container )
846 {
847   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor OnRelayout\n");
848
849   if( mController->Relayout( size ) ||
850       !mRenderer )
851   {
852     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnRelayout %p Displaying new contents\n", mController.Get() );
853
854     if( mDecorator )
855     {
856       mDecorator->Relayout( size );
857     }
858
859     if( !mRenderer )
860     {
861       mRenderer = Backend::Get().NewRenderer( mRenderingBackend );
862     }
863
864     EnableClipping( true, size );
865     RenderText();
866   }
867 }
868
869 void TextEditor::RenderText()
870 {
871   Actor self = Self();
872   Actor renderableActor;
873   if( mRenderer )
874   {
875     renderableActor = mRenderer->Render( mController->GetView(), DepthIndex::TEXT );
876   }
877
878   if( renderableActor != mRenderableActor )
879   {
880     UnparentAndReset( mRenderableActor );
881     mRenderableActor = renderableActor;
882   }
883
884   if( mRenderableActor )
885   {
886     // TODO: Scroll and alignment needs to be refactored.
887     const Vector2& alignmentOffset = mController->GetAlignmentOffset();
888     const Vector2& scrollOffset = mController->GetScrollPosition();
889
890     mRenderableActor.SetPosition( scrollOffset.x, alignmentOffset.y + scrollOffset.y );
891
892     Actor clipRootActor;
893     if( mClipper )
894     {
895       clipRootActor = mClipper->GetRootActor();
896     }
897
898     for( std::vector<Actor>::const_iterator it = mClippingDecorationActors.begin(),
899            endIt = mClippingDecorationActors.end();
900          it != endIt;
901          ++it )
902     {
903       Actor actor = *it;
904
905       if( clipRootActor )
906       {
907         clipRootActor.Add( actor );
908       }
909       else
910       {
911         self.Add( actor );
912       }
913     }
914     mClippingDecorationActors.clear();
915
916     // Make sure the actor is parented correctly with/without clipping
917     if( clipRootActor )
918     {
919       clipRootActor.Add( mRenderableActor );
920     }
921     else
922     {
923       self.Add( mRenderableActor );
924     }
925   }
926 }
927
928 void TextEditor::OnKeyInputFocusGained()
929 {
930   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnKeyInputFocusGained %p\n", mController.Get() );
931
932   VirtualKeyboard::StatusChangedSignal().Connect( this, &TextEditor::KeyboardStatusChanged );
933
934   ImfManager imfManager = ImfManager::Get();
935
936   if ( imfManager )
937   {
938     imfManager.EventReceivedSignal().Connect( this, &TextEditor::OnImfEvent );
939
940     // Notify that the text editing start.
941     imfManager.Activate();
942
943     // When window gain lost focus, the imf manager is deactivated. Thus when window gain focus again, the imf manager must be activated.
944     imfManager.SetRestoreAfterFocusLost( true );
945   }
946
947    ClipboardEventNotifier notifier( ClipboardEventNotifier::Get() );
948
949    if ( notifier )
950    {
951       notifier.ContentSelectedSignal().Connect( this, &TextEditor::OnClipboardTextSelected );
952    }
953
954   mController->KeyboardFocusGainEvent(); // Called in the case of no virtual keyboard to trigger this event
955
956   EmitKeyInputFocusSignal( true ); // Calls back into the Control hence done last.
957 }
958
959 void TextEditor::OnKeyInputFocusLost()
960 {
961   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor:OnKeyInputFocusLost %p\n", mController.Get() );
962
963   VirtualKeyboard::StatusChangedSignal().Disconnect( this, &TextEditor::KeyboardStatusChanged );
964
965   ImfManager imfManager = ImfManager::Get();
966   if ( imfManager )
967   {
968     // The text editing is finished. Therefore the imf manager don't have restore activation.
969     imfManager.SetRestoreAfterFocusLost( false );
970
971     // Notify that the text editing finish.
972     imfManager.Deactivate();
973
974     imfManager.EventReceivedSignal().Disconnect( this, &TextEditor::OnImfEvent );
975   }
976
977   ClipboardEventNotifier notifier( ClipboardEventNotifier::Get() );
978
979   if ( notifier )
980   {
981     notifier.ContentSelectedSignal().Disconnect( this, &TextEditor::OnClipboardTextSelected );
982   }
983
984   mController->KeyboardFocusLostEvent();
985
986   EmitKeyInputFocusSignal( false ); // Calls back into the Control hence done last.
987 }
988
989 void TextEditor::OnTap( const TapGesture& gesture )
990 {
991   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnTap %p\n", mController.Get() );
992
993   // Show the keyboard if it was hidden.
994   if (!VirtualKeyboard::IsVisible())
995   {
996     VirtualKeyboard::Show();
997   }
998
999   // Deliver the tap before the focus event to controller; this allows us to detect when focus is gained due to tap-gestures
1000   mController->TapEvent( gesture.numberOfTaps, gesture.localPoint.x, gesture.localPoint.y );
1001
1002   SetKeyInputFocus();
1003 }
1004
1005 void TextEditor::OnPan( const PanGesture& gesture )
1006 {
1007   mController->PanEvent( gesture.state, gesture.displacement );
1008 }
1009
1010 void TextEditor::OnLongPress( const LongPressGesture& gesture )
1011 {
1012   // Show the keyboard if it was hidden.
1013   if (!VirtualKeyboard::IsVisible())
1014   {
1015     VirtualKeyboard::Show();
1016   }
1017
1018   mController->LongPressEvent( gesture.state, gesture.localPoint.x, gesture.localPoint.y );
1019
1020   SetKeyInputFocus();
1021 }
1022
1023 bool TextEditor::OnKeyEvent( const KeyEvent& event )
1024 {
1025   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnKeyEvent %p keyCode %d\n", mController.Get(), event.keyCode );
1026
1027   if( Dali::DALI_KEY_ESCAPE == event.keyCode ) // Make a Dali key code for this
1028   {
1029     ClearKeyInputFocus();
1030     return true;
1031   }
1032
1033   return mController->KeyEvent( event );
1034 }
1035
1036 void TextEditor::AddDecoration( Actor& actor, bool needsClipping )
1037 {
1038   if( actor )
1039   {
1040     if( needsClipping )
1041     {
1042       mClippingDecorationActors.push_back( actor );
1043     }
1044     else
1045     {
1046       Self().Add( actor );
1047     }
1048   }
1049 }
1050
1051 void TextEditor::RequestTextRelayout()
1052 {
1053   RelayoutRequest();
1054 }
1055
1056 void TextEditor::TextChanged()
1057 {
1058   Dali::Toolkit::TextEditor handle( GetOwner() );
1059   mTextChangedSignal.Emit( handle );
1060 }
1061
1062 void TextEditor::MaxLengthReached()
1063 {
1064   // Nothing to do as TextEditor doesn't emit a max length reached signal.
1065 }
1066
1067 void TextEditor::OnStageConnect( Dali::Actor actor )
1068 {
1069   if ( mHasBeenStaged )
1070   {
1071     RenderText();
1072   }
1073   else
1074   {
1075     mHasBeenStaged = true;
1076   }
1077 }
1078
1079 ImfManager::ImfCallbackData TextEditor::OnImfEvent( Dali::ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent )
1080 {
1081   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::OnImfEvent %p eventName %d\n", mController.Get(), imfEvent.eventName );
1082   return mController->OnImfEvent( imfManager, imfEvent );
1083 }
1084
1085 void TextEditor::GetHandleImagePropertyValue(  Property::Value& value, Text::HandleType handleType, Text::HandleImageType handleImageType )
1086 {
1087   if( mDecorator )
1088   {
1089     ResourceImage image = ResourceImage::DownCast( mDecorator->GetHandleImage( handleType, handleImageType ) );
1090
1091     if ( image )
1092     {
1093       Property::Map map;
1094       Scripting::CreatePropertyMap( image, map );
1095       value = map;
1096     }
1097   }
1098 }
1099
1100 void TextEditor::EnableClipping( bool clipping, const Vector2& size )
1101 {
1102   if( clipping )
1103   {
1104     // Not worth to created clip actor if width or height is equal to zero.
1105     if( size.width > Math::MACHINE_EPSILON_1000 && size.height > Math::MACHINE_EPSILON_1000 )
1106     {
1107       if( !mClipper )
1108       {
1109         Actor self = Self();
1110
1111         mClipper = Clipper::New( size );
1112         self.Add( mClipper->GetRootActor() );
1113         self.Add( mClipper->GetImageActor() );
1114       }
1115       else if ( mClipper )
1116       {
1117         mClipper->Refresh( size );
1118       }
1119     }
1120   }
1121   else
1122   {
1123     // Note - this will automatically remove the root & image actors
1124     mClipper.Reset();
1125   }
1126 }
1127
1128 void TextEditor::OnClipboardTextSelected( ClipboardEventNotifier& clipboard )
1129 {
1130   mController->PasteClipboardItemEvent();
1131 }
1132
1133 void TextEditor::KeyboardStatusChanged(bool keyboardShown)
1134 {
1135   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextEditor::KeyboardStatusChanged %p keyboardShown %d\n", mController.Get(), keyboardShown );
1136
1137   // Just hide the grab handle when keyboard is hidden.
1138   if (!keyboardShown )
1139   {
1140     mController->KeyboardFocusLostEvent();
1141   }
1142   else
1143   {
1144     mController->KeyboardFocusGainEvent(); // Initially called by OnKeyInputFocusGained
1145   }
1146 }
1147
1148 void TextEditor::OnStageConnection( int depth )
1149 {
1150   // Call the Control::OnStageConnection() to set the depth of the background.
1151   Control::OnStageConnection( depth );
1152
1153   // Sets the depth to the renderers inside the text's decorator.
1154   mDecorator->SetTextDepth( depth );
1155
1156   // The depth of the text renderer is set in the RenderText() called from OnRelayout().
1157 }
1158
1159 bool TextEditor::OnTouched( Actor actor, const TouchEvent& event )
1160 {
1161   return true;
1162 }
1163
1164 TextEditor::TextEditor()
1165 : Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ),
1166   mRenderingBackend( DEFAULT_RENDERING_BACKEND ),
1167   mHasBeenStaged( false )
1168 {
1169 }
1170
1171 TextEditor::~TextEditor()
1172 {
1173   mClipper.Reset();
1174 }
1175
1176 } // namespace Internal
1177
1178 } // namespace Toolkit
1179
1180 } // namespace Dali