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