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