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