2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <dali-toolkit/internal/controls/text-input/text-input-popup-impl.h>
20 #include <dali-toolkit/public-api/controls/buttons/push-button.h>
21 #include <dali-toolkit/public-api/controls/default-controls/solid-color-actor.h>
28 #define GET_LOCALE_TEXT(string) dgettext("sys_string", string)
34 const Vector4 DEFAULT_POPUP_BACKGROUND( Vector4( .20f, 0.29f, 0.44f, 1.0f ) );
35 const Vector4 DEFAULT_POPUP_BUTTON_PRESSED( Vector4( 0.07f, 0.10f, 0.17f, 1.0f ) );
36 const Vector4 DEFAULT_BORDER_COLOR( Vector4( 0.36f, 0.45f, 0.59f, 1.0f ) );
37 const Vector3 POPUP_BORDER( Vector3(1.0f, 1.0f, 0.0f) );
39 /* Functionality in place to have the end buttons using different images to inner button.
40 * Supply a centre image and then a left and right image, the centre image can have straight ends while
41 * the left image can be rounded on the left and straight on the right, the right image can be straight on the left and rounded on the right.
45 const char* DEFAULT_POPUP_TAIL_BOTTOM( DALI_IMAGE_DIR "popup_bubble_tail_bottom.png" );
46 const char* DEFAULT_POPUP_TAIL_BOTTOM_OUTLINE( DALI_IMAGE_DIR "popup_bubble_tail_bottom_line.png" );
48 // Popup: Vertical Constraint
49 // TODO: Remove - this should come from application - it is not possible to get the
50 // height of the indicator actor from Dali-Toolkit.
52 const float POP_UP_SCREEN_EDGE_MARGIN( 4.0f );
53 const Vector2 DEFAULT_POPUP_INDICATOR_OFFSET(POP_UP_SCREEN_EDGE_MARGIN, 60.0f);
55 const Vector3 POPUP_TEXT_OFFSET( 0.0f, 0.0f, 0.0f );
56 const Vector3 POPUP_TEXT_ENLARGE( 12.0f, 28.0f, 0.0f );
57 const Vector3 POPUP_MINIMUM_SIZE( 128.0f, 124.0f, 0.0f );
59 const Vector3 BUTTON_TEXT_ENLARGE( 32.0f, 0.0f, 0.0f );
60 const Vector3 BUTTON_TEXT_MINIMUM_SIZE( 128.0f, 126.0f, 0.0f );
61 const Vector3 BUTTON_TEXT_MAXIMUM_SIZE( 190.0f, 126.0f, 0.0f );
62 const Vector3 TEXT_LABEL_MAX_SIZE( 160.0f, 30.0f, 0.0f );
64 const float DIVIDER_WIDTH(2.0f); ///< Width of each button divider
65 const float DIVIDER_MARGIN(0.0f); ///< Top/Bottom Margin between divider and edge of popup.
67 const float DEFAULT_UI_FONT_SIZE(7.0f); ///< Standard font size for Text-Input's UI
69 const float HIDE_POPUP_ANIMATION_DURATION(0.2f); ///< Duration of popup hide animation in seconds.
70 const float SHOW_POPUP_ANIMATION_DURATION(0.2f); ///< Duration of popup show animation in seconds.
72 const Vector2 DEFAULT_ICON_SIZE( 45.0f, 45.0f ); ///< Default icon size for image in options
73 const float TEXT_POSITION_OFFSET( -19.0f ); ///< Default offset for text label
74 const float ICON_POSITION_OFFSET( 19.0f ); ///< Default offset for icon
76 const char* DEFAULT_ICON_CLIPBOARD( DALI_IMAGE_DIR "copy_paste_icon_clipboard.png" );
77 const char* DEFAULT_ICON_COPY( DALI_IMAGE_DIR "copy_paste_icon_copy.png" );
78 const char* DEFAULT_ICON_CUT( DALI_IMAGE_DIR "copy_paste_icon_cut.png" );
79 const char* DEFAULT_ICON_PASTE( DALI_IMAGE_DIR "copy_paste_icon_paste.png" );
80 const char* DEFAULT_ICON_SELECT( DALI_IMAGE_DIR "copy_paste_icon_select.png" );
81 const char* DEFAULT_ICON_SELECT_ALL( DALI_IMAGE_DIR "copy_paste_icon_select_all.png" );
83 // TODO: This should be based on the content for example:
84 // 1. For selection: should be above top of highlighted selection, or below bottom of highlighted selection + end handle.
85 // 2. For cursor: should be above top of cursor, or below bottom of cursor + grab handle.
86 const std::string POPUP_ALTERNATIVE_OFFSET("popup-alternative-offset"); ///< Alternative offset property for confinenment constraint.
90 * Confine Actor to boundaries of reference actor (e.g. Parent)
91 * Actor bounds (top-left position + size) are confined to reference Actor's
94 struct ConfinementConstraint
97 * Confinement constraint constructor.
98 * @param[in] topLeftMargin (optional) Top-Left margins (defaults to 0.0f, 0.0f)
99 * @param[in] bottomRightMargin (optional) Bottom-Right margins (defaults to 0.0f, 0.0f)
100 * @paran[in[ flipHorizontal (optional) whether to flip Actor to other side if near edge
101 * @param[in] flipVertical (optional) whether to flip Actor to the other side if near edge
102 * @param[in] boundingRect Rectangle to bound Popup to.
105 ConfinementConstraint(Vector2 topLeftMargin = Vector2::ZERO, Vector2 bottomRightMargin = Vector2::ZERO, bool flipHorizontal = false, bool flipVertical = false, Rect<float> boundingRect = Rect<float>(0.0f, 0.0f, 0.0f, 0.0f) )
106 : mMinIndent(topLeftMargin),
107 mMaxIndent(bottomRightMargin),
108 mFlipHorizontal(flipHorizontal),
109 mFlipVertical(flipVertical),
110 mBoundingRect( boundingRect )
114 Vector3 operator()(const Vector3& constPosition,
115 const PropertyInput& sizeProperty,
116 const PropertyInput& parentOriginProperty,
117 const PropertyInput& anchorPointProperty,
118 const PropertyInput& referenceSizeProperty,
119 const PropertyInput& alternativeOffsetProperty)
121 const Vector3& size = sizeProperty.GetVector3();
122 const Vector3& origin = parentOriginProperty.GetVector3();
123 const Vector3& anchor = anchorPointProperty.GetVector3();
124 const Vector3& referenceSize = referenceSizeProperty.GetVector3();
125 const Vector2& alternativeOffset = alternativeOffsetProperty.GetVector2();
127 Vector3 newPosition(constPosition);
129 // Get actual position of Actor relative to parent's Top-Left.
130 Vector3 position(constPosition + origin * referenceSize);
132 // if top-left corner is outside of Top-Left bounds, then push back in screen.
134 Vector3 corner(position - size * anchor - mMinIndent);
136 newPosition.x -= std::max(corner.x, 0.0f);
138 if ( mFlipHorizontal )
140 if( corner.x < mBoundingRect.x + POP_UP_SCREEN_EDGE_MARGIN )
142 // Snap PopUp to left hand boundary so stays visible
143 corner.x = mBoundingRect.x + POP_UP_SCREEN_EDGE_MARGIN ;
145 else if ( ( corner.x + size.x ) > ( ( mBoundingRect.x + mBoundingRect.width ) - POP_UP_SCREEN_EDGE_MARGIN ))
147 // Calculate offset from left boundary PopUp must be placed at so it does not exceed right side boundary.
148 float requiredOffSetFromLeftBoundaryToFit = mBoundingRect.width - POP_UP_SCREEN_EDGE_MARGIN - size.x;
149 corner.x = mBoundingRect.x + requiredOffSetFromLeftBoundaryToFit - ( origin.x * referenceSize.x ) + ( size.x * anchor.x );
151 newPosition.x = corner.x;
154 if(mFlipVertical && corner.y < 0.0f)
157 newPosition.y += size.height + alternativeOffset.height;
160 newPosition.y -= std::min(corner.y, 0.0f);
162 // if bottom-right corner is outside of Bottom-Right bounds, then push back in screen.
163 corner += size - referenceSize + mMinIndent + mMaxIndent;
165 if(mFlipVertical && corner.y > 0.0f)
168 newPosition.y -= size.height + alternativeOffset.height;
174 Vector3 mMinIndent; ///< Top-Left Margin
175 Vector3 mMaxIndent; ///< Bottom-Right Margin.
176 bool mFlipHorizontal; ///< Whether to flip actor's position if exceeds horizontal screen bounds
177 bool mFlipVertical; ///< Whether to flip actor's position if exceeds vertical screen bounds
178 Rect<float> mBoundingRect; ///< Bounding Rect Popup must stay within
182 * Confine actor to the x axis boundaries of reference actor (e.g. Parent)
184 struct ParentXAxisConstraint
187 * Confinement constraint constructor.
189 ParentXAxisConstraint( float handlesMidPoint = 0.0f )
190 : mHandlesMidPoint( handlesMidPoint )
194 float operator()( const float constXPosition,
195 const PropertyInput& localWidthProperty,
196 const PropertyInput& anchorPointXProperty )
198 const float size = localWidthProperty.GetFloat();
199 const float anchor = anchorPointXProperty.GetFloat();
201 float newPosition = Clamp( mHandlesMidPoint, constXPosition - size * anchor , constXPosition + size * anchor);
206 float mHandlesMidPoint;
210 } // unnamed namespace
221 const char* const TextInputPopup::SIGNAL_PRESSED = "pressed";
222 const char* const TextInputPopup::SIGNAL_HIDE_FINISHED = "hide-finished";
223 const char* const TextInputPopup::SIGNAL_SHOW_FINISHED = "show-finished";
225 const char* const TextInputPopup::OPTION_SELECT_WORD = "option-select_word"; // "Select Word" popup option.
226 const char* const TextInputPopup::OPTION_SELECT_ALL("option-select_all"); // "Select All" popup option.
227 const char* const TextInputPopup::OPTION_CUT("option-cut"); // "Cut" popup option.
228 const char* const TextInputPopup::OPTION_COPY("option-copy"); // "Copy" popup option.
229 const char* const TextInputPopup::OPTION_PASTE("option-paste"); // "Paste" popup option.
230 const char* const TextInputPopup::OPTION_CLIPBOARD("option-clipboard"); // "Clipboard" popup option.
232 TextInputPopup::TextInputPopup()
233 : mState(StateHidden),
234 mRootActor(Layer::New()),
235 mPopupTailXPosition( 0.0f ),
236 mContentSize( Vector3::ZERO ),
237 mCutPasteButtonsColor( DEFAULT_POPUP_BACKGROUND ),
238 mCutPasteButtonsPressedColor( DEFAULT_POPUP_BUTTON_PRESSED ),
239 mBorderColor( DEFAULT_BORDER_COLOR ),
240 mSelectOptionPriority(1),
241 mSelectAllOptionPriority(2),
242 mCutOptionPriority(3),
243 mCopyOptionPriority(4),
244 mPasteOptionPriority(5),
245 mClipboardOptionPriority(6),
247 mHideFinishedSignal(),
248 mShowFinishedSignal()
250 mAlternativeOffsetProperty = mRootActor.RegisterProperty( POPUP_ALTERNATIVE_OFFSET, Vector2::ZERO );
251 mRootActor.SetParentOrigin( ParentOrigin::CENTER );
252 mRootActor.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
253 // constrain popup to size of parent.
256 Actor TextInputPopup::Self()
261 void TextInputPopup::AddToStage()
263 // TODO: Confinement constraint borders should be defined by the application.
264 // It should also not use the stage directly, instead it should add to parent container.
265 Stage::GetCurrent().Add(mRootActor);
267 ApplyConfinementConstraint();
270 void TextInputPopup::ApplyConfinementConstraint()
272 mRootActor.RemoveConstraints();
273 Constraint constraint = Constraint::New<Vector3>( Actor::POSITION,
274 LocalSource( Actor::SIZE ),
275 LocalSource( Actor::PARENT_ORIGIN ),
276 LocalSource( Actor::ANCHOR_POINT ),
277 ParentSource( Actor::SIZE ),
278 LocalSource( mAlternativeOffsetProperty ),
279 ConfinementConstraint( DEFAULT_POPUP_INDICATOR_OFFSET,
282 true, mBoundingRect ) );
283 mRootActor.ApplyConstraint(constraint);
286 void TextInputPopup::ApplyTailConstraint()
288 mTail.RemoveConstraints();
289 Constraint constraint = Constraint::New<float>( Actor::POSITION_X,
290 LocalSource( Actor::SIZE_WIDTH ),
291 LocalSource( Actor::ANCHOR_POINT_X ),
292 ParentXAxisConstraint());
295 void TextInputPopup::CreateLayer( const Vector2& size )
297 mLayer = Layer::New();
298 mLayer.SetParentOrigin(ParentOrigin::CENTER);
299 mLayer.SetAnchorPoint(AnchorPoint::CENTER);
300 mLayer.SetSize( size ); // matches stencil size
301 mLayer.SetName("popup-mLayer");
304 void TextInputPopup::CreateStencil( const Vector2& size )
306 mStencil = CreateSolidColorActor( Color::BLUE );
307 mStencil.SetParentOrigin( Vector3( ParentOrigin::CENTER ) );
308 mStencil.SetAnchorPoint( AnchorPoint::CENTER );
309 mStencil.SetDrawMode( DrawMode::STENCIL );
310 mStencil.SetSize( size ); // slightly smaller than layer and stencil so over shoot always inside.
311 mStencil.SetVisible( true );
312 mStencil.SetName("popup-stencil");
315 void TextInputPopup::OnScrollStarted( const Vector3& position )
317 mBackground.SetSensitive( false );
320 void TextInputPopup::OnScrollCompleted( const Vector3& position )
322 mBackground.SetSensitive( true );
325 void TextInputPopup::CreateScrollView( const Vector2& domainSize, const Vector2& visibleSize )
327 mScrollView = Toolkit::ScrollView::New();
328 mScrollView.SetName("popup-scroll-view");
329 mScrollView.SetAnchorPoint( AnchorPoint::TOP_LEFT );
330 mScrollView.SetParentOrigin( ParentOrigin::TOP_LEFT );
331 mScrollView.SetSize( visibleSize.x, visibleSize.y );
332 mScrollView.SetScrollingDirection( PanGestureDetector::DIRECTION_HORIZONTAL, Degree( 40.0f ) );
333 mScrollView.SetAxisAutoLock( true );
334 mScrollView.ScrollStartedSignal().Connect( this, &TextInputPopup::OnScrollStarted );
335 mScrollView.ScrollCompletedSignal().Connect( this, &TextInputPopup::OnScrollCompleted );
337 RulerPtr rulerX = new DefaultRuler(); // IntrusivePtr which is unreferenced when ScrollView is destroyed.
338 RulerPtr rulerY = new DefaultRuler(); // IntrusivePtr which is unreferenced when ScrollView is destroyed.
340 rulerX->SetDomain( RulerDomain( 0, domainSize.width, true ) );
341 mScrollView.SetRulerX(rulerX);
342 mScrollView.SetRulerY(rulerY);
345 void TextInputPopup::RemoveFromStage()
347 Actor rootActor = Self();
348 Stage::GetCurrent().Remove( rootActor );
351 void TextInputPopup::Clear()
355 UnparentAndReset( mTail );
356 UnparentAndReset( mStencil );
357 UnparentAndReset( mBackground );
358 UnparentAndReset( mScrollView );
359 UnparentAndReset( mLayer );
360 mButtonContainer.clear();
361 mDividerContainer.clear();
364 mRootActor.RemoveConstraints();
366 mState = StateHidden;
370 Toolkit::TextView TextInputPopup::CreateOptionText( const MarkupProcessor::StyledTextArray& styledCaption )
372 Toolkit::TextView label = Toolkit::TextView::New( styledCaption );
373 label.SetSizePolicy( Toolkit::Control::Fixed, Toolkit::Control::Fixed );
374 label.SetWidthExceedPolicy( Toolkit::TextView::Fade );
375 label.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
376 label.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
377 label.SetPosition( 0.0f, TEXT_POSITION_OFFSET );
382 ImageActor TextInputPopup::CreateOptionIcon( Image iconImage )
384 ImageActor icon = ImageActor::New( iconImage );
386 icon.SetSize( DEFAULT_ICON_SIZE );
387 icon.SetParentOrigin( ParentOrigin::TOP_CENTER );
388 icon.SetAnchorPoint( AnchorPoint::TOP_CENTER );
389 icon.SetPosition( 0.0f, ICON_POSITION_OFFSET );
394 void TextInputPopup::CreatePopUpBackground()
396 // Create background-panel if not already created (required if we have at least one option)
399 mBackground = Toolkit::CreateSolidColorActor( GetCutPastePopUpColor(), true, mBorderColor );
400 mBackground.SetAnchorPoint( AnchorPoint::TOP_LEFT );
401 mBackground.SetParentOrigin( ParentOrigin::TOP_LEFT );
402 mBackground.SetName("pop-up-background");
403 mContentSize = POPUP_TEXT_OFFSET;
408 Image tailImage = Image::New( DEFAULT_POPUP_TAIL_BOTTOM );
409 Image tailImageOutline = Image::New( DEFAULT_POPUP_TAIL_BOTTOM_OUTLINE );
411 mTailOutline = ImageActor::New ( tailImageOutline );
412 mTailOutline.SetParentOrigin( ParentOrigin::CENTER );
413 mTailOutline.SetAnchorPoint( AnchorPoint::CENTER );
414 mTailOutline.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) );
416 mTail = ImageActor::New( tailImage );
417 mTail.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
418 mTail.SetAnchorPoint( AnchorPoint::TOP_CENTER );
419 // TODO: Make tail visible, and positioned in relation to original intended position of popup (i.e. before constrained effects)
420 mTail.SetVisible(true);
421 mTail.SetColor( mCutPasteButtonsColor );
422 mTailOutline.SetColor( mBorderColor );
423 mTail.Add( mTailOutline);
427 void TextInputPopup::CreateDivider()
429 if(mButtonContainer.size() > 0)
431 ImageActor divider = Toolkit::CreateSolidColorActor( mBorderColor );
432 divider.SetParentOrigin( ParentOrigin::TOP_LEFT );
433 divider.SetAnchorPoint( AnchorPoint::TOP_LEFT );
434 divider.SetPosition( Vector3( mContentSize.width, POPUP_TEXT_OFFSET.y, 0.0f ) );
435 // Keep track of all the dividers. As their height's need to be updated to the max. of all
436 // buttons currently added.
437 mDividerContainer.push_back(divider);
438 mBackground.Add( divider );
439 mContentSize.width += DIVIDER_WIDTH;
443 ImageActor TextInputPopup::CreatePressedBackground( const Vector3 requiredSize )
445 std::string pressedImageFilename;
446 Vector4 pressedImageBorder;
447 Vector2 pressedImageSize;
449 ImageActor pressedButtonBg = Toolkit::CreateSolidColorActor( GetCutPastePopUpPressedColor() );
451 pressedButtonBg.SetSize ( requiredSize );
452 pressedButtonBg.SetParentOrigin( ParentOrigin::CENTER );
453 pressedButtonBg.SetAnchorPoint( AnchorPoint::CENTER );
455 return pressedButtonBg;
458 TextInputPopup::ButtonRequirement TextInputPopup::CreateRequiredButton( TextInputPopup::Buttons buttonId, std::size_t orderOfPriority,
459 const std::string& name, const std::string& caption, Image iconImage, bool enabled )
461 TextInputPopup::ButtonRequirement currentButton;
463 currentButton.buttonId = buttonId;
464 currentButton.orderOfPriority = orderOfPriority;
465 currentButton.name = name;
466 currentButton.caption = caption;
467 currentButton.iconImage = iconImage;
468 currentButton.enabled = enabled;
470 return currentButton;
473 void TextInputPopup::CreateOrderedListOfOptions()
475 mOrderListOfButtons.clear();
477 for ( std::size_t index= 0; index < ButtonsEnumEnd; index++ )
479 TextInputPopup::ButtonRequirement currentButton;
481 // Create button for each possible option using Option priority
486 Image cutIcon = Image::New( DEFAULT_ICON_CUT );
487 currentButton = CreateRequiredButton( ButtonsCut, mCutOptionPriority, OPTION_CUT, GET_LOCALE_TEXT("IDS_COM_BODY_CUT"), cutIcon, false );
492 Image copyIcon = Image::New( DEFAULT_ICON_COPY );
493 currentButton = CreateRequiredButton( ButtonsCopy, mCopyOptionPriority, OPTION_COPY, GET_LOCALE_TEXT("IDS_COM_BODY_COPY"), copyIcon, false );
498 Image pasteIcon = Image::New( DEFAULT_ICON_PASTE );
499 currentButton = CreateRequiredButton( ButtonsPaste, mPasteOptionPriority, OPTION_PASTE, GET_LOCALE_TEXT("IDS_COM_BODY_PASTE"), pasteIcon, false );
504 Image selectIcon = Image::New( DEFAULT_ICON_SELECT );
505 currentButton = CreateRequiredButton( ButtonsSelect, mSelectOptionPriority, OPTION_SELECT_WORD, GET_LOCALE_TEXT("IDS_COM_SK_SELECT"), selectIcon, false );
508 case ButtonsSelectAll:
510 Image selectAllIcon = Image::New( DEFAULT_ICON_SELECT_ALL );
511 currentButton = CreateRequiredButton( ButtonsSelectAll, mSelectAllOptionPriority, OPTION_SELECT_ALL, GET_LOCALE_TEXT("IDS_COM_BODY_SELECT_ALL"), selectAllIcon, false );
514 case ButtonsClipboard:
516 Image clipboardIcon = Image::New( DEFAULT_ICON_CLIPBOARD );
517 currentButton = CreateRequiredButton( ButtonsClipboard, mClipboardOptionPriority, OPTION_CLIPBOARD, GET_LOCALE_TEXT("IDS_COM_BODY_CLIPBOARD"), clipboardIcon, false );
522 DALI_ASSERT_DEBUG( "ButtonsEnumEnd used but an invalid choice");
523 currentButton.orderOfPriority = 0;
530 // Insert button in list of buttons in order of priority setting.
531 for( std::vector<ButtonRequirement>::iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt && !match ); ++it )
533 const ButtonRequirement& button( *it );
534 if ( currentButton.orderOfPriority < button.orderOfPriority )
536 if ( currentButton.orderOfPriority != 0 ) // If order priority 0 then do not add button as not required.
538 mOrderListOfButtons.insert( it, currentButton );
546 mOrderListOfButtons.push_back( currentButton );
551 void TextInputPopup::AddOption(const std::string& name, const std::string& caption, const Image iconImage, bool finalOption)
553 CreatePopUpBackground();
557 // Create a Button with Text, Icon and highlight when pressed
559 Toolkit::PushButton button = Toolkit::PushButton::New();
560 button.SetSizePolicy( Toolkit::Control::Fixed, Toolkit::Control::Fixed );
561 button.SetName( name );
563 // Create container for text and icon when not pressed
564 Actor iconTextContainer = Actor::New();
565 iconTextContainer.SetParentOrigin( ParentOrigin::TOP_LEFT );
566 iconTextContainer.SetAnchorPoint( AnchorPoint::TOP_LEFT );
570 style.SetFontPointSize( PointSize( DEFAULT_UI_FONT_SIZE ) );
571 MarkupProcessor::StyledTextArray styledCaption;
572 styledCaption.push_back( MarkupProcessor::StyledText( Text( caption ), style ) );
573 Toolkit::TextView label = CreateOptionText( styledCaption );
574 label.SetName( name );
576 iconTextContainer.Add( label );
578 // Get natural size of text and then constrain it to bounds.
579 const Vector3 textSize = label.GetNaturalSize();
580 const Vector3 constrainedTextSize = Min( textSize, TEXT_LABEL_MAX_SIZE );
581 Vector3 buttonSize( Max(constrainedTextSize + BUTTON_TEXT_ENLARGE, BUTTON_TEXT_MINIMUM_SIZE) );
582 buttonSize = ( Min(buttonSize, BUTTON_TEXT_MAXIMUM_SIZE) );
583 label.SetSize( Min( buttonSize, constrainedTextSize ) );
585 button.SetParentOrigin( ParentOrigin::TOP_LEFT );
586 button.SetAnchorPoint( AnchorPoint::TOP_LEFT );
587 button.SetSize( buttonSize );
588 button.SetPosition( Vector3( mContentSize.width, POPUP_BORDER.y, 0.0f ) );
591 ImageActor icon = CreateOptionIcon( iconImage );
593 iconTextContainer.Add( icon );
595 // 3. Add highlight - Pressed state in Pushbutton needs a new image which means creating the text and icon again but including a highlight this time.
596 ImageActor pressedImageBg = CreatePressedBackground( buttonSize );
598 Actor iconPressedTextContainer = Actor::New();
599 iconPressedTextContainer.SetDrawMode( DrawMode::OVERLAY );
601 Toolkit::TextView pressedLabel = CreateOptionText( styledCaption );
602 pressedLabel.SetSize( Min( buttonSize, TEXT_LABEL_MAX_SIZE ) );
603 ImageActor pressedIcon = CreateOptionIcon( iconImage );
605 iconPressedTextContainer.Add( pressedImageBg );
606 iconPressedTextContainer.Add( pressedLabel );
607 iconPressedTextContainer.Add( pressedIcon );
609 // Set Pressed button Image
610 iconPressedTextContainer.SetSize( buttonSize );
611 button.SetPressedImage( iconPressedTextContainer );
613 // Set Normal button Image
614 iconTextContainer.SetSize( buttonSize );
615 button.SetButtonImage( iconTextContainer );
616 mBackground.Add( button );
618 // Update content size (represents size of all content i.e. from top-left of first button, to bottom-right of last button)
619 mContentSize.width += buttonSize.width;
620 mContentSize.height = std::max(mContentSize.height + ( POPUP_BORDER.y ), buttonSize.height);
621 mButtonContainer.push_back(button);
623 // resize all dividers based on the height content (i.e. max of all button heights)
624 const float dividerHeight = mContentSize.height - DIVIDER_MARGIN;
625 for(ActorIter i = mDividerContainer.begin(); i != mDividerContainer.end(); ++i)
627 i->SetSize( DIVIDER_WIDTH, dividerHeight );
629 button.ClickedSignal().Connect( this, &TextInputPopup::OnButtonPressed );
632 void TextInputPopup::Hide(bool animate)
644 mAnimation = Animation::New( HIDE_POPUP_ANIMATION_DURATION );
645 mAnimation.AnimateTo( Property(mRootActor, Actor::SCALE), Vector3::ZERO, AlphaFunctions::EaseOut );
646 mAnimation.AnimateTo( Property(mRootActor, Actor::COLOR_ALPHA), 0.0f, AlphaFunctions::EaseOut );
649 mAnimation.FinishedSignal().Connect( this, &TextInputPopup::OnHideFinished );
650 mState = StateHiding;
654 mRootActor.SetProperty(Actor::SCALE, Vector3::ZERO);
655 mRootActor.SetProperty(Actor::COLOR_ALPHA, 0.0f);
656 mState = StateHidden;
661 void TextInputPopup::Show(bool animate)
665 mRootActor.SetSensitive( true );
667 mTail.SetPosition(Vector3( mPopupTailXPosition, 0.0f, 0.0f));
677 mAnimation = Animation::New( SHOW_POPUP_ANIMATION_DURATION );
678 mAnimation.AnimateTo( Property(mRootActor, Actor::SCALE), Vector3::ONE, AlphaFunctions::EaseOut );
679 mAnimation.AnimateTo( Property(mRootActor, Actor::COLOR_ALPHA), 1.0f, AlphaFunctions::EaseOut );
682 mAnimation.FinishedSignal().Connect( this, &TextInputPopup::OnShowFinished );
683 mState = StateShowing;
687 mRootActor.SetProperty(Actor::SCALE, Vector3::ONE);
688 mRootActor.SetProperty(Actor::COLOR_ALPHA, 1.0f);
694 void TextInputPopup::SetAlternativeOffset(Vector2 offset)
696 mRootActor.SetProperty( mAlternativeOffsetProperty, offset );
697 ApplyConfinementConstraint();
700 TextInputPopup::State TextInputPopup::GetState(void) const
705 Actor TextInputPopup::GetRootActor() const
712 void TextInputPopup::SetCutPastePopUpColor( const Vector4& color )
714 mCutPasteButtonsColor = color;
717 const Vector4& TextInputPopup::GetCutPastePopUpColor() const
719 return mCutPasteButtonsColor;
722 void TextInputPopup::SetCutPastePopUpPressedColor( const Vector4& color )
724 mCutPasteButtonsPressedColor = color;
727 const Vector4& TextInputPopup::GetCutPastePopUpPressedColor() const
729 return mCutPasteButtonsPressedColor;
732 void TextInputPopup::TogglePopUpButtonOnOff( TextInputPopup::Buttons requiredButton, bool enable )
734 bool match ( false );
735 for( std::vector<ButtonRequirement>::iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt && !match ); ++it )
737 ButtonRequirement& button( *it );
738 if ( requiredButton == button.buttonId )
740 button.enabled = enable;
746 void TextInputPopup::SetButtonPriorityPosition( TextInputPopup::Buttons button, unsigned int priority )
752 mCutOptionPriority = priority;
757 mCopyOptionPriority = priority;
762 mPasteOptionPriority = priority;
767 mSelectOptionPriority = priority;
770 case ButtonsSelectAll:
772 mSelectAllOptionPriority = priority;
775 case ButtonsClipboard:
777 mClipboardOptionPriority = priority;
782 DALI_ASSERT_DEBUG( "ButtonsEnumEnd used but an invalid choice");
786 CreateOrderedListOfOptions(); // Update list of options as priority changed.
789 unsigned int TextInputPopup::GetButtonPriorityPosition( TextInputPopup::Buttons button ) const
791 unsigned int priority = 0;
797 priority = mCutOptionPriority;
802 priority = mCopyOptionPriority;
807 priority = mPasteOptionPriority;
812 priority = mSelectOptionPriority;
815 case ButtonsSelectAll:
817 priority = mSelectAllOptionPriority;
820 case ButtonsClipboard:
822 priority = mClipboardOptionPriority;
827 DALI_ASSERT_DEBUG( "ButtonsEnumEnd used but an invalid choice");
835 void TextInputPopup::AddPopupOptions()
837 for( std::vector<ButtonRequirement>::const_iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt ); ++it )
839 const ButtonRequirement& button( *it );
840 if ( button.enabled )
842 AddOption( button.name, button.caption, button.iconImage, false );
846 float visiblePopUpWidth = std::min( mContentSize.width - POP_UP_SCREEN_EDGE_MARGIN*2 , mBoundingRect.width - POP_UP_SCREEN_EDGE_MARGIN *2);
847 float visbilePopUpHeight = std::max( mContentSize.height, POPUP_MINIMUM_SIZE.height );
848 Vector2 visiblePopUpSize = Vector2( visiblePopUpWidth, visbilePopUpHeight );
850 visiblePopUpWidth = std::max( visiblePopUpWidth, POPUP_MINIMUM_SIZE.width );
852 mBackground.SetSize( mContentSize.width, mContentSize.height );
853 mRootActor.SetSize( visiblePopUpWidth, visbilePopUpHeight ); // Make Root Actor reflect the size of its content
855 CreateLayer( visiblePopUpSize );
856 CreateStencil( visiblePopUpSize );
857 CreateScrollView( Vector2( mContentSize.width, mContentSize.height ), visiblePopUpSize );
859 mLayer.Add( mStencil );
860 mLayer.Add( mScrollView );
861 mScrollView.Add( mBackground );
862 mRootActor.Add( mTail );
867 void TextInputPopup::SetPopupBoundary( const Rect<float>& boundingRectangle )
869 mBoundingRect = boundingRectangle;
872 void TextInputPopup::SetTailPosition( const Vector3& position )
874 mPopupTailXPosition = position.x;
875 ApplyTailConstraint();
878 bool TextInputPopup::OnButtonPressed( Toolkit::Button button )
880 mPressedSignal.Emit( button );
884 void TextInputPopup::OnHideFinished(Animation& source)
886 source.FinishedSignal().Disconnect( this, &TextInputPopup::OnHideFinished );
888 mState = StateHidden;
889 mHideFinishedSignal.Emit( *this );
892 void TextInputPopup::OnShowFinished(Animation& source)
894 source.FinishedSignal().Disconnect( this, &TextInputPopup::OnShowFinished );
896 mShowFinishedSignal.Emit( *this );
899 TextInputPopup::PressedSignalV2& TextInputPopup::PressedSignal()
901 return mPressedSignal;
904 TextInputPopup::HideFinishedSignalV2& TextInputPopup::HideFinishedSignal()
906 return mHideFinishedSignal;
909 TextInputPopup::ShowFinishedSignalV2& TextInputPopup::ShowFinishedSignal()
911 return mShowFinishedSignal;
914 } // namespace Internal
916 } // namespace Toolkit