9951f88510a160cae00ec78a2c5518a9ae1c48e7
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / internal / controls / text-input / text-input-popup-impl.cpp
1 /*
2  * Copyright (c) 2014 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 #include <dali/integration-api/debug.h>
19
20 #include <dali-toolkit/internal/controls/text-input/text-input-popup-impl.h>
21 #include <dali-toolkit/public-api/controls/buttons/push-button.h>
22 #include <dali-toolkit/public-api/controls/default-controls/solid-color-actor.h>
23
24 #include <libintl.h>
25
26 using namespace std;
27 using namespace Dali;
28
29 #define GET_LOCALE_TEXT(string) dgettext("sys_string", string)
30
31 namespace
32 {
33 const Vector2 DEFAULT_POPUP_INDICATOR_OFFSET(0.0f, 60.0f);
34
35 // 1. For selection: should be above top of highlighted selection, or below bottom of highlighted selection + end handle.
36 // 2. For cursor: should be above top of cursor, or below bottom of cursor + grab handle.
37
38 /**
39  * Image resource paths
40  */
41 const std::string POPUP_BACKGROUND( DALI_IMAGE_DIR "popup_bubble_bg.#.png" );
42 const std::string POPUP_BACKGROUND_EFFECT( DALI_IMAGE_DIR "popup_bubble_bg_ef.#.png" );
43 const std::string POPUP_BACKGROUND_LINE( DALI_IMAGE_DIR "popup_bubble_bg_line.#.png" );
44
45 const std::string POPUP_TAIL_BOTTOM( DALI_IMAGE_DIR "popup_bubble_tail_bottom.png" );
46 const std::string POPUP_TAIL_BOTTOM_EFFECT( DALI_IMAGE_DIR "popup_bubble_tail_bottom_ef.png" );
47 const std::string POPUP_TAIL_BOTTOM_LINE( DALI_IMAGE_DIR "popup_bubble_tail_bottom_line.png" );
48 const std::string POPUP_TAIL_TOP( DALI_IMAGE_DIR "popup_bubble_tail_top.png" );
49 const std::string POPUP_TAIL_TOP_EFFECT( DALI_IMAGE_DIR "popup_bubble_tail_top_ef.png" );
50 const std::string POPUP_TAIL_TOP_LINE( DALI_IMAGE_DIR "popup_bubble_tail_top_line.png" );
51
52 const std::string OPTION_ICON_CLIPBOARD( DALI_IMAGE_DIR "copy_paste_icon_clipboard.png" );
53 const std::string OPTION_ICON_COPY( DALI_IMAGE_DIR "copy_paste_icon_copy.png" );
54 const std::string OPTION_ICON_CUT( DALI_IMAGE_DIR "copy_paste_icon_cut.png" );
55 const std::string OPTION_ICON_PASTE( DALI_IMAGE_DIR "copy_paste_icon_paste.png" );
56 const std::string OPTION_ICON_SELECT( DALI_IMAGE_DIR "copy_paste_icon_select.png" );
57 const std::string OPTION_ICON_SELECT_ALL( DALI_IMAGE_DIR "copy_paste_icon_select_all.png" );
58
59 /**
60  * Constant values for building the GUI
61  */
62 const Vector4 POPUP_BORDER( 14.0f, 14.0f, 14.0f, 14.0f );  ///< The margin of the popup.
63 const Vector2 POPUP_MIN_SIZE( 0.0f, 126.0f );  ///< The minimum size of the popup.
64 const Vector2 POPUP_MAX_SIZE( 720.0f, 126.0f );  ///< The maximum size of the popup.
65 const float POPUP_TAIL_Y_OFFSET( -2.25f );  ///< The y offset of the tail.
66 const Vector2 POPUP_TAIL_SIZE( 36.0f, 36.0f );  ///< The size of the tail.
67 const Vector2 POPUP_DIVIDER_SIZE( 1.0f, 126.0f );  ///< The size of the divider.
68
69 const Vector4 OPTION_MARGIN( 0.0f, 0.0f, 24.0f, 19.0f );  ///< The margin of the icon. the order is left, right, top and bottom
70 const Vector2 OPTION_MAX_SIZE( 360.0f, 126.0f );  ///< The maximum size of the option.
71 const Vector2 OPTION_MIN_SIZE( 128.0f, 126.0f );  ///< The minimum size of the option.
72 const Vector2 OPTION_ICON_SIZE( 45.0f, 45.0f );  ///< The size of the icon.
73 const Vector2 OPTION_TEXT_MIN_SIZE( 128.0f, 30.0f );  ///< The minimum size of the text.
74 const float OPTION_GAP_ICON_TEXT( 8.0f );  ///< The gap between the icon and the text
75
76 const float HIDE_POPUP_ANIMATION_DURATION( 0.2f );                            ///< Duration of popup hide animation in seconds.
77 const float SHOW_POPUP_ANIMATION_DURATION( 0.2f );                            ///< Duration of popup show animation in seconds.
78
79 /**
80  * Default Colors
81  */
82 const Vector4 DEFAULT_POPUP_BACKGROUND( Vector4( .20f, 0.29f, 0.44f, 1.0f ) );
83 const Vector4 DEFAULT_POPUP_BACKGROUND_PRESSED( Vector4( 0.07f, 0.10f, 0.17f, 1.0f ) );
84 const Vector4 DEFAULT_POPUP_LINE_COLOR( Vector4( 0.36f, 0.45f, 0.59f, 1.0f ) );
85 const Vector4 DEFAULT_OPTION_ICON( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) );
86 const Vector4 DEFAULT_OPTION_ICON_PRESSED( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) );
87 const Vector4 DEFAULT_OPTION_TEXT( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) );
88 const Vector4 DEFAULT_OPTION_TEXT_PRESSED( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) );
89
90 } // unnamed namespace
91
92 namespace Dali
93 {
94
95 namespace Toolkit
96 {
97
98 namespace Internal
99 {
100
101 const char* const TextInputPopup::SIGNAL_PRESSED = "pressed";
102 const char* const TextInputPopup::SIGNAL_HIDE_FINISHED = "hide-finished";
103 const char* const TextInputPopup::SIGNAL_SHOW_FINISHED = "show-finished";
104
105 const char* const TextInputPopup::OPTION_SELECT_WORD = "option-select_word";                       // "Select Word" popup option.
106 const char* const TextInputPopup::OPTION_SELECT_ALL("option-select_all");                          // "Select All" popup option.
107 const char* const TextInputPopup::OPTION_CUT("option-cut");                                        // "Cut" popup option.
108 const char* const TextInputPopup::OPTION_COPY("option-copy");                                      // "Copy" popup option.
109 const char* const TextInputPopup::OPTION_PASTE("option-paste");                                    // "Paste" popup option.
110 const char* const TextInputPopup::OPTION_CLIPBOARD("option-clipboard");                            // "Clipboard" popup option.
111
112 TextInputPopup::TextInputPopup()
113 : mState(StateHidden),
114   mRoot(Layer::New()),
115   mVisiblePopUpSize(),
116   mPopupTailXPosition( 0.0f ),
117   mContentSize( POPUP_MIN_SIZE ),
118   mBackgroundColor( DEFAULT_POPUP_BACKGROUND ),
119   mBackgroundPressedColor( DEFAULT_POPUP_BACKGROUND_PRESSED ),
120   mLineColor( DEFAULT_POPUP_LINE_COLOR ),
121   mIconColor( DEFAULT_OPTION_ICON ),
122   mIconPressedColor( DEFAULT_OPTION_ICON_PRESSED ),
123   mTextColor( DEFAULT_OPTION_TEXT ),
124   mTextPressedColor( DEFAULT_OPTION_TEXT_PRESSED ),
125   mSelectOptionPriority(1),
126   mSelectAllOptionPriority(2),
127   mCutOptionPriority(3),
128   mCopyOptionPriority(4),
129   mPasteOptionPriority(5),
130   mClipboardOptionPriority(6),
131   mPressedSignal(),
132   mHideFinishedSignal(),
133   mShowFinishedSignal()
134 {
135   mRoot.SetParentOrigin( ParentOrigin::TOP_LEFT );
136   mRoot.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
137 }
138
139 void TextInputPopup::AddToParent( Actor parent )
140 {
141   Actor existingParent = mRoot.GetParent();
142
143   if ( !existingParent )
144   {
145     parent.Add( mRoot );
146   }
147 }
148
149 void TextInputPopup::RemoveFromParent()
150 {
151   Actor parent = mRoot.GetParent();
152
153   if ( parent )
154   {
155     parent.Remove( mRoot );
156   }
157 }
158
159 void TextInputPopup::CreateStencil( const Vector2& size )
160 {
161   mStencil = CreateSolidColorActor( Color::BLUE );
162   mStencil.SetParentOrigin( ParentOrigin::CENTER );
163   mStencil.SetAnchorPoint( AnchorPoint::CENTER );
164   mStencil.SetDrawMode( DrawMode::STENCIL );
165   mStencil.SetVisible( true );
166   mStencil.SetName( "popup-stencil" );
167   mStencil.SetSize( size );
168 }
169
170 void TextInputPopup::OnScrollStarted( const Vector3& position )
171 {
172   mBackground.SetSensitive( false );
173 }
174
175 void TextInputPopup::OnScrollCompleted( const Vector3& position )
176 {
177   mBackground.SetSensitive( true );
178 }
179
180 void TextInputPopup::CreateScrollView()
181 {
182   mScrollView = Toolkit::ScrollView::New();
183   mScrollView.SetName("popup-scroll-view");
184   mScrollView.SetAnchorPoint( AnchorPoint::TOP_LEFT );
185   mScrollView.SetParentOrigin( ParentOrigin::TOP_LEFT );
186   mScrollView.SetPosition( POPUP_BORDER.x, POPUP_BORDER.y );
187   mScrollView.SetScrollingDirection( PanGestureDetector::DIRECTION_HORIZONTAL, Degree( 40.0f ) );
188   mScrollView.SetAxisAutoLock( true );
189   mScrollView.ScrollStartedSignal().Connect( this, &TextInputPopup::OnScrollStarted );
190   mScrollView.ScrollCompletedSignal().Connect( this, &TextInputPopup::OnScrollCompleted );
191 }
192
193 void TextInputPopup::UpdateScrollViewRulerAndSize( const Vector2& visibleSize )
194 {
195   mScrollView.SetSize( visibleSize.x, visibleSize.y );
196
197   RulerPtr rulerX = new DefaultRuler();  // IntrusivePtr which is unreferenced when ScrollView is destroyed.
198   RulerPtr rulerY = new DefaultRuler();  // IntrusivePtr which is unreferenced when ScrollView is destroyed.
199   rulerY->Disable();
200   rulerX->SetDomain( RulerDomain( 0, mContentSize.width, true ) );
201   mScrollView.SetRulerX(rulerX);
202   mScrollView.SetRulerY(rulerY);
203 }
204
205
206 void TextInputPopup::Clear()
207 {
208   if ( mBackground )
209   {
210     UnparentAndReset( mTail );
211     UnparentAndReset( mStencil );
212     UnparentAndReset( mBackground );
213     UnparentAndReset( mScrollView );
214     mButtonContainer.clear();
215     mDividerContainer.clear();
216     mRoot.RemoveConstraints();
217     RemoveFromParent();
218     mState = StateHidden;
219   }
220 }
221
222 ImageActor TextInputPopup::CreateOptionIcon( Image iconImage, const Vector4& color )
223 {
224   ImageActor icon = ImageActor::New( iconImage );
225   icon.SetSize( OPTION_ICON_SIZE );
226   icon.SetParentOrigin( ParentOrigin::TOP_CENTER );
227   icon.SetAnchorPoint( AnchorPoint::TOP_CENTER );
228   icon.SetColor( color );
229   icon.SetY( OPTION_MARGIN.z );
230   return icon;
231 }
232
233 Toolkit::TextView TextInputPopup::CreateOptionCaption( const std::string& caption, const Vector4& color )
234 {
235   TextStyle style;
236   style.SetTextColor( color );
237
238   PointSize pointSize( Font::PixelsToPoints( OPTION_TEXT_MIN_SIZE.y ) );
239   style.SetFontPointSize( pointSize );
240
241   MarkupProcessor::StyledTextArray styledCaption;
242   styledCaption.push_back( MarkupProcessor::StyledText( Text( caption ), style ) );
243
244   Toolkit::TextView textView = Toolkit::TextView::New( styledCaption );
245   textView.SetSizePolicy( Toolkit::Control::Fixed, Toolkit::Control::Fixed );
246   textView.SetWidthExceedPolicy( Toolkit::TextView::ShrinkToFit );
247   textView.SetHeightExceedPolicy( Toolkit::TextView::ShrinkToFit );
248   textView.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
249   textView.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
250   textView.SetY( -OPTION_MARGIN.w );
251
252   const float textWidth = textView.GetWidthForHeight( OPTION_TEXT_MIN_SIZE.y );
253   textView.SetSize( textWidth, OPTION_TEXT_MIN_SIZE.y );
254
255   return textView;
256 }
257
258 void TextInputPopup::CreateBackground()
259 {
260   // Create background-panel if not already created (required if we have at least one option)
261   if ( !mBackground )
262   {
263     Image bgImg = Image::New( POPUP_BACKGROUND );
264     mBackground = ImageActor::New( bgImg );
265     mBackground.SetAnchorPoint( AnchorPoint::CENTER );
266     mBackground.SetParentOrigin( ParentOrigin::CENTER );
267     mBackground.SetName( "text-input-popup-background" );
268     mBackground.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) );
269     mBackground.SetColor( mBackgroundColor );
270
271     Image bgEffectImg = Image::New( POPUP_BACKGROUND_EFFECT );
272     mBackgroundEffect = ImageActor::New( bgEffectImg );
273     mBackgroundEffect.SetAnchorPoint( AnchorPoint::CENTER );
274     mBackgroundEffect.SetParentOrigin( ParentOrigin::CENTER );
275     mBackgroundEffect.SetName( "text-input-popup-background-effect" );
276     mBackgroundEffect.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) );
277     mBackgroundEffect.SetZ( 1.0f );
278     mBackground.Add( mBackgroundEffect );
279
280     Image bgLine = Image::New( POPUP_BACKGROUND_LINE );
281     mBackgroundLine = ImageActor::New( bgLine );
282     mBackgroundLine.SetAnchorPoint( AnchorPoint::CENTER);
283     mBackgroundLine.SetParentOrigin( ParentOrigin::CENTER );
284     mBackgroundLine.SetName( "text-input-popup-background-effect" );
285     mBackgroundLine.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) );
286     mBackgroundLine.SetColor( mLineColor );
287     mBackgroundLine.SetZ( 0.1f );
288     mBackgroundEffect.Add( mBackgroundLine );
289
290     Hide(false);
291     GetRootActor().Add( mBackground );
292   }
293 }
294
295 void TextInputPopup::CreateTail()
296 {
297   if ( !mTail )
298   {
299     Image tail = Image::New( POPUP_TAIL_BOTTOM );
300     mTail = ImageActor::New( tail );
301     mTail.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
302     mTail.SetAnchorPoint( AnchorPoint::TOP_CENTER );
303     mTail.SetName( "text-input-popup-tail" );
304     mTail.SetPosition( 0.0f, POPUP_TAIL_Y_OFFSET - POPUP_BORDER.w, 1.2f );
305     mTail.SetColor( mBackgroundColor );
306
307     Image tailEffect = Image::New( POPUP_TAIL_BOTTOM_EFFECT );
308     mTailEffect = ImageActor::New( tailEffect );
309     mTailEffect.SetParentOrigin( ParentOrigin::CENTER );
310     mTailEffect.SetAnchorPoint( AnchorPoint::CENTER );
311     mTailEffect.SetName( "text-input-popup-tail-effect" );
312     mTailEffect.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) );
313     mTailEffect.SetZ( 0.1f );
314     mTail.Add( mTailEffect );
315
316     Image tailLine = Image::New( POPUP_TAIL_BOTTOM_LINE );
317     mTailLine = ImageActor::New( tailLine );
318     mTailLine.SetParentOrigin( ParentOrigin::CENTER );
319     mTailLine.SetAnchorPoint( AnchorPoint::CENTER );
320     mTailLine.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) );
321     mTailLine.SetName( "text-input-popup-tail-line" );
322     mTailLine.SetColor( mLineColor );
323     mTailLine.SetZ( 0.1f );
324     mTailEffect.Add( mTailLine );
325   }
326 }
327
328 ImageActor TextInputPopup::CreateDivider()
329 {
330   ImageActor divider = Toolkit::CreateSolidColorActor( mLineColor );
331   divider.SetParentOrigin( ParentOrigin::TOP_LEFT );
332   divider.SetAnchorPoint( AnchorPoint::TOP_LEFT );
333   divider.SetSize( POPUP_DIVIDER_SIZE );
334   divider.SetPosition( mContentSize.width - POPUP_DIVIDER_SIZE.width, 0.0f );
335
336   // Keep track of all the dividers. As their height's need to be updated to the max of all
337   // buttons currently added.
338   mDividerContainer.push_back( divider );
339
340   return divider;
341 }
342
343 ImageActor TextInputPopup::CreatePressedBackground( const Vector2& requiredSize )
344 {
345   ImageActor pressedBg = Toolkit::CreateSolidColorActor( mBackgroundPressedColor );
346   pressedBg.SetDrawMode( DrawMode::OVERLAY );
347   pressedBg.SetParentOrigin( ParentOrigin::CENTER );
348   pressedBg.SetAnchorPoint( AnchorPoint::CENTER );
349   pressedBg.SetSize( requiredSize );
350   return pressedBg;
351 }
352
353 TextInputPopup::ButtonRequirement TextInputPopup::CreateRequiredButton( TextInputPopup::Buttons buttonId, std::size_t orderOfPriority,
354                                                                         const std::string& name, const std::string& caption, Image iconImage, bool enabled )
355 {
356   TextInputPopup::ButtonRequirement currentButton;
357   currentButton.buttonId = buttonId;
358   currentButton.orderOfPriority = orderOfPriority;
359   currentButton.name = name;
360   currentButton.caption = caption;
361   currentButton.iconImage = iconImage;
362   currentButton.enabled = enabled;
363
364   return currentButton;
365 }
366
367 void TextInputPopup::CreateOrderedListOfOptions()
368 {
369   mOrderListOfButtons.clear();
370
371   for ( std::size_t index= 0; index < ButtonsEnumEnd; index++ )
372   {
373     TextInputPopup::ButtonRequirement currentButton;
374
375     // Create button for each possible option using Option priority
376     switch ( index )
377     {
378       case ButtonsCut:
379       {
380         Image cutIcon = Image::New( OPTION_ICON_CUT );
381         currentButton = CreateRequiredButton( ButtonsCut, mCutOptionPriority, OPTION_CUT, GET_LOCALE_TEXT("IDS_COM_BODY_CUT"), cutIcon, false );
382         break;
383       }
384       case ButtonsCopy:
385       {
386         Image copyIcon = Image::New( OPTION_ICON_COPY );
387         currentButton = CreateRequiredButton( ButtonsCopy, mCopyOptionPriority, OPTION_COPY, GET_LOCALE_TEXT("IDS_COM_BODY_COPY"), copyIcon, false );
388         break;
389       }
390       case ButtonsPaste:
391       {
392         Image pasteIcon = Image::New( OPTION_ICON_PASTE );
393         currentButton = CreateRequiredButton( ButtonsPaste, mPasteOptionPriority, OPTION_PASTE, GET_LOCALE_TEXT("IDS_COM_BODY_PASTE"), pasteIcon, false );
394         break;
395       }
396       case ButtonsSelect:
397       {
398         Image selectIcon = Image::New( OPTION_ICON_SELECT );
399         currentButton = CreateRequiredButton( ButtonsSelect, mSelectOptionPriority, OPTION_SELECT_WORD, GET_LOCALE_TEXT("IDS_COM_SK_SELECT"), selectIcon, false );
400         break;
401       }
402       case ButtonsSelectAll:
403       {
404         Image selectAllIcon = Image::New( OPTION_ICON_SELECT_ALL );
405         currentButton = CreateRequiredButton( ButtonsSelectAll, mSelectAllOptionPriority, OPTION_SELECT_ALL, GET_LOCALE_TEXT("IDS_COM_BODY_SELECT_ALL"), selectAllIcon, false );
406         break;
407       }
408       case ButtonsClipboard:
409       {
410         Image clipboardIcon = Image::New( OPTION_ICON_CLIPBOARD );
411         currentButton = CreateRequiredButton( ButtonsClipboard, mClipboardOptionPriority, OPTION_CLIPBOARD, GET_LOCALE_TEXT("IDS_COM_BODY_CLIPBOARD"), clipboardIcon, false );
412         break;
413       }
414       case ButtonsEnumEnd:
415       {
416         DALI_ASSERT_DEBUG( "ButtonsEnumEnd used but an invalid choice");
417         currentButton.orderOfPriority = 0;
418         break;
419       }
420     }
421
422     bool match = false;
423
424     // Insert button in list of buttons in order of priority setting.
425     for( std::vector<ButtonRequirement>::iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt && !match ); ++it )
426     {
427       const ButtonRequirement& button( *it );
428       if ( currentButton.orderOfPriority < button.orderOfPriority )
429       {
430         if ( currentButton.orderOfPriority != 0 ) // If order priority 0 then do not add button as not required.
431         {
432           mOrderListOfButtons.insert( it, currentButton );
433         }
434         match = true;
435       }
436     }
437
438     if ( !match)
439     {
440       mOrderListOfButtons.push_back( currentButton );
441     }
442   }
443 }
444
445 void TextInputPopup::AddOption(const std::string& name, const std::string& caption, const Image iconImage, bool finalOption)
446 {
447   // 1. Create container for text and icon when not pressed.
448   Actor optionContainer = Actor::New();
449   optionContainer.SetParentOrigin( ParentOrigin::TOP_LEFT );
450   optionContainer.SetAnchorPoint( AnchorPoint::TOP_LEFT );
451
452   // 2. Add text.
453   Toolkit::TextView captionTextView = CreateOptionCaption( caption, mTextColor );
454   optionContainer.Add( captionTextView );
455
456   // 3. Add icon.
457   ImageActor icon = CreateOptionIcon( iconImage, mIconColor );
458   optionContainer.Add( icon );
459
460   // 4. Calculate the size of option.
461   const Vector2 textSize = Vector2( captionTextView.GetNaturalSize() );
462   const Vector2 optionSize( std::max( textSize.x, OPTION_ICON_SIZE.x ),
463                             OPTION_MARGIN.z + OPTION_ICON_SIZE.y + OPTION_GAP_ICON_TEXT + textSize.y + OPTION_MARGIN.w );
464   const Vector2 constrainedOptionSize = Min( Max( optionSize, OPTION_MIN_SIZE ), OPTION_MAX_SIZE );
465
466   // 5. Create a option.
467   Toolkit::PushButton option = Toolkit::PushButton::New();
468   option.SetSizePolicy( Toolkit::Control::Fixed, Toolkit::Control::Fixed );
469   option.SetParentOrigin( ParentOrigin::TOP_LEFT );
470   option.SetAnchorPoint( AnchorPoint::TOP_LEFT );
471   option.SetSize( constrainedOptionSize );
472   option.SetX( mContentSize.x );
473   option.SetName( name );
474   option.SetAnimationTime( 0.0f );
475   option.ClickedSignal().Connect( this, &TextInputPopup::OnButtonPressed );
476   mScrollView.Add( option );
477
478   // 6. Set the normal option image.
479   option.SetButtonImage( optionContainer );
480
481   // 7. Update the content size.
482   mContentSize.x += constrainedOptionSize.x;
483
484   // 8. Create the pressed container.
485   Actor optionPressedContainer = Actor::New();
486
487   // 9. Add option pressed background.
488   Vector2 optionPressedBackgroundSize( constrainedOptionSize.x - 1.0f, constrainedOptionSize.y - 2.0f );
489   ImageActor optionPressedBackground = CreatePressedBackground( optionPressedBackgroundSize );
490   optionPressedContainer.Add( optionPressedBackground );
491
492   // 10. Add pressed text
493   Toolkit::TextView pressedCaptionTextView = CreateOptionCaption( caption, mTextPressedColor );
494   optionPressedBackground.Add( pressedCaptionTextView );
495
496   // 11. Add pressed icon
497   ImageActor pressedIcon = CreateOptionIcon( iconImage, mIconPressedColor );
498   optionPressedBackground.Add( pressedIcon );
499
500   // 12. Set the pressed option image
501   option.SetPressedImage( optionPressedContainer );
502
503   // 13. Add the divider
504   if ( !finalOption )
505   {
506     ImageActor divider = CreateDivider();
507     mScrollView.Add( divider );
508   }
509 }
510
511 void TextInputPopup::Hide(bool animate)
512 {
513   if( mRoot )
514   {
515     if(mAnimation)
516     {
517       mAnimation.Clear();
518       mAnimation.Reset();
519     }
520
521     if(animate)
522     {
523       mAnimation = Animation::New( HIDE_POPUP_ANIMATION_DURATION );
524       mAnimation.AnimateTo( Property(mRoot, Actor::SCALE), Vector3::ZERO, AlphaFunctions::EaseOut );
525       mAnimation.AnimateTo( Property(mRoot, Actor::COLOR_ALPHA), 0.0f, AlphaFunctions::EaseOut );
526       mAnimation.Play();
527
528       mAnimation.FinishedSignal().Connect( this, &TextInputPopup::OnHideFinished );
529       mState = StateHiding;
530     }
531     else
532     {
533       mRoot.SetProperty(Actor::SCALE, Vector3::ZERO);
534       mRoot.SetProperty(Actor::COLOR_ALPHA, 0.0f);
535       mState = StateHidden;
536     }
537   }
538 }
539
540 void TextInputPopup::Show( Actor target, bool animate )
541 {
542   if( mRoot )
543   {
544     mRoot.SetSensitive( true );
545
546     if(mAnimation)
547     {
548       mAnimation.Clear();
549       mAnimation.Reset();
550     }
551
552     if ( target )
553     {
554       AddToParent( target );
555     }
556
557     if(animate)
558     {
559       mAnimation = Animation::New( SHOW_POPUP_ANIMATION_DURATION );
560       mAnimation.AnimateTo( Property(mRoot, Actor::SCALE), Vector3::ONE, AlphaFunctions::EaseOut );
561       mAnimation.AnimateTo( Property(mRoot, Actor::COLOR_ALPHA), 1.0f, AlphaFunctions::EaseOut );
562       mAnimation.Play();
563
564       mAnimation.FinishedSignal().Connect( this, &TextInputPopup::OnShowFinished );
565       mState = StateShowing;
566     }
567     else
568     {
569       mRoot.SetProperty(Actor::SCALE, Vector3::ONE);
570       mRoot.SetProperty(Actor::COLOR_ALPHA, 1.0f);
571       mState = StateShown;
572     }
573   }
574 }
575
576 TextInputPopup::State TextInputPopup::GetState(void) const
577 {
578   return mState;
579 }
580
581 Actor TextInputPopup::GetRootActor() const
582 {
583   return mRoot;
584 }
585
586 // Styling
587
588 void TextInputPopup::SetCutPastePopupColor( const Vector4& color )
589 {
590   mBackgroundColor = color;
591 }
592
593 const Vector4& TextInputPopup::GetCutPastePopupColor() const
594 {
595   return mBackgroundColor;
596 }
597
598 void TextInputPopup::SetCutPastePopupPressedColor( const Vector4& color )
599 {
600   mBackgroundPressedColor = color;
601 }
602
603 const Vector4& TextInputPopup::GetCutPastePopupPressedColor() const
604 {
605   return mBackgroundPressedColor;
606 }
607
608 void TextInputPopup::SetCutPastePopupBorderColor( const Vector4& color )
609 {
610   mLineColor = color;
611 }
612
613 const Vector4& TextInputPopup::GetCutPastePopupBorderColor() const
614 {
615   return mLineColor;
616 }
617
618 void TextInputPopup::SetCutPastePopupIconColor( const Vector4& color )
619 {
620   mIconColor = color;
621 }
622
623 const Vector4& TextInputPopup::GetCutPastePopupIconColor() const
624 {
625   return mIconColor;
626 }
627
628 void TextInputPopup::SetCutPastePopupIconPressedColor( const Vector4& color )
629 {
630   mIconPressedColor = color;
631 }
632
633 const Vector4& TextInputPopup::GetCutPastePopupIconPressedColor()
634 {
635   return mIconPressedColor;
636 }
637
638 void TextInputPopup::SetCutPastePopupTextColor( const Vector4& color )
639 {
640   mTextColor = color;
641 }
642
643 const Vector4& TextInputPopup::GetCutPastePopupTextColor()
644 {
645   return mTextColor;
646 }
647
648 void TextInputPopup::SetCutPastePopupTextPressedColor( const Vector4& color )
649 {
650   mTextPressedColor = color;
651 }
652
653 const Vector4& TextInputPopup::GetCutPastePopupTextPressedColor()
654 {
655   return mTextPressedColor;
656 }
657
658 void TextInputPopup::TogglePopupButtonOnOff( TextInputPopup::Buttons requiredButton, bool enable )
659 {
660   bool match ( false );
661   for( std::vector<ButtonRequirement>::iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt && !match ); ++it )
662    {
663      ButtonRequirement& button( *it );
664      if ( requiredButton == button.buttonId )
665      {
666        button.enabled = enable;
667        match = true;
668      }
669    }
670 }
671
672 void TextInputPopup::SetButtonPriorityPosition( TextInputPopup::Buttons button, unsigned int priority )
673 {
674   switch ( button )
675   {
676     case ButtonsCut:
677     {
678       mCutOptionPriority = priority;
679       break;
680     }
681     case ButtonsCopy:
682     {
683       mCopyOptionPriority = priority;
684       break;
685     }
686     case ButtonsPaste:
687     {
688       mPasteOptionPriority = priority;
689       break;
690     }
691     case ButtonsSelect:
692     {
693       mSelectOptionPriority = priority;
694       break;
695     }
696     case ButtonsSelectAll:
697     {
698       mSelectAllOptionPriority = priority;
699       break;
700     }
701     case ButtonsClipboard:
702     {
703       mClipboardOptionPriority = priority;
704       break;
705     }
706     case ButtonsEnumEnd:
707     {
708       DALI_ASSERT_DEBUG( "ButtonsEnumEnd used but an invalid choice");
709       break;
710     }
711   }
712   CreateOrderedListOfOptions(); // Update list of options as priority changed.
713 }
714
715 unsigned int TextInputPopup::GetButtonPriorityPosition( TextInputPopup::Buttons button ) const
716 {
717   unsigned int priority = 0;
718
719   switch ( button )
720   {
721     case ButtonsCut:
722     {
723       priority = mCutOptionPriority;
724       break;
725     }
726     case ButtonsCopy:
727     {
728       priority = mCopyOptionPriority;
729       break;
730     }
731     case ButtonsPaste:
732     {
733       priority = mPasteOptionPriority;
734       break;
735     }
736     case ButtonsSelect:
737     {
738       priority = mSelectOptionPriority;
739       break;
740     }
741     case ButtonsSelectAll:
742     {
743       priority = mSelectAllOptionPriority;
744       break;
745     }
746     case ButtonsClipboard:
747     {
748       priority = mClipboardOptionPriority;
749       break;
750     }
751     case ButtonsEnumEnd:
752     {
753       DALI_ASSERT_DEBUG( "ButtonsEnumEnd used but an invalid choice");
754       break;
755     }
756   }
757
758   return priority;
759 }
760
761 void TextInputPopup::AddPopupOptions()
762 {
763   mContentSize = POPUP_MIN_SIZE;
764
765   // 1. Create the background.
766   CreateBackground();
767   mRoot.Add(mBackground);
768
769   // 2. Create the tail.
770   CreateTail();
771   mBackground.Add( mTail );
772
773   // 3. Create the scroll view.
774   CreateScrollView();
775   mBackground.Add( mScrollView );
776
777   // 4. Create the options and add into the scroll view.
778   for( std::vector<ButtonRequirement>::const_iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt ); ++it )
779   {
780     const ButtonRequirement& button( *it );
781     if ( button.enabled )
782     {
783       AddOption( button.name, button.caption, button.iconImage, it != ( endIt - 1 ) ? false : true );
784     }
785   }
786
787   // 5. Calculate size of content and of popup including borders
788   const Vector2 visibleContentSize  = Vector2( std::min( mContentSize.x, POPUP_MAX_SIZE.x - POPUP_BORDER.x - POPUP_BORDER.y ), mContentSize.y );
789   const Vector2 popupSize = Vector2( POPUP_BORDER.x + visibleContentSize.x + POPUP_BORDER.y,
790                                      POPUP_BORDER.z + visibleContentSize.y + POPUP_BORDER.w );
791   mVisiblePopUpSize = Vector3( popupSize.x,  popupSize.y, 1.0f);
792
793   // 6. Set the scroll view ruler.
794   UpdateScrollViewRulerAndSize( visibleContentSize );
795
796   // 7. Create stencil
797   const Vector2 stencilSize = Vector2( popupSize.x, popupSize.y + POPUP_TAIL_SIZE.x + POPUP_TAIL_Y_OFFSET );
798   CreateStencil( stencilSize );
799   mRoot.Add( mStencil );
800
801   // 8. Set the root size.
802   mRoot.SetSize( popupSize );   // Make Root Actor reflect the size of its content
803 }
804
805 void TextInputPopup::SetPopupBoundary( const Rect<float>& boundingRectangle )
806 {
807   mBoundingRect =  boundingRectangle;
808 }
809
810 const Vector3& TextInputPopup::GetVisibileSize() const
811 {
812   return mVisiblePopUpSize;
813 }
814
815
816 void TextInputPopup::SetTailPosition( const Vector3& position, bool yAxisFlip )
817 {
818   mPopupTailXPosition = position.x;
819   mTail.SetX( position.x );
820
821   if ( yAxisFlip )
822   {
823     Image tail = Image::New( POPUP_TAIL_TOP );
824     mTail.SetImage( tail );
825     mTail.SetParentOrigin( ParentOrigin::TOP_CENTER );
826     mTail.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
827     mTail.SetY( POPUP_BORDER.y - POPUP_TAIL_Y_OFFSET );
828     Image tailEffect = Image::New( POPUP_TAIL_TOP_EFFECT );
829     mTailEffect.SetImage( tailEffect );
830
831     Image tailLine = Image::New( POPUP_TAIL_TOP_LINE );
832     mTailLine.SetImage( tailLine );
833   }
834 }
835
836 bool TextInputPopup::OnButtonPressed( Toolkit::Button button )
837 {
838   mPressedSignal.Emit( button );
839   return false;
840 }
841
842 void TextInputPopup::OnHideFinished(Animation& source)
843 {
844   source.FinishedSignal().Disconnect( this, &TextInputPopup::OnHideFinished );
845   Clear();
846   mState = StateHidden;
847   mHideFinishedSignal.Emit( *this );
848 }
849
850 void TextInputPopup::OnShowFinished(Animation& source)
851 {
852   source.FinishedSignal().Disconnect( this, &TextInputPopup::OnShowFinished );
853   mState = StateShown;
854   mShowFinishedSignal.Emit( *this );
855 }
856
857 TextInputPopup::PressedSignalV2& TextInputPopup::PressedSignal()
858 {
859   return mPressedSignal;
860 }
861
862 TextInputPopup::HideFinishedSignalV2& TextInputPopup::HideFinishedSignal()
863 {
864   return mHideFinishedSignal;
865 }
866
867 TextInputPopup::ShowFinishedSignalV2& TextInputPopup::ShowFinishedSignal()
868 {
869   return mShowFinishedSignal;
870 }
871
872 } // namespace Internal
873
874 } // namespace Toolkit
875
876 } // namespace Dali
877