Merge "The advance of the letters is too narrow. So, remove the floor." into devel...
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / text-controls / text-selection-popup-impl.cpp
1 /*
2  * Copyright (c) 2020 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-selection-popup-impl.h>
20
21 // EXTERNAL INCLUDES
22 #if defined(__GLIBC__)
23 #include <libintl.h>
24 #endif
25 #include <string.h>
26 #include <cfloat>
27 #include <dali/public-api/animation/animation.h>
28 #include <dali/public-api/math/vector2.h>
29 #include <dali/public-api/math/vector4.h>
30 #include <dali/public-api/object/property-map.h>
31 #include <dali/public-api/object/type-registry-helper.h>
32 #include <dali/integration-api/debug.h>
33
34 // INTERNAL INCLUDES
35 #include <dali-toolkit/public-api/controls/text-controls/text-label.h>
36 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
37 #include <dali-toolkit/devel-api/controls/control-devel.h>
38 #include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup-callback-interface.h>
39 #include <dali-toolkit/public-api/visuals/color-visual-properties.h>
40 #include <dali-toolkit/public-api/visuals/text-visual-properties.h>
41 #include <dali-toolkit/public-api/visuals/visual-properties.h>
42 #include <dali-toolkit/internal/helpers/color-conversion.h>
43 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
44
45 namespace Dali
46 {
47
48 namespace Toolkit
49 {
50
51 namespace Internal
52 {
53
54 namespace
55 {
56 #if defined(__GLIBC__)
57 #define GET_LOCALE_TEXT(string) dgettext("dali-toolkit", string)
58 #endif
59
60 const std::string TEXT_SELECTION_POPUP_BUTTON_STYLE_NAME( "TextSelectionPopupButton" );
61 const Dali::Vector4 DEFAULT_OPTION_PRESSED_COLOR( Dali::Vector4( 0.24f, 0.72f, 0.8f, 1.0f ) );
62
63 #if defined(DEBUG_ENABLED)
64   Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
65 #endif
66
67 #ifdef DGETTEXT_ENABLED
68
69 #define POPUP_CUT_STRING GET_LOCALE_TEXT("IDS_COM_BODY_CUT")
70 #define POPUP_COPY_STRING GET_LOCALE_TEXT("IDS_COM_BODY_COPY")
71 #define POPUP_PASTE_STRING GET_LOCALE_TEXT("IDS_COM_BODY_PASTE")
72 #define POPUP_SELECT_STRING GET_LOCALE_TEXT("IDS_COM_SK_SELECT")
73 #define POPUP_SELECT_ALL_STRING GET_LOCALE_TEXT("IDS_COM_BODY_SELECT_ALL")
74 #define POPUP_CLIPBOARD_STRING GET_LOCALE_TEXT("IDS_COM_BODY_CLIPBOARD")
75
76 #else
77
78 #define POPUP_CUT_STRING  "Cut"
79 #define POPUP_COPY_STRING  "Copy"
80 #define POPUP_PASTE_STRING  "Paste"
81 #define POPUP_SELECT_STRING  "Select"
82 #define POPUP_SELECT_ALL_STRING  "Select All"
83 #define POPUP_CLIPBOARD_STRING  "Clipboard"
84
85 #endif
86
87 const char* const OPTION_SELECT_WORD = "option-select_word";                       // "Select Word" popup option.
88 const char* const OPTION_SELECT_ALL("option-select_all");                          // "Select All" popup option.
89 const char* const OPTION_CUT("optionCut");                                        // "Cut" popup option.
90 const char* const OPTION_COPY("optionCopy");                                      // "Copy" popup option.
91 const char* const OPTION_PASTE("optionPaste");                                    // "Paste" popup option.
92 const char* const OPTION_CLIPBOARD("optionClipboard");                            // "Clipboard" popup option.
93
94 const std::string IDS_LTR( "IDS_LTR" );
95 const std::string RTL_DIRECTION( "RTL" );
96
97 BaseHandle Create()
98 {
99   return Toolkit::TextSelectionPopup::New( NULL );
100 }
101
102 // Setup properties, signals and actions using the type-registry.
103
104 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextSelectionPopup, Toolkit::Control, Create );
105
106 DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popupMaxSize", VECTOR2,   POPUP_MAX_SIZE )
107 DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popupMinSize", VECTOR2,   POPUP_MIN_SIZE )
108 DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "optionMaxSize", VECTOR2,   OPTION_MAX_SIZE )
109 DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "optionMinSize", VECTOR2,   OPTION_MIN_SIZE )
110 DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "optionDividerSize", VECTOR2,   OPTION_DIVIDER_SIZE )
111 DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popupClipboardButtonImage", STRING, POPUP_CLIPBOARD_BUTTON_ICON_IMAGE )
112 DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popupCutButtonImage", STRING, POPUP_CUT_BUTTON_ICON_IMAGE )
113 DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popupCopyButtonImage", STRING, POPUP_COPY_BUTTON_ICON_IMAGE )
114 DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popupPasteButtonImage", STRING, POPUP_PASTE_BUTTON_ICON_IMAGE )
115 DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popupSelectButtonImage", STRING, POPUP_SELECT_BUTTON_ICON_IMAGE )
116 DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popupSelectAllButtonImage", STRING, POPUP_SELECT_ALL_BUTTON_ICON_IMAGE )
117 DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popupDividerColor", VECTOR4, POPUP_DIVIDER_COLOR )
118 DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popupIconColor", VECTOR4, POPUP_ICON_COLOR )
119 DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popupPressedColor", VECTOR4, POPUP_PRESSED_COLOR )
120 DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popupPressedImage", STRING, POPUP_PRESSED_IMAGE )
121 DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popupFadeInDuration", FLOAT, POPUP_FADE_IN_DURATION )
122 DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popupFadeOutDuration", FLOAT, POPUP_FADE_OUT_DURATION )
123 DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "backgroundBorder", MAP, BACKGROUND_BORDER )
124
125 DALI_TYPE_REGISTRATION_END()
126
127 } // namespace
128
129
130 Dali::Toolkit::TextSelectionPopup TextSelectionPopup::New( TextSelectionPopupCallbackInterface* callbackInterface )
131 {
132   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextSelectionPopup::New\n" );
133
134    // Create the implementation, temporarily owned by this handle on stack
135   IntrusivePtr< TextSelectionPopup > impl = new TextSelectionPopup( callbackInterface );
136
137   // Pass ownership to CustomActor handle
138   Dali::Toolkit::TextSelectionPopup handle( *impl );
139
140   // Second-phase init of the implementation
141   // This can only be done after the CustomActor connection has been made...
142   impl->Initialize();
143
144   return handle;
145 }
146
147 void TextSelectionPopup::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
148 {
149   Toolkit::TextSelectionPopup selectionPopup = Toolkit::TextSelectionPopup::DownCast( Dali::BaseHandle( object ) );
150
151   if( selectionPopup )
152   {
153     TextSelectionPopup& impl( GetImpl( selectionPopup ) );
154
155     switch( index )
156     {
157       case Toolkit::TextSelectionPopup::Property::POPUP_MAX_SIZE:
158       {
159        impl.SetDimensionToCustomise( POPUP_MAXIMUM_SIZE, value.Get< Vector2 >() );
160        break;
161       }
162       case Toolkit::TextSelectionPopup::Property::OPTION_MAX_SIZE:
163       {
164         impl.SetDimensionToCustomise( OPTION_MAXIMUM_SIZE, value.Get< Vector2 >() );
165         break;
166       }
167       case Toolkit::TextSelectionPopup::Property::OPTION_MIN_SIZE:
168       {
169         impl.SetDimensionToCustomise( OPTION_MINIMUM_SIZE, value.Get< Vector2>() );
170         break;
171       }
172       case Toolkit::TextSelectionPopup::Property::OPTION_DIVIDER_SIZE:
173       {
174         impl.SetDimensionToCustomise( OPTION_DIVIDER_SIZE, value.Get< Vector2>() );
175         break;
176       }
177       case Toolkit::TextSelectionPopup::Property::POPUP_CLIPBOARD_BUTTON_ICON_IMAGE:
178       {
179         impl.SetButtonImage( Toolkit::TextSelectionPopup::CLIPBOARD, value.Get< std::string >() );
180         break;
181       }
182       case Toolkit::TextSelectionPopup::Property::POPUP_CUT_BUTTON_ICON_IMAGE:
183       {
184         impl.SetButtonImage( Toolkit::TextSelectionPopup::CUT, value.Get< std::string >() );
185         break;
186       }
187       case Toolkit::TextSelectionPopup::Property::POPUP_COPY_BUTTON_ICON_IMAGE:
188       {
189         impl.SetButtonImage( Toolkit::TextSelectionPopup::COPY, value.Get< std::string >() );
190         break;
191       }
192       case Toolkit::TextSelectionPopup::Property::POPUP_PASTE_BUTTON_ICON_IMAGE:
193       {
194         impl.SetButtonImage( Toolkit::TextSelectionPopup::PASTE, value.Get< std::string >() );
195         break;
196       }
197       case Toolkit::TextSelectionPopup::Property::POPUP_SELECT_BUTTON_ICON_IMAGE:
198       {
199         impl.SetButtonImage( Toolkit::TextSelectionPopup::SELECT, value.Get< std::string >() );
200         break;
201       }
202       case Toolkit::TextSelectionPopup::Property::POPUP_SELECT_ALL_BUTTON_ICON_IMAGE:
203       {
204         impl.SetButtonImage( Toolkit::TextSelectionPopup::SELECT_ALL, value.Get< std::string >() );
205         break;
206       }
207       case Toolkit::TextSelectionPopup::Property::POPUP_DIVIDER_COLOR:
208       {
209         impl.mDividerColor = value.Get< Vector4 >();
210         break;
211       }
212       case Toolkit::TextSelectionPopup::Property::POPUP_ICON_COLOR:
213       {
214         impl.mIconColor = value.Get< Vector4 >();
215         break;
216       }
217       case Toolkit::TextSelectionPopup::Property::POPUP_PRESSED_COLOR:
218       {
219         impl.mPressedColor = value.Get< Vector4 >();
220         break;
221       }
222       case Toolkit::TextSelectionPopup::Property::POPUP_PRESSED_IMAGE:
223       {
224         impl.SetPressedImage( value.Get< std::string >() );
225         break;
226       }
227       case Toolkit::TextSelectionPopup::Property::POPUP_FADE_IN_DURATION:
228       {
229         impl.mFadeInDuration = value.Get < float >();
230         break;
231       }
232       case Toolkit::TextSelectionPopup::Property::POPUP_FADE_OUT_DURATION:
233       {
234         impl.mFadeOutDuration = value.Get < float >();
235         break;
236       }
237       case Toolkit::TextSelectionPopup::Property::BACKGROUND_BORDER:
238       {
239         Property::Map map = value.Get<Property::Map>();
240         impl.CreateBackgroundBorder( map );
241         break;
242       }
243     } // switch
244   } // TextSelectionPopup
245 }
246
247 Property::Value TextSelectionPopup::GetProperty( BaseObject* object, Property::Index index )
248 {
249   Property::Value value;
250
251   Toolkit::TextSelectionPopup selectionPopup = Toolkit::TextSelectionPopup::DownCast( Dali::BaseHandle( object ) );
252
253   if( selectionPopup )
254   {
255     TextSelectionPopup& impl( GetImpl( selectionPopup ) );
256
257     switch( index )
258     {
259       case Toolkit::TextSelectionPopup::Property::POPUP_MAX_SIZE:
260       {
261         value = impl.GetDimensionToCustomise( POPUP_MAXIMUM_SIZE );
262         break;
263       }
264       case Toolkit::TextSelectionPopup::Property::OPTION_MAX_SIZE:
265       {
266         value = impl.GetDimensionToCustomise( OPTION_MAXIMUM_SIZE );
267         break;
268       }
269       case Toolkit::TextSelectionPopup::Property::OPTION_MIN_SIZE:
270       {
271         value = impl.GetDimensionToCustomise( OPTION_MINIMUM_SIZE );
272         break;
273       }
274       case Toolkit::TextSelectionPopup::Property::OPTION_DIVIDER_SIZE:
275       {
276         value = impl.GetDimensionToCustomise( OPTION_DIVIDER_SIZE );
277         break;
278       }
279       case Toolkit::TextSelectionPopup::Property::POPUP_CLIPBOARD_BUTTON_ICON_IMAGE:
280       {
281         value = impl.GetButtonImage( Toolkit::TextSelectionPopup::CLIPBOARD );
282         break;
283       }
284       case Toolkit::TextSelectionPopup::Property::POPUP_CUT_BUTTON_ICON_IMAGE:
285       {
286         value = impl.GetButtonImage( Toolkit::TextSelectionPopup::CUT );
287         break;
288       }
289       case Toolkit::TextSelectionPopup::Property::POPUP_COPY_BUTTON_ICON_IMAGE:
290       {
291         value = impl.GetButtonImage( Toolkit::TextSelectionPopup::COPY );
292         break;
293       }
294       case Toolkit::TextSelectionPopup::Property::POPUP_PASTE_BUTTON_ICON_IMAGE:
295       {
296         value = impl.GetButtonImage( Toolkit::TextSelectionPopup::PASTE );
297         break;
298       }
299       case Toolkit::TextSelectionPopup::Property::POPUP_SELECT_BUTTON_ICON_IMAGE:
300       {
301         value = impl.GetButtonImage( Toolkit::TextSelectionPopup::SELECT );
302         break;
303       }
304       case Toolkit::TextSelectionPopup::Property::POPUP_SELECT_ALL_BUTTON_ICON_IMAGE:
305       {
306         value = impl.GetButtonImage( Toolkit::TextSelectionPopup::SELECT_ALL );
307         break;
308       }
309       case Toolkit::TextSelectionPopup::Property::POPUP_PRESSED_IMAGE:
310       {
311         value = impl.GetPressedImage();
312         break;
313       }
314       case Toolkit::TextSelectionPopup::Property::POPUP_FADE_IN_DURATION:
315       {
316         value = impl.mFadeInDuration;
317         break;
318       }
319       case Toolkit::TextSelectionPopup::Property::POPUP_FADE_OUT_DURATION:
320       {
321         value = impl.mFadeOutDuration;
322         break;
323       }
324       case Toolkit::TextSelectionPopup::Property::BACKGROUND_BORDER:
325       {
326         Property::Map map;
327         Toolkit::Visual::Base visual = DevelControl::GetVisual( impl, Toolkit::TextSelectionPopup::Property::BACKGROUND_BORDER );
328         if( visual )
329         {
330           visual.CreatePropertyMap( map );
331         }
332         value = map;
333         break;
334       }
335     } // switch
336   }
337   return value;
338 }
339
340 void TextSelectionPopup::EnableButtons( Toolkit::TextSelectionPopup::Buttons buttonsToEnable )
341 {
342   mEnabledButtons = buttonsToEnable;
343   mButtonsChanged = true;
344 }
345
346 void TextSelectionPopup::RaiseAbove( Layer target )
347 {
348   if( mToolbar )
349   {
350     mToolbar.RaiseAbove( target );
351   }
352 }
353
354 void TextSelectionPopup::ShowPopup()
355 {
356   if( ( !mPopupShowing || mButtonsChanged ) &&
357       ( Toolkit::TextSelectionPopup::NONE != mEnabledButtons ) )
358   {
359     Actor self = Self();
360     AddPopupOptionsToToolbar( mShowIcons, mShowCaptions );
361
362     Animation animation = Animation::New( mFadeInDuration );
363     animation.AnimateTo( Property(self, Actor::Property::COLOR_ALPHA), 1.0f  );
364     animation.Play();
365     mPopupShowing = true;
366   }
367 }
368
369 void TextSelectionPopup::HidePopup()
370 {
371   if ( mPopupShowing )
372   {
373     mPopupShowing = false;
374     Actor self = Self();
375     Animation animation = Animation::New( mFadeOutDuration );
376     animation.AnimateTo( Property(self, Actor::Property::COLOR_ALPHA), 0.0f  );
377     animation.FinishedSignal().Connect( this, &TextSelectionPopup::HideAnimationFinished );
378     animation.Play();
379   }
380 }
381
382 void TextSelectionPopup::OnInitialize()
383 {
384   DALI_LOG_INFO( gLogFilter, Debug::General, "TextSelectionPopup::OnInitialize\n" );
385   Actor self = Self();
386   self.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
387   self.SetProperty( Actor::Property::COLOR_ALPHA, 0.0f );
388 }
389
390 void TextSelectionPopup::HideAnimationFinished( Animation& animation )
391 {
392   Actor self = Self();
393   if ( !mPopupShowing ) // During the Hide/Fade animation there could be a call to Show the Popup again, mPopupShowing will be true in this case.
394   {
395     DALI_LOG_INFO( gLogFilter, Debug::General, "TextSelectionPopup::HideAnimationFinished\n" );
396     UnparentAndReset( mToolbar );
397   }
398 }
399
400 bool TextSelectionPopup::OnCutButtonPressed( Toolkit::Button button )
401 {
402   if( mCallbackInterface )
403   {
404     mCallbackInterface->TextPopupButtonTouched( Toolkit::TextSelectionPopup::CUT );
405   }
406
407   return true;
408 }
409
410 bool TextSelectionPopup::OnCopyButtonPressed( Toolkit::Button button )
411 {
412   if( mCallbackInterface )
413   {
414     mCallbackInterface->TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::COPY );
415   }
416
417   return true;
418 }
419
420 bool TextSelectionPopup::OnPasteButtonPressed( Toolkit::Button button )
421 {
422   if( mCallbackInterface )
423   {
424     mCallbackInterface->TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::PASTE );
425   }
426
427   return true;
428 }
429
430 bool TextSelectionPopup::OnSelectButtonPressed( Toolkit::Button button )
431 {
432   if( mCallbackInterface )
433   {
434     mCallbackInterface->TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::SELECT );
435   }
436
437   return true;
438 }
439
440 bool TextSelectionPopup::OnSelectAllButtonPressed( Toolkit::Button button )
441 {
442   if( mCallbackInterface )
443   {
444     mCallbackInterface->TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::SELECT_ALL );
445   }
446
447   return true;
448 }
449
450 bool TextSelectionPopup::OnClipboardButtonPressed( Toolkit::Button button )
451 {
452   if( mCallbackInterface )
453   {
454     mCallbackInterface->TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::CLIPBOARD );
455   }
456
457   return true;
458 }
459
460 void TextSelectionPopup::SetDimensionToCustomise( const PopupCustomisations& settingToCustomise, const Size& dimension )
461 {
462   switch( settingToCustomise )
463   {
464     case POPUP_MAXIMUM_SIZE :
465     {
466       mPopupMaxSize = dimension;
467       if ( mToolbar )
468       {
469         mToolbar.SetProperty( Toolkit::TextSelectionToolbar::Property::MAX_SIZE, dimension );
470       }
471       break;
472     }
473     case OPTION_MAXIMUM_SIZE :
474     {
475       mOptionMaxSize = dimension;
476       // Option max size not currently currently supported
477       break;
478     }
479     case OPTION_MINIMUM_SIZE :
480     {
481       mOptionMinSize = dimension;
482       // Option min size not currently currently supported
483       break;
484     }
485     case OPTION_DIVIDER_SIZE :
486     {
487       mOptionDividerSize = dimension;
488       if ( mToolbar )
489       {
490         // Resize Dividers not currently supported
491       }
492       break;
493     }
494   } // switch
495 }
496
497 Size TextSelectionPopup::GetDimensionToCustomise( const PopupCustomisations& settingToCustomise ) const
498 {
499   switch( settingToCustomise )
500   {
501     case POPUP_MAXIMUM_SIZE :
502     {
503       if ( mToolbar )
504       {
505         return mToolbar.GetProperty( Toolkit::TextSelectionToolbar::Property::MAX_SIZE ).Get< Vector2 >();
506       }
507       else
508       {
509         return mPopupMaxSize;
510       }
511     }
512     case OPTION_MAXIMUM_SIZE :
513     {
514       return mOptionMaxSize;
515     }
516     case OPTION_MINIMUM_SIZE :
517     {
518       return mOptionMinSize;
519     }
520     case OPTION_DIVIDER_SIZE :
521     {
522       return mOptionDividerSize;
523     }
524   } // switch
525
526   return Size::ZERO;
527 }
528
529 void TextSelectionPopup::SetButtonImage( Toolkit::TextSelectionPopup::Buttons button, const std::string& image )
530 {
531    switch ( button )
532    {
533      case Toolkit::TextSelectionPopup::CLIPBOARD:
534      {
535        mClipboardIconImage  = image;
536        break;
537      }
538      case Toolkit::TextSelectionPopup::CUT :
539      {
540        mCutIconImage = image;
541        break;
542      }
543      case Toolkit::TextSelectionPopup::COPY :
544      {
545        mCopyIconImage = image;
546        break;
547      }
548      case Toolkit::TextSelectionPopup::PASTE :
549      {
550        mPasteIconImage = image;
551        break;
552      }
553      case Toolkit::TextSelectionPopup::SELECT :
554      {
555        mSelectIconImage = image;
556        break;
557      }
558      case Toolkit::TextSelectionPopup::SELECT_ALL :
559      {
560        mSelectAllIconImage = image;
561        break;
562      }
563      default :
564      {
565        DALI_ASSERT_DEBUG( "TextSelectionPopup SetPopupImage Unknown Button" );
566      }
567    } // switch
568 }
569
570 const std::string& TextSelectionPopup::GetButtonImage( Toolkit::TextSelectionPopup::Buttons button ) const
571 {
572   switch ( button )
573   {
574     case Toolkit::TextSelectionPopup::CLIPBOARD:
575     {
576       return mClipboardIconImage;
577       break;
578     }
579     case Toolkit::TextSelectionPopup::CUT:
580     {
581       return mCutIconImage;
582       break;
583     }
584     case Toolkit::TextSelectionPopup::COPY:
585     {
586       return mCopyIconImage;
587       break;
588     }
589     case Toolkit::TextSelectionPopup::PASTE:
590     {
591       return mPasteIconImage;
592       break;
593     }
594     case Toolkit::TextSelectionPopup::SELECT:
595     {
596       return mSelectIconImage;
597       break;
598     }
599     case Toolkit::TextSelectionPopup::SELECT_ALL:
600     {
601       return mSelectAllIconImage;
602       break;
603     }
604     case Toolkit::TextSelectionPopup::NONE:
605     {
606       break;
607     }
608   } // switch
609
610   DALI_ASSERT_DEBUG( "TextSelectionPopup GetPopupImage Unknown Button" );
611   static std::string empty;
612   return empty;
613 }
614
615 void TextSelectionPopup::SetPressedImage( const std::string& filename )
616 {
617   mPressedImage = filename;
618 }
619
620 std::string TextSelectionPopup::GetPressedImage() const
621 {
622   return mPressedImage;
623 }
624
625  void TextSelectionPopup::CreateOrderedListOfPopupOptions()
626  {
627    mOrderListOfButtons.clear();
628    mOrderListOfButtons.reserve( 8u );
629
630    // Create button for each possible option using Option priority
631    mOrderListOfButtons.push_back( ButtonRequirement( Toolkit::TextSelectionPopup::CUT, mCutOptionPriority, OPTION_CUT, POPUP_CUT_STRING , 0 != ( mEnabledButtons & Toolkit::TextSelectionPopup::CUT)  ) );
632    mOrderListOfButtons.push_back( ButtonRequirement( Toolkit::TextSelectionPopup::COPY, mCopyOptionPriority, OPTION_COPY, POPUP_COPY_STRING, 0 != ( mEnabledButtons & Toolkit::TextSelectionPopup::COPY)  ) );
633    mOrderListOfButtons.push_back( ButtonRequirement( Toolkit::TextSelectionPopup::PASTE, mPasteOptionPriority, OPTION_PASTE, POPUP_PASTE_STRING, 0 != ( mEnabledButtons & Toolkit::TextSelectionPopup::PASTE)  ) );
634    mOrderListOfButtons.push_back( ButtonRequirement( Toolkit::TextSelectionPopup::SELECT, mSelectOptionPriority, OPTION_SELECT_WORD, POPUP_SELECT_STRING, 0 != ( mEnabledButtons & Toolkit::TextSelectionPopup::SELECT)  ) );
635    mOrderListOfButtons.push_back( ButtonRequirement( Toolkit::TextSelectionPopup::SELECT_ALL, mSelectAllOptionPriority, OPTION_SELECT_ALL, POPUP_SELECT_ALL_STRING, 0 != ( mEnabledButtons & Toolkit::TextSelectionPopup::SELECT_ALL)  ) );
636    mOrderListOfButtons.push_back( ButtonRequirement( Toolkit::TextSelectionPopup::CLIPBOARD, mClipboardOptionPriority, OPTION_CLIPBOARD, POPUP_CLIPBOARD_STRING, 0 != ( mEnabledButtons & Toolkit::TextSelectionPopup::CLIPBOARD)  ) );
637
638    // Sort the buttons according their priorities.
639    std::sort( mOrderListOfButtons.begin(), mOrderListOfButtons.end(), TextSelectionPopup::ButtonPriorityCompare() );
640  }
641
642  void TextSelectionPopup::AddOption( const ButtonRequirement& button, bool showDivider, bool showIcons, bool showCaption  )
643  {
644    // 1. Create a option.
645    DALI_LOG_INFO( gLogFilter, Debug::General, "TextSelectionPopup::AddOption\n" );
646
647    Toolkit::PushButton option = Toolkit::PushButton::New();
648    option.SetProperty( Dali::Actor::Property::NAME, button.name );
649    option.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
650
651    switch( button.id )
652    {
653      case Toolkit::TextSelectionPopup::CUT:
654      {
655        option.ClickedSignal().Connect( this, &TextSelectionPopup::OnCutButtonPressed );
656        break;
657      }
658      case Toolkit::TextSelectionPopup::COPY:
659      {
660        option.ClickedSignal().Connect( this, &TextSelectionPopup::OnCopyButtonPressed );
661        break;
662      }
663      case Toolkit::TextSelectionPopup::PASTE:
664      {
665        option.ClickedSignal().Connect( this, &TextSelectionPopup::OnPasteButtonPressed );
666        break;
667      }
668      case Toolkit::TextSelectionPopup::SELECT:
669      {
670        option.ClickedSignal().Connect( this, &TextSelectionPopup::OnSelectButtonPressed );
671        break;
672      }
673      case Toolkit::TextSelectionPopup::SELECT_ALL:
674      {
675        option.ClickedSignal().Connect( this, &TextSelectionPopup::OnSelectAllButtonPressed );
676        break;
677      }
678      case Toolkit::TextSelectionPopup::CLIPBOARD:
679      {
680        option.ClickedSignal().Connect( this, &TextSelectionPopup::OnClipboardButtonPressed );
681        break;
682      }
683      case Toolkit::TextSelectionPopup::NONE:
684      {
685        // Nothing to do:
686        break;
687      }
688    }
689
690    // 2. Set the options contents.
691    if( showCaption )
692    {
693      // PushButton layout properties.
694      option.SetProperty( Toolkit::PushButton::Property::LABEL_PADDING, Vector4( 24.0f, 24.0f, 14.0f, 14.0f ) );
695
696      // Label properties.
697      Property::Map buttonLabelProperties;
698      buttonLabelProperties.Insert( Toolkit::TextVisual::Property::TEXT, button.caption );
699      option.SetProperty( Toolkit::Button::Property::LABEL, buttonLabelProperties );
700    }
701    if( showIcons )
702    {
703      option.SetProperty( Toolkit::PushButton::Property::ICON_PADDING, Vector4( 10.0f, 10.0f, 10.0f, 10.0f ) );
704      option.SetProperty( Toolkit::PushButton::Property::ICON_ALIGNMENT, "TOP" );
705
706      // TODO: This is temporarily disabled until the text-selection-popup image API is changed to strings.
707      //option.SetProperty( Toolkit::PushButton::Property::SELECTED_ICON, button.icon );
708      //option.SetProperty( Toolkit::PushButton::Property::UNSELECTED_ICON, button.icon );
709    }
710
711    // 3. Set the normal option image (blank / Transparent).
712    option.SetProperty( Toolkit::Button::Property::UNSELECTED_BACKGROUND_VISUAL, "" );
713
714    // 4. Set the pressed option image.
715    Property::Value selectedBackgroundValue( mPressedImage );
716    if( mPressedImage.empty() )
717    {
718      // The image can be blank, the color can be used in that case.
719      selectedBackgroundValue = Property::Value{ { Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR  },
720                                                 { Toolkit::ColorVisual::Property::MIX_COLOR, mPressedColor } };
721    }
722    option.SetProperty( Toolkit::Button::Property::SELECTED_BACKGROUND_VISUAL, selectedBackgroundValue );
723    option.SetProperty( Toolkit::Control::Property::STYLE_NAME, TEXT_SELECTION_POPUP_BUTTON_STYLE_NAME );
724
725    // 5 Add option to tool bar
726    mToolbar.AddOption( option );
727
728    // 6. Add the divider
729    if( showDivider )
730    {
731      const Size size( mOptionDividerSize.width, 0.0f ); // Height FILL_TO_PARENT
732
733      Toolkit::Control divider = Toolkit::Control::New();
734 #ifdef DECORATOR_DEBUG
735      divider.SetProperty( Dali::Actor::Property::NAME,"Text's popup divider");
736 #endif
737      divider.SetProperty( Actor::Property::SIZE, size );
738      divider.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
739      divider.SetBackgroundColor( mDividerColor  );
740      mToolbar.AddDivider( divider );
741    }
742  }
743
744  std::size_t TextSelectionPopup::GetNumberOfEnabledOptions() const
745  {
746    std::size_t numberOfOptions = 0u;
747    for( std::vector<ButtonRequirement>::const_iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt ); ++it )
748    {
749      const ButtonRequirement& button( *it );
750      if( button.enabled )
751      {
752        ++numberOfOptions;
753      }
754    }
755
756    return numberOfOptions;
757  }
758
759  void TextSelectionPopup::AddPopupOptionsToToolbar( bool showIcons, bool showCaptions )
760  {
761    DALI_LOG_INFO( gLogFilter, Debug::General, "TextSelectionPopup::AddPopupOptionsToToolbar\n" );
762
763    CreateOrderedListOfPopupOptions();
764
765    mButtonsChanged = false;
766    UnparentAndReset( mToolbar);
767
768    if( !mToolbar )
769    {
770      Actor self = Self();
771      mToolbar = Toolkit::TextSelectionToolbar::New();
772      if ( mPopupMaxSize != Vector2::ZERO ) // If PopupMaxSize property set then apply to Toolbar. Toolbar currently is not retriving this from json
773      {
774        mToolbar.SetProperty( Toolkit::TextSelectionToolbar::Property::MAX_SIZE, mPopupMaxSize );
775      }
776      mToolbar.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
777 #ifdef DECORATOR_DEBUG
778      mToolbar.SetProperty( Dali::Actor::Property::NAME,"TextSelectionToolbar");
779 #endif
780      self.Add( mToolbar );
781    }
782
783    // Whether to mirror the list of buttons (for right to left languages)
784    bool mirror = false;
785 #if defined(__GLIBC__)
786    char* idsLtr = GET_LOCALE_TEXT( IDS_LTR.c_str() );
787    if( NULL != idsLtr )
788    {
789      mirror = ( 0 == strcmp( idsLtr, RTL_DIRECTION.c_str() ) );
790
791      if( mirror )
792      {
793        std::reverse( mOrderListOfButtons.begin(), mOrderListOfButtons.end() );
794      }
795    }
796 #endif
797
798    // Iterate list of buttons and add active ones to Toolbar
799    std::size_t numberOfOptionsRequired =  GetNumberOfEnabledOptions();
800    std::size_t numberOfOptionsAdded = 0u;
801    for( std::vector<ButtonRequirement>::const_iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt ); ++it )
802    {
803      const ButtonRequirement& button( *it );
804      if ( button.enabled )
805      {
806        numberOfOptionsAdded++;
807        AddOption(  button, ( numberOfOptionsAdded < numberOfOptionsRequired ) , showIcons, showCaptions );
808      }
809    }
810
811    if( mirror )
812    {
813      mToolbar.ScrollTo( Vector2( mPopupMaxSize.x, 0.f ) );
814    }
815  }
816
817 void TextSelectionPopup::CreateBackgroundBorder( Property::Map& propertyMap )
818 {
819   // Removes previous image if necessary
820   DevelControl::UnregisterVisual( *this, Toolkit::TextSelectionPopup::Property::BACKGROUND_BORDER );
821
822   if( ! propertyMap.Empty() )
823   {
824     Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( propertyMap );
825
826     if( visual )
827     {
828       DevelControl::RegisterVisual( *this, Toolkit::TextSelectionPopup::Property::BACKGROUND_BORDER, visual, DepthIndex::CONTENT );
829     }
830   }
831 }
832
833 TextSelectionPopup::TextSelectionPopup( TextSelectionPopupCallbackInterface* callbackInterface )
834 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
835   mToolbar(),
836   mPopupMaxSize(),
837   mOptionMaxSize(),
838   mOptionMinSize(),
839   mOptionDividerSize(),
840   mEnabledButtons( Toolkit::TextSelectionPopup::NONE ),
841   mCallbackInterface( callbackInterface ),
842   mPressedColor( DEFAULT_OPTION_PRESSED_COLOR ),
843   mDividerColor( Color::WHITE ),
844   mIconColor( Color::WHITE ),
845   mSelectOptionPriority( 1 ),
846   mSelectAllOptionPriority ( 2 ),
847   mCutOptionPriority ( 4 ),
848   mCopyOptionPriority ( 3 ),
849   mPasteOptionPriority ( 5 ),
850   mClipboardOptionPriority( 6 ),
851   mFadeInDuration(0.0f),
852   mFadeOutDuration(0.0f),
853   mShowIcons( false ),
854   mShowCaptions( true ),
855   mPopupShowing( false ),
856   mButtonsChanged( false )
857 {
858 }
859
860 TextSelectionPopup::~TextSelectionPopup()
861 {
862 }
863
864
865 } // namespace Internal
866
867 } // namespace Toolkit
868
869 } // namespace Dali