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 Vector4 DEFAULT_POPUP_ICON( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) );
38 const Vector4 DEFAULT_POPUP_ICON_PRESSED( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) );
39 const Vector4 DEFAULT_POPUP_TEXT( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) );
40 const Vector4 DEFAULT_POPUP_TEXT_PRESSED( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) );
41 const Vector3 POPUP_BORDER( Vector3( 1.0f, 1.0f, 0.0f ) );
43 /* Functionality in place to have the end buttons using different images to inner button.
44 * Supply a centre image and then a left and right image, the centre image can have straight ends while
45 * 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.
49 const char* DEFAULT_POPUP_TAIL_BOTTOM( DALI_IMAGE_DIR "popup_bubble_tail_bottom.png" );
50 const char* DEFAULT_POPUP_TAIL_BOTTOM_OUTLINE( DALI_IMAGE_DIR "popup_bubble_tail_bottom_line.png" );
51 const float TAIL_Y_POSITION( -1.5f );
53 // Popup: Vertical Constraint
54 // TODO: Remove - this should come from application - it is not possible to get the
55 // height of the indicator actor from Dali-Toolkit.
57 const float POP_UP_SCREEN_EDGE_MARGIN( 4.0f );
58 const Vector2 DEFAULT_POPUP_INDICATOR_OFFSET(POP_UP_SCREEN_EDGE_MARGIN, 60.0f);
60 const Vector3 POPUP_TEXT_OFFSET( 0.0f, 0.0f, 0.0f );
61 const Vector3 POPUP_TEXT_ENLARGE( 12.0f, 28.0f, 0.0f );
62 const Vector3 POPUP_MINIMUM_SIZE( 128.0f, 124.0f, 0.0f );
64 const Vector3 BUTTON_TEXT_ENLARGE( 32.0f, 0.0f, 0.0f );
65 const Vector3 BUTTON_TEXT_MINIMUM_SIZE( 128.0f, 126.0f, 0.0f );
66 const Vector3 BUTTON_TEXT_MAXIMUM_SIZE( 190.0f, 126.0f, 0.0f );
67 const Vector3 TEXT_LABEL_MAX_SIZE( 160.0f, 30.0f, 0.0f );
69 const float DIVIDER_WIDTH(2.0f); ///< Width of each button divider
70 const float DIVIDER_MARGIN(0.0f); ///< Top/Bottom Margin between divider and edge of popup.
72 const float DEFAULT_UI_FONT_SIZE(7.0f); ///< Standard font size for Text-Input's UI
74 const float HIDE_POPUP_ANIMATION_DURATION(0.2f); ///< Duration of popup hide animation in seconds.
75 const float SHOW_POPUP_ANIMATION_DURATION(0.2f); ///< Duration of popup show animation in seconds.
77 const Vector2 DEFAULT_ICON_SIZE( 45.0f, 45.0f ); ///< Default icon size for image in options
78 const float TEXT_POSITION_OFFSET( -19.0f ); ///< Default offset for text label
79 const float ICON_POSITION_OFFSET( 19.0f ); ///< Default offset for icon
81 const char* DEFAULT_ICON_CLIPBOARD( DALI_IMAGE_DIR "copy_paste_icon_clipboard.png" );
82 const char* DEFAULT_ICON_COPY( DALI_IMAGE_DIR "copy_paste_icon_copy.png" );
83 const char* DEFAULT_ICON_CUT( DALI_IMAGE_DIR "copy_paste_icon_cut.png" );
84 const char* DEFAULT_ICON_PASTE( DALI_IMAGE_DIR "copy_paste_icon_paste.png" );
85 const char* DEFAULT_ICON_SELECT( DALI_IMAGE_DIR "copy_paste_icon_select.png" );
86 const char* DEFAULT_ICON_SELECT_ALL( DALI_IMAGE_DIR "copy_paste_icon_select_all.png" );
88 // TODO: This should be based on the content for example:
89 // 1. For selection: should be above top of highlighted selection, or below bottom of highlighted selection + end handle.
90 // 2. For cursor: should be above top of cursor, or below bottom of cursor + grab handle.
91 const std::string POPUP_ALTERNATIVE_OFFSET("popup-alternative-offset"); ///< Alternative offset property for confinenment constraint.
93 const std::string POPUP_REQUESTED_POSITION("popup-requested-position"); ///< Position the Popup was requested to be, for confinenment constraint.
96 * Confine Actor to boundaries of reference actor (e.g. Parent)
97 * Actor bounds (top-left position + size) are confined to reference Actor's
100 struct ConfinementConstraint
103 * Confinement constraint constructor.
104 * @param[in] topLeftMargin (optional) Top-Left margins (defaults to 0.0f, 0.0f)
105 * @param[in] bottomRightMargin (optional) Bottom-Right margins (defaults to 0.0f, 0.0f)
106 * @paran[in[ flipHorizontal (optional) whether to flip Actor to other side if near edge
107 * @param[in] flipVertical (optional) whether to flip Actor to the other side if near edge
108 * @param[in] boundingRect Rectangle to bound Popup to.
111 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) )
112 : mMinIndent(topLeftMargin),
113 mMaxIndent(bottomRightMargin),
114 mFlipHorizontal(flipHorizontal),
115 mFlipVertical(flipVertical),
116 mBoundingRect( boundingRect )
120 Vector3 operator()(const Vector3& constPosition,
121 const PropertyInput& sizeProperty,
122 const PropertyInput& parentOriginProperty,
123 const PropertyInput& anchorPointProperty,
124 const PropertyInput& referenceSizeProperty,
125 const PropertyInput& alternativeOffsetProperty,
126 const PropertyInput& requestedPositionProperty )
128 const Vector3& size = sizeProperty.GetVector3();
129 const Vector3& origin = parentOriginProperty.GetVector3();
130 const Vector3& anchor = anchorPointProperty.GetVector3();
131 const Vector3& referenceSize = referenceSizeProperty.GetVector3();
132 const Vector2& alternativeOffset = alternativeOffsetProperty.GetVector2();
133 const Vector3& requestedPosition = requestedPositionProperty.GetVector3();
135 Vector3 newPosition( requestedPosition );
137 // Get actual position of Actor relative to parent's Top-Left.
138 Vector3 position(constPosition + origin * referenceSize);
140 // if top-left corner is outside of Top-Left bounds, then push back in screen.
142 Vector3 corner(position - size * anchor - mMinIndent);
144 if ( mFlipHorizontal )
146 if( corner.x < mBoundingRect.x + POP_UP_SCREEN_EDGE_MARGIN )
148 // Snap PopUp to left hand boundary so stays visible
149 corner.x = mBoundingRect.x + POP_UP_SCREEN_EDGE_MARGIN - ( origin.x * referenceSize.x ) + ( size.x * anchor.x );
150 newPosition.x = corner.x;
152 else if ( ( corner.x + size.x ) > ( ( mBoundingRect.x + mBoundingRect.width ) - POP_UP_SCREEN_EDGE_MARGIN ))
154 // Calculate offset from left boundary PopUp must be placed at so it does not exceed right side boundary.
155 float requiredOffSetFromLeftBoundaryToFit = mBoundingRect.width - POP_UP_SCREEN_EDGE_MARGIN - size.x;
156 corner.x = mBoundingRect.x + requiredOffSetFromLeftBoundaryToFit - ( origin.x * referenceSize.x ) + ( size.x * anchor.x );
157 newPosition.x = corner.x;
161 if(mFlipVertical && corner.y < 0.0f)
164 newPosition.y += size.height + alternativeOffset.height;
167 newPosition.y -= std::min(corner.y, 0.0f);
169 // if bottom-right corner is outside of Bottom-Right bounds, then push back in screen.
170 corner += size - referenceSize + mMinIndent + mMaxIndent;
172 if(mFlipVertical && corner.y > 0.0f)
175 newPosition.y -= size.height + alternativeOffset.height;
181 Vector3 mMinIndent; ///< Top-Left Margin
182 Vector3 mMaxIndent; ///< Bottom-Right Margin.
183 bool mFlipHorizontal; ///< Whether to flip actor's position if exceeds horizontal screen bounds
184 bool mFlipVertical; ///< Whether to flip actor's position if exceeds vertical screen bounds
185 Rect<float> mBoundingRect; ///< Bounding Rect Popup must stay within
189 * Confine actor to the x axis boundaries of reference actor (e.g. Parent)
191 struct ParentXAxisConstraint
194 * Confinement constraint constructor.
196 ParentXAxisConstraint( float handlesMidPoint = 0.0f )
197 : mHandlesMidPoint( handlesMidPoint )
201 float operator()( const float constXPosition,
202 const PropertyInput& localSizeWidthProperty,
203 const PropertyInput& parentWidthProperty,
204 const PropertyInput& anchorPointXProperty )
206 const float localSizeProperty = localSizeWidthProperty.GetFloat();
207 const float size = parentWidthProperty.GetFloat();
209 float newPosition = std::max( mHandlesMidPoint, -size/2 + localSizeProperty );
210 newPosition = std::min( newPosition, size/2 - localSizeProperty );
214 float mHandlesMidPoint;
218 } // unnamed namespace
229 const char* const TextInputPopup::SIGNAL_PRESSED = "pressed";
230 const char* const TextInputPopup::SIGNAL_HIDE_FINISHED = "hide-finished";
231 const char* const TextInputPopup::SIGNAL_SHOW_FINISHED = "show-finished";
233 const char* const TextInputPopup::OPTION_SELECT_WORD = "option-select_word"; // "Select Word" popup option.
234 const char* const TextInputPopup::OPTION_SELECT_ALL("option-select_all"); // "Select All" popup option.
235 const char* const TextInputPopup::OPTION_CUT("option-cut"); // "Cut" popup option.
236 const char* const TextInputPopup::OPTION_COPY("option-copy"); // "Copy" popup option.
237 const char* const TextInputPopup::OPTION_PASTE("option-paste"); // "Paste" popup option.
238 const char* const TextInputPopup::OPTION_CLIPBOARD("option-clipboard"); // "Clipboard" popup option.
240 TextInputPopup::TextInputPopup()
241 : mState(StateHidden),
242 mRootActor(Layer::New()),
243 mPopupTailXPosition( 0.0f ),
244 mContentSize( Vector3::ZERO ),
245 mCutPasteButtonsColor( DEFAULT_POPUP_BACKGROUND ),
246 mCutPasteButtonsPressedColor( DEFAULT_POPUP_BUTTON_PRESSED ),
247 mBorderColor( DEFAULT_BORDER_COLOR ),
248 mCutPasteIconsColor( DEFAULT_POPUP_ICON ),
249 mCutPasteIconsPressedColor( DEFAULT_POPUP_ICON_PRESSED ),
250 mCutPasteTextsColor( DEFAULT_POPUP_TEXT ),
251 mCutPasteTextsPressedColor( DEFAULT_POPUP_TEXT_PRESSED ),
252 mSelectOptionPriority(1),
253 mSelectAllOptionPriority(2),
254 mCutOptionPriority(3),
255 mCopyOptionPriority(4),
256 mPasteOptionPriority(5),
257 mClipboardOptionPriority(6),
259 mHideFinishedSignal(),
260 mShowFinishedSignal()
262 mAlternativeOffsetProperty = mRootActor.RegisterProperty( POPUP_ALTERNATIVE_OFFSET, Vector2::ZERO );
263 mRequestionPositionProperty = mRootActor.RegisterProperty( POPUP_REQUESTED_POSITION, Vector3::ZERO );
264 mRootActor.SetParentOrigin( ParentOrigin::CENTER );
265 mRootActor.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
266 // constrain popup to size of parent.
269 Actor TextInputPopup::Self()
274 void TextInputPopup::AddToStage()
276 // TODO: Confinement constraint borders should be defined by the application.
277 // It should also not use the stage directly, instead it should add to parent container.
278 Stage::GetCurrent().Add(mRootActor);
280 ApplyConfinementConstraint();
283 void TextInputPopup::ApplyConfinementConstraint()
285 mRootActor.RemoveConstraints();
286 Constraint constraint = Constraint::New<Vector3>( Actor::POSITION,
287 LocalSource( Actor::SIZE ),
288 LocalSource( Actor::PARENT_ORIGIN ),
289 LocalSource( Actor::ANCHOR_POINT ),
290 ParentSource( Actor::SIZE ),
291 LocalSource( mAlternativeOffsetProperty ),
292 LocalSource( mRequestionPositionProperty),
293 ConfinementConstraint( DEFAULT_POPUP_INDICATOR_OFFSET,
296 true, mBoundingRect ) );
297 mRootActor.ApplyConstraint(constraint);
300 void TextInputPopup::ApplyTailConstraint()
302 mTail.RemoveConstraints();
303 Constraint constraint = Constraint::New<float>( Actor::POSITION_X,
304 LocalSource( Actor::SIZE_WIDTH ),
305 ParentSource( Actor::SIZE_WIDTH ),
306 LocalSource( Actor::PARENT_ORIGIN_X ),
307 ParentXAxisConstraint( mPopupTailXPosition ));
308 mTail.ApplyConstraint( constraint );
311 void TextInputPopup::CreateLayer( const Vector2& size )
313 mLayer = Layer::New();
314 mLayer.SetParentOrigin(ParentOrigin::CENTER);
315 mLayer.SetAnchorPoint(AnchorPoint::CENTER);
316 mLayer.SetSize( size ); // matches stencil size
317 mLayer.SetName("popup-mLayer");
320 void TextInputPopup::CreateStencil( const Vector2& size )
322 mStencil = CreateSolidColorActor( Color::BLUE );
323 mStencil.SetParentOrigin( Vector3( ParentOrigin::CENTER ) );
324 mStencil.SetAnchorPoint( AnchorPoint::CENTER );
325 mStencil.SetDrawMode( DrawMode::STENCIL );
326 mStencil.SetSize( size ); // slightly smaller than layer and stencil so over shoot always inside.
327 mStencil.SetVisible( true );
328 mStencil.SetName("popup-stencil");
331 void TextInputPopup::OnScrollStarted( const Vector3& position )
333 mBackground.SetSensitive( false );
336 void TextInputPopup::OnScrollCompleted( const Vector3& position )
338 mBackground.SetSensitive( true );
341 void TextInputPopup::CreateScrollView( const Vector2& domainSize, const Vector2& visibleSize )
343 mScrollView = Toolkit::ScrollView::New();
344 mScrollView.SetName("popup-scroll-view");
345 mScrollView.SetAnchorPoint( AnchorPoint::TOP_LEFT );
346 mScrollView.SetParentOrigin( ParentOrigin::TOP_LEFT );
347 mScrollView.SetSize( visibleSize.x, visibleSize.y );
348 mScrollView.SetScrollingDirection( PanGestureDetector::DIRECTION_HORIZONTAL, Degree( 40.0f ) );
349 mScrollView.SetAxisAutoLock( true );
350 mScrollView.ScrollStartedSignal().Connect( this, &TextInputPopup::OnScrollStarted );
351 mScrollView.ScrollCompletedSignal().Connect( this, &TextInputPopup::OnScrollCompleted );
353 RulerPtr rulerX = new DefaultRuler(); // IntrusivePtr which is unreferenced when ScrollView is destroyed.
354 RulerPtr rulerY = new DefaultRuler(); // IntrusivePtr which is unreferenced when ScrollView is destroyed.
356 rulerX->SetDomain( RulerDomain( 0, domainSize.width, true ) );
357 mScrollView.SetRulerX(rulerX);
358 mScrollView.SetRulerY(rulerY);
361 void TextInputPopup::RemoveFromStage()
363 Actor rootActor = Self();
364 Stage::GetCurrent().Remove( rootActor );
367 void TextInputPopup::Clear()
371 UnparentAndReset( mTail );
372 UnparentAndReset( mStencil );
373 UnparentAndReset( mBackground );
374 UnparentAndReset( mScrollView );
375 UnparentAndReset( mLayer );
376 mButtonContainer.clear();
377 mDividerContainer.clear();
380 mRootActor.RemoveConstraints();
382 mState = StateHidden;
386 Toolkit::TextView TextInputPopup::CreateOptionText( const MarkupProcessor::StyledTextArray& styledCaption )
388 Toolkit::TextView label = Toolkit::TextView::New( styledCaption );
389 label.SetSizePolicy( Toolkit::Control::Fixed, Toolkit::Control::Fixed );
390 label.SetWidthExceedPolicy( Toolkit::TextView::Fade );
391 label.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
392 label.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
393 label.SetPosition( 0.0f, TEXT_POSITION_OFFSET );
398 ImageActor TextInputPopup::CreateOptionIcon( Image iconImage, const Vector4& color )
400 ImageActor icon = ImageActor::New( iconImage );
402 icon.SetSize( DEFAULT_ICON_SIZE );
403 icon.SetParentOrigin( ParentOrigin::TOP_CENTER );
404 icon.SetAnchorPoint( AnchorPoint::TOP_CENTER );
405 icon.SetPosition( 0.0f, ICON_POSITION_OFFSET );
406 icon.SetColor( color );
411 void TextInputPopup::CreatePopUpBackground()
413 // Create background-panel if not already created (required if we have at least one option)
416 mBackground = Toolkit::CreateSolidColorActor( GetCutPastePopUpColor(), true, mBorderColor );
417 mBackground.SetAnchorPoint( AnchorPoint::TOP_LEFT );
418 mBackground.SetParentOrigin( ParentOrigin::TOP_LEFT );
419 mBackground.SetName("pop-up-background");
420 mContentSize = POPUP_TEXT_OFFSET;
425 Image tailImage = Image::New( DEFAULT_POPUP_TAIL_BOTTOM );
426 Image tailImageOutline = Image::New( DEFAULT_POPUP_TAIL_BOTTOM_OUTLINE );
428 mTailOutline = ImageActor::New ( tailImageOutline );
429 mTailOutline.SetParentOrigin( ParentOrigin::CENTER );
430 mTailOutline.SetAnchorPoint( AnchorPoint::CENTER );
431 mTailOutline.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) );
433 mTail = ImageActor::New( tailImage );
434 mTail.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
435 mTail.SetAnchorPoint( AnchorPoint::TOP_CENTER );
436 mTail.SetPosition( 0.0f, TAIL_Y_POSITION );
437 // TODO: Make tail visible, and positioned in relation to original intended position of popup (i.e. before constrained effects)
438 mTail.SetVisible(true);
439 mTail.SetColor( mCutPasteButtonsColor );
440 mTailOutline.SetColor( mBorderColor );
441 mTail.Add( mTailOutline);
445 void TextInputPopup::CreateDivider()
447 if(mButtonContainer.size() > 0)
449 ImageActor divider = Toolkit::CreateSolidColorActor( mBorderColor );
450 divider.SetParentOrigin( ParentOrigin::TOP_LEFT );
451 divider.SetAnchorPoint( AnchorPoint::TOP_LEFT );
452 divider.SetPosition( Vector3( mContentSize.width, POPUP_TEXT_OFFSET.y, 0.0f ) );
453 divider.SetColor( mBorderColor );
454 // Keep track of all the dividers. As their height's need to be updated to the max. of all
455 // buttons currently added.
456 mDividerContainer.push_back(divider);
457 mBackground.Add( divider );
458 mContentSize.width += DIVIDER_WIDTH;
462 ImageActor TextInputPopup::CreatePressedBackground( const Vector3 requiredSize )
464 std::string pressedImageFilename;
465 Vector4 pressedImageBorder;
466 Vector2 pressedImageSize;
468 ImageActor pressedButtonBg = Toolkit::CreateSolidColorActor( GetCutPastePopUpPressedColor() );
470 pressedButtonBg.SetSize ( requiredSize );
471 pressedButtonBg.SetParentOrigin( ParentOrigin::CENTER );
472 pressedButtonBg.SetAnchorPoint( AnchorPoint::CENTER );
474 return pressedButtonBg;
477 TextInputPopup::ButtonRequirement TextInputPopup::CreateRequiredButton( TextInputPopup::Buttons buttonId, std::size_t orderOfPriority,
478 const std::string& name, const std::string& caption, Image iconImage, bool enabled )
480 TextInputPopup::ButtonRequirement currentButton;
482 currentButton.buttonId = buttonId;
483 currentButton.orderOfPriority = orderOfPriority;
484 currentButton.name = name;
485 currentButton.caption = caption;
486 currentButton.iconImage = iconImage;
487 currentButton.enabled = enabled;
489 return currentButton;
492 void TextInputPopup::CreateOrderedListOfOptions()
494 mOrderListOfButtons.clear();
496 for ( std::size_t index= 0; index < ButtonsEnumEnd; index++ )
498 TextInputPopup::ButtonRequirement currentButton;
500 // Create button for each possible option using Option priority
505 Image cutIcon = Image::New( DEFAULT_ICON_CUT );
506 currentButton = CreateRequiredButton( ButtonsCut, mCutOptionPriority, OPTION_CUT, GET_LOCALE_TEXT("IDS_COM_BODY_CUT"), cutIcon, false );
511 Image copyIcon = Image::New( DEFAULT_ICON_COPY );
512 currentButton = CreateRequiredButton( ButtonsCopy, mCopyOptionPriority, OPTION_COPY, GET_LOCALE_TEXT("IDS_COM_BODY_COPY"), copyIcon, false );
517 Image pasteIcon = Image::New( DEFAULT_ICON_PASTE );
518 currentButton = CreateRequiredButton( ButtonsPaste, mPasteOptionPriority, OPTION_PASTE, GET_LOCALE_TEXT("IDS_COM_BODY_PASTE"), pasteIcon, false );
523 Image selectIcon = Image::New( DEFAULT_ICON_SELECT );
524 currentButton = CreateRequiredButton( ButtonsSelect, mSelectOptionPriority, OPTION_SELECT_WORD, GET_LOCALE_TEXT("IDS_COM_SK_SELECT"), selectIcon, false );
527 case ButtonsSelectAll:
529 Image selectAllIcon = Image::New( DEFAULT_ICON_SELECT_ALL );
530 currentButton = CreateRequiredButton( ButtonsSelectAll, mSelectAllOptionPriority, OPTION_SELECT_ALL, GET_LOCALE_TEXT("IDS_COM_BODY_SELECT_ALL"), selectAllIcon, false );
533 case ButtonsClipboard:
535 Image clipboardIcon = Image::New( DEFAULT_ICON_CLIPBOARD );
536 currentButton = CreateRequiredButton( ButtonsClipboard, mClipboardOptionPriority, OPTION_CLIPBOARD, GET_LOCALE_TEXT("IDS_COM_BODY_CLIPBOARD"), clipboardIcon, false );
541 DALI_ASSERT_DEBUG( "ButtonsEnumEnd used but an invalid choice");
542 currentButton.orderOfPriority = 0;
549 // Insert button in list of buttons in order of priority setting.
550 for( std::vector<ButtonRequirement>::iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt && !match ); ++it )
552 const ButtonRequirement& button( *it );
553 if ( currentButton.orderOfPriority < button.orderOfPriority )
555 if ( currentButton.orderOfPriority != 0 ) // If order priority 0 then do not add button as not required.
557 mOrderListOfButtons.insert( it, currentButton );
565 mOrderListOfButtons.push_back( currentButton );
570 void TextInputPopup::AddOption(const std::string& name, const std::string& caption, const Image iconImage, bool finalOption)
572 CreatePopUpBackground();
576 // Create a Button with Text, Icon and highlight when pressed
578 Toolkit::PushButton button = Toolkit::PushButton::New();
579 button.SetSizePolicy( Toolkit::Control::Fixed, Toolkit::Control::Fixed );
580 button.SetName( name );
582 // Create container for text and icon when not pressed
583 Actor iconTextContainer = Actor::New();
584 iconTextContainer.SetParentOrigin( ParentOrigin::TOP_LEFT );
585 iconTextContainer.SetAnchorPoint( AnchorPoint::TOP_LEFT );
589 style.SetFontPointSize( PointSize( DEFAULT_UI_FONT_SIZE ) );
590 style.SetTextColor( mCutPasteTextsColor );
591 MarkupProcessor::StyledTextArray styledCaption;
592 styledCaption.push_back( MarkupProcessor::StyledText( Text( caption ), style ) );
593 Toolkit::TextView label = CreateOptionText( styledCaption );
594 label.SetName( name );
596 iconTextContainer.Add( label );
598 // Get natural size of text and then constrain it to bounds.
599 const Vector3 textSize = label.GetNaturalSize();
600 const Vector3 constrainedTextSize = Min( textSize, TEXT_LABEL_MAX_SIZE );
601 Vector3 buttonSize( Max(constrainedTextSize + BUTTON_TEXT_ENLARGE, BUTTON_TEXT_MINIMUM_SIZE) );
602 buttonSize = ( Min(buttonSize, BUTTON_TEXT_MAXIMUM_SIZE) );
603 label.SetSize( Min( buttonSize, constrainedTextSize ) );
605 button.SetParentOrigin( ParentOrigin::TOP_LEFT );
606 button.SetAnchorPoint( AnchorPoint::TOP_LEFT );
607 button.SetSize( buttonSize );
608 button.SetPosition( Vector3( mContentSize.width, POPUP_BORDER.y, 0.0f ) );
611 ImageActor icon = CreateOptionIcon( iconImage, mCutPasteIconsColor );
613 iconTextContainer.Add( icon );
615 // 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.
616 ImageActor pressedImageBg = CreatePressedBackground( buttonSize );
618 Actor iconPressedTextContainer = Actor::New();
619 iconPressedTextContainer.SetDrawMode( DrawMode::OVERLAY );
621 style.SetTextColor( mCutPasteTextsPressedColor );
622 styledCaption.clear();
623 styledCaption.push_back( MarkupProcessor::StyledText( Text( caption ), style ) );
624 Toolkit::TextView pressedLabel = CreateOptionText( styledCaption );
625 pressedLabel.SetSize( Min( buttonSize, TEXT_LABEL_MAX_SIZE ) );
626 ImageActor pressedIcon = CreateOptionIcon( iconImage, mCutPasteIconsPressedColor );
628 iconPressedTextContainer.Add( pressedImageBg );
629 iconPressedTextContainer.Add( pressedLabel );
630 iconPressedTextContainer.Add( pressedIcon );
632 // Set Pressed button Image
633 iconPressedTextContainer.SetSize( buttonSize );
634 button.SetPressedImage( iconPressedTextContainer );
636 // Set Normal button Image
637 iconTextContainer.SetSize( buttonSize );
638 button.SetButtonImage( iconTextContainer );
639 mBackground.Add( button );
641 // Update content size (represents size of all content i.e. from top-left of first button, to bottom-right of last button)
642 mContentSize.width += buttonSize.width;
643 mContentSize.height = std::max(mContentSize.height + ( POPUP_BORDER.y ), buttonSize.height);
644 mButtonContainer.push_back(button);
646 // resize all dividers based on the height content (i.e. max of all button heights)
647 const float dividerHeight = mContentSize.height - DIVIDER_MARGIN;
648 for(ActorIter i = mDividerContainer.begin(); i != mDividerContainer.end(); ++i)
650 i->SetSize( DIVIDER_WIDTH, dividerHeight );
652 button.ClickedSignal().Connect( this, &TextInputPopup::OnButtonPressed );
655 void TextInputPopup::Hide(bool animate)
667 mAnimation = Animation::New( HIDE_POPUP_ANIMATION_DURATION );
668 mAnimation.AnimateTo( Property(mRootActor, Actor::SCALE), Vector3::ZERO, AlphaFunctions::EaseOut );
669 mAnimation.AnimateTo( Property(mRootActor, Actor::COLOR_ALPHA), 0.0f, AlphaFunctions::EaseOut );
672 mAnimation.FinishedSignal().Connect( this, &TextInputPopup::OnHideFinished );
673 mState = StateHiding;
677 mRootActor.SetProperty(Actor::SCALE, Vector3::ZERO);
678 mRootActor.SetProperty(Actor::COLOR_ALPHA, 0.0f);
679 mState = StateHidden;
684 void TextInputPopup::Show(bool animate)
688 mRootActor.SetSensitive( true );
698 mAnimation = Animation::New( SHOW_POPUP_ANIMATION_DURATION );
699 mAnimation.AnimateTo( Property(mRootActor, Actor::SCALE), Vector3::ONE, AlphaFunctions::EaseOut );
700 mAnimation.AnimateTo( Property(mRootActor, Actor::COLOR_ALPHA), 1.0f, AlphaFunctions::EaseOut );
703 mAnimation.FinishedSignal().Connect( this, &TextInputPopup::OnShowFinished );
704 mState = StateShowing;
708 mRootActor.SetProperty(Actor::SCALE, Vector3::ONE);
709 mRootActor.SetProperty(Actor::COLOR_ALPHA, 1.0f);
715 void TextInputPopup::SetAlternativeOffset(Vector2 offset)
717 mRootActor.SetProperty( mAlternativeOffsetProperty, offset );
718 ApplyConfinementConstraint();
721 TextInputPopup::State TextInputPopup::GetState(void) const
726 Actor TextInputPopup::GetRootActor() const
733 void TextInputPopup::SetCutPastePopUpColor( const Vector4& color )
735 mCutPasteButtonsColor = color;
738 const Vector4& TextInputPopup::GetCutPastePopUpColor() const
740 return mCutPasteButtonsColor;
743 void TextInputPopup::SetCutPastePopUpPressedColor( const Vector4& color )
745 mCutPasteButtonsPressedColor = color;
748 const Vector4& TextInputPopup::GetCutPastePopUpPressedColor() const
750 return mCutPasteButtonsPressedColor;
753 void TextInputPopup::SetCutPastePopUpBorderColor( const Vector4& color )
755 mBorderColor = color;
758 const Vector4& TextInputPopup::GetCutPastePopUpBorderColor() const
763 void TextInputPopup::SetCutPastePopUpIconColor( const Vector4& color )
765 mCutPasteIconsColor = color;
768 const Vector4& TextInputPopup::GetCutPastePopUpIconColor() const
770 return mCutPasteIconsColor;
773 void TextInputPopup::SetCutPastePopUpIconPressedColor( const Vector4& color )
775 mCutPasteIconsPressedColor = color;
778 const Vector4& TextInputPopup::GetCutPastePopUpIconPressedColor()
780 return mCutPasteIconsPressedColor;
783 void TextInputPopup::SetCutPastePopUpTextColor( const Vector4& color )
785 mCutPasteTextsColor = color;
788 const Vector4& TextInputPopup::GetCutPastePopUpTextColor()
790 return mCutPasteTextsColor;
793 void TextInputPopup::SetCutPastePopUpTextPressedColor( const Vector4& color )
795 mCutPasteTextsPressedColor = color;
798 const Vector4& TextInputPopup::GetCutPastePopUpTextPressedColor()
800 return mCutPasteTextsPressedColor;
803 void TextInputPopup::TogglePopUpButtonOnOff( TextInputPopup::Buttons requiredButton, bool enable )
805 bool match ( false );
806 for( std::vector<ButtonRequirement>::iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt && !match ); ++it )
808 ButtonRequirement& button( *it );
809 if ( requiredButton == button.buttonId )
811 button.enabled = enable;
817 void TextInputPopup::SetButtonPriorityPosition( TextInputPopup::Buttons button, unsigned int priority )
823 mCutOptionPriority = priority;
828 mCopyOptionPriority = priority;
833 mPasteOptionPriority = priority;
838 mSelectOptionPriority = priority;
841 case ButtonsSelectAll:
843 mSelectAllOptionPriority = priority;
846 case ButtonsClipboard:
848 mClipboardOptionPriority = priority;
853 DALI_ASSERT_DEBUG( "ButtonsEnumEnd used but an invalid choice");
857 CreateOrderedListOfOptions(); // Update list of options as priority changed.
860 unsigned int TextInputPopup::GetButtonPriorityPosition( TextInputPopup::Buttons button ) const
862 unsigned int priority = 0;
868 priority = mCutOptionPriority;
873 priority = mCopyOptionPriority;
878 priority = mPasteOptionPriority;
883 priority = mSelectOptionPriority;
886 case ButtonsSelectAll:
888 priority = mSelectAllOptionPriority;
891 case ButtonsClipboard:
893 priority = mClipboardOptionPriority;
898 DALI_ASSERT_DEBUG( "ButtonsEnumEnd used but an invalid choice");
906 void TextInputPopup::AddPopupOptions()
908 for( std::vector<ButtonRequirement>::const_iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt ); ++it )
910 const ButtonRequirement& button( *it );
911 if ( button.enabled )
913 AddOption( button.name, button.caption, button.iconImage, false );
917 float visiblePopUpWidth = std::min( mContentSize.width - POP_UP_SCREEN_EDGE_MARGIN*2 , mBoundingRect.width - POP_UP_SCREEN_EDGE_MARGIN *2);
918 float visbilePopUpHeight = std::max( mContentSize.height, POPUP_MINIMUM_SIZE.height );
919 Vector2 visiblePopUpSize = Vector2( visiblePopUpWidth, visbilePopUpHeight );
921 visiblePopUpWidth = std::max( visiblePopUpWidth, POPUP_MINIMUM_SIZE.width );
923 mBackground.SetSize( mContentSize.width, mContentSize.height );
924 mRootActor.SetSize( visiblePopUpWidth, visbilePopUpHeight ); // Make Root Actor reflect the size of its content
926 CreateLayer( visiblePopUpSize );
927 CreateStencil( visiblePopUpSize );
928 CreateScrollView( Vector2( mContentSize.width, mContentSize.height ), visiblePopUpSize );
930 mLayer.Add( mStencil );
931 mLayer.Add( mScrollView );
932 mScrollView.Add( mBackground );
933 mRootActor.Add( mTail );
940 void TextInputPopup::SetPopupBoundary( const Rect<float>& boundingRectangle )
942 mBoundingRect = boundingRectangle;
945 void TextInputPopup::SetTailPosition( const Vector3& position )
947 mRootActor.SetProperty( mRequestionPositionProperty, position );
948 mPopupTailXPosition = position.x;
949 ApplyConfinementConstraint();
950 ApplyTailConstraint();
953 bool TextInputPopup::OnButtonPressed( Toolkit::Button button )
955 mPressedSignal.Emit( button );
959 void TextInputPopup::OnHideFinished(Animation& source)
961 source.FinishedSignal().Disconnect( this, &TextInputPopup::OnHideFinished );
963 mState = StateHidden;
964 mHideFinishedSignal.Emit( *this );
967 void TextInputPopup::OnShowFinished(Animation& source)
969 source.FinishedSignal().Disconnect( this, &TextInputPopup::OnShowFinished );
971 mShowFinishedSignal.Emit( *this );
974 TextInputPopup::PressedSignalV2& TextInputPopup::PressedSignal()
976 return mPressedSignal;
979 TextInputPopup::HideFinishedSignalV2& TextInputPopup::HideFinishedSignal()
981 return mHideFinishedSignal;
984 TextInputPopup::ShowFinishedSignalV2& TextInputPopup::ShowFinishedSignal()
986 return mShowFinishedSignal;
989 } // namespace Internal
991 } // namespace Toolkit