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