X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=base%2Fdali-toolkit%2Finternal%2Fcontrols%2Ftext-input%2Ftext-input-popup-impl.cpp;h=bd7132e0cc32376ad7aa4ca75dcba64bb79c1962;hp=7d9bf42648c21aa7bb4f07cdcd325bc300079100;hb=05c97b7ff1d90ab7f90cb9d6ec5f060c61b46aab;hpb=e58fa784d19a558e35f458ecf6d262a2344beb4f diff --git a/base/dali-toolkit/internal/controls/text-input/text-input-popup-impl.cpp b/base/dali-toolkit/internal/controls/text-input/text-input-popup-impl.cpp index 7d9bf42..bd7132e 100644 --- a/base/dali-toolkit/internal/controls/text-input/text-input-popup-impl.cpp +++ b/base/dali-toolkit/internal/controls/text-input/text-input-popup-impl.cpp @@ -1,71 +1,68 @@ -// -// Copyright (c) 2014 Samsung Electronics Co., Ltd. -// -// Licensed under the Flora License, Version 1.0 (the License); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://floralicense.org/license/ -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an AS IS BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ #include + #include +#include + +#include using namespace std; using namespace Dali; +#define GET_LOCALE_TEXT(string) dgettext("sys_string", string) + namespace { -// Popup: Background -const char* DEFAULT_PANEL_BACKGROUND = DALI_IMAGE_DIR "cutCopyPastePopup_bg.png"; +// Default Colors -// Popup: Divider -const char* DEFAULT_PANEL_BUTTON_DIVIDER = DALI_IMAGE_DIR "copypanelLine.png"; +const Vector4 DEFAULT_POPUP_BACKGROUND( Vector4( .20f, 0.29f, 0.44f, 1.0f ) ); +const Vector4 DEFAULT_POPUP_BUTTON_PRESSED( Vector4( 0.07f, 0.10f, 0.17f, 1.0f ) ); +const Vector4 DEFAULT_BORDER_COLOR( Vector4( 0.36f, 0.45f, 0.59f, 1.0f ) ); +const Vector3 POPUP_BORDER( Vector3(1.0f, 1.0f, 0.0f) ); /* Functionality in place to have the end buttons using different images to inner button. * Supply a centre image and then a left and right image, the centre image can have straight ends while * 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. */ -// Popup: Left Pressed Highlight -const char* DEFAULT_BUTTON_HIGHLIGHT_LEFT( DALI_IMAGE_DIR "00_popup_button_pressed.png" ); -const Vector4 DEFAULT_BUTTON_HIGHLIGHT_LEFT_BORDER( 6.0f, 9.0f, 6.0f, 9.0f ); - -// Popup: Center Pressed Highlight -const char* DEFAULT_BUTTON_HIGHLIGHT_CENTER( DALI_IMAGE_DIR "00_popup_button_pressed.png" ); -const Vector4 DEFAULT_BUTTON_HIGHLIGHT_CENTER_BORDER( 6.0f, 9.0f, 6.0f, 9.0f ); - -// Popup: Right Pressed Highlight -const char* DEFAULT_BUTTON_HIGHLIGHT_RIGHT( DALI_IMAGE_DIR "00_popup_button_pressed.png" ); -const Vector4 DEFAULT_BUTTON_HIGHLIGHT_RIGHT_BORDER( 6.0f, 9.0f, 6.0f, 9.0f ); - // Popup: Tails -const char* DEFAULT_POPUP_TAIL_BOTTOM( DALI_IMAGE_DIR "00_popup_bubble_tail_bottom.png" ); +const char* DEFAULT_POPUP_TAIL_BOTTOM( DALI_IMAGE_DIR "popup_bubble_tail_bottom.png" ); +const char* DEFAULT_POPUP_TAIL_BOTTOM_OUTLINE( DALI_IMAGE_DIR "popup_bubble_tail_bottom_line.png" ); // Popup: Vertical Constraint // TODO: Remove - this should come from application - it is not possible to get the // height of the indicator actor from Dali-Toolkit. -const Vector2 DEFAULT_POPUP_INDICATOR_OFFSET(0.0f, 60.0f); -const Vector4 BACKGROUND_IMAGE_BORDER( 22.0f, 20.0f, 29.0f, 27.0f ); -const Vector2 BACKGROUND_IMAGE_SIZE( 50.0f, 54.0f ); -const Vector3 POPUP_TEXT_OFFSET( 12.0f, 10.0f, 0.0f ); +const float POP_UP_SCREEN_EDGE_MARGIN( 4.0f ); +const Vector2 DEFAULT_POPUP_INDICATOR_OFFSET(POP_UP_SCREEN_EDGE_MARGIN, 60.0f); + +const Vector3 POPUP_TEXT_OFFSET( 0.0f, 0.0f, 0.0f ); const Vector3 POPUP_TEXT_ENLARGE( 12.0f, 28.0f, 0.0f ); const Vector3 POPUP_MINIMUM_SIZE( 128.0f, 124.0f, 0.0f ); const Vector3 BUTTON_TEXT_ENLARGE( 32.0f, 0.0f, 0.0f ); const Vector3 BUTTON_TEXT_MINIMUM_SIZE( 128.0f, 126.0f, 0.0f ); -const Vector3 BUTTON_TEXT_MAXIMUM_SIZE( 196.0f, 126.0f, 0.0f ); +const Vector3 BUTTON_TEXT_MAXIMUM_SIZE( 190.0f, 126.0f, 0.0f ); const Vector3 TEXT_LABEL_MAX_SIZE( 160.0f, 30.0f, 0.0f ); const float DIVIDER_WIDTH(2.0f); ///< Width of each button divider -const float DIVIDER_MARGIN(10.0f); ///< Top/Bottom Margin between divider and edge of popup. +const float DIVIDER_MARGIN(0.0f); ///< Top/Bottom Margin between divider and edge of popup. const float DEFAULT_UI_FONT_SIZE(7.0f); ///< Standard font size for Text-Input's UI @@ -73,9 +70,16 @@ const float HIDE_POPUP_ANIMATION_DURATION(0.2f); ///< const float SHOW_POPUP_ANIMATION_DURATION(0.2f); ///< Duration of popup show animation in seconds. const Vector2 DEFAULT_ICON_SIZE( 45.0f, 45.0f ); ///< Default icon size for image in options -const float TEXT_POSITION_OFFSET( -19.0f ); ///< Default offset for text label +const float TEXT_POSITION_OFFSET( -19.0f ); ///< Default offset for text label const float ICON_POSITION_OFFSET( 19.0f ); ///< Default offset for icon +const char* DEFAULT_ICON_CLIPBOARD( DALI_IMAGE_DIR "copy_paste_icon_clipboard.png" ); +const char* DEFAULT_ICON_COPY( DALI_IMAGE_DIR "copy_paste_icon_copy.png" ); +const char* DEFAULT_ICON_CUT( DALI_IMAGE_DIR "copy_paste_icon_cut.png" ); +const char* DEFAULT_ICON_PASTE( DALI_IMAGE_DIR "copy_paste_icon_paste.png" ); +const char* DEFAULT_ICON_SELECT( DALI_IMAGE_DIR "copy_paste_icon_select.png" ); +const char* DEFAULT_ICON_SELECT_ALL( DALI_IMAGE_DIR "copy_paste_icon_select_all.png" ); + // TODO: This should be based on the content for example: // 1. For selection: should be above top of highlighted selection, or below bottom of highlighted selection + end handle. // 2. For cursor: should be above top of cursor, or below bottom of cursor + grab handle. @@ -93,14 +97,17 @@ struct ConfinementConstraint * Confinement constraint constructor. * @param[in] topLeftMargin (optional) Top-Left margins (defaults to 0.0f, 0.0f) * @param[in] bottomRightMargin (optional) Bottom-Right margins (defaults to 0.0f, 0.0f) - * @param[in] flipVertical (optional) whether to flip Actor to the other side if near edge, and by - * how much (defaults to 0.0f i.e. no flip) + * @paran[in[ flipHorizontal (optional) whether to flip Actor to other side if near edge + * @param[in] flipVertical (optional) whether to flip Actor to the other side if near edge + * @param[in] boundingRect Rectangle to bound Popup to. + * */ - ConfinementConstraint(Vector2 topLeftMargin = Vector2::ZERO, Vector2 bottomRightMargin = Vector2::ZERO, bool flipHorizontal = false, bool flipVertical = false) + ConfinementConstraint(Vector2 topLeftMargin = Vector2::ZERO, Vector2 bottomRightMargin = Vector2::ZERO, bool flipHorizontal = false, bool flipVertical = false, Rect boundingRect = Rect(0.0f, 0.0f, 0.0f, 0.0f) ) : mMinIndent(topLeftMargin), mMaxIndent(bottomRightMargin), mFlipHorizontal(flipHorizontal), - mFlipVertical(flipVertical) + mFlipVertical(flipVertical), + mBoundingRect( boundingRect ) { } @@ -123,12 +130,25 @@ struct ConfinementConstraint Vector3 position(constPosition + origin * referenceSize); // if top-left corner is outside of Top-Left bounds, then push back in screen. + Vector3 corner(position - size * anchor - mMinIndent); - if(mFlipHorizontal && corner.x < 0.0f) + newPosition.x -= std::max(corner.x, 0.0f); + + if ( mFlipHorizontal ) { - corner.x = 0.0f; - newPosition.x += size.width + alternativeOffset.width; + if( corner.x < mBoundingRect.x + POP_UP_SCREEN_EDGE_MARGIN ) + { + // Snap PopUp to left hand boundary so stays visible + corner.x = mBoundingRect.x + POP_UP_SCREEN_EDGE_MARGIN ; + } + else if ( ( corner.x + size.x ) > ( ( mBoundingRect.x + mBoundingRect.width ) - POP_UP_SCREEN_EDGE_MARGIN )) + { + // Calculate offset from left boundary PopUp must be placed at so it does not exceed right side boundary. + float requiredOffSetFromLeftBoundaryToFit = mBoundingRect.width - POP_UP_SCREEN_EDGE_MARGIN - size.x; + corner.x = mBoundingRect.x + requiredOffSetFromLeftBoundaryToFit - ( origin.x * referenceSize.x ) + ( size.x * anchor.x ); + } + newPosition.x = corner.x; } if(mFlipVertical && corner.y < 0.0f) @@ -137,27 +157,17 @@ struct ConfinementConstraint newPosition.y += size.height + alternativeOffset.height; } - newPosition.x -= std::min(corner.x, 0.0f); newPosition.y -= std::min(corner.y, 0.0f); // if bottom-right corner is outside of Bottom-Right bounds, then push back in screen. corner += size - referenceSize + mMinIndent + mMaxIndent; - if(mFlipHorizontal && corner.x > 0.0f) - { - corner.x = 0.0f; - newPosition.x -= size.width + alternativeOffset.width; - } - if(mFlipVertical && corner.y > 0.0f) { corner.y = 0.0f; newPosition.y -= size.height + alternativeOffset.height; } - newPosition.x -= std::max(corner.x, 0.0f); - newPosition.y -= std::max(corner.y, 0.0f); - return newPosition; } @@ -165,8 +175,38 @@ struct ConfinementConstraint Vector3 mMaxIndent; ///< Bottom-Right Margin. bool mFlipHorizontal; ///< Whether to flip actor's position if exceeds horizontal screen bounds bool mFlipVertical; ///< Whether to flip actor's position if exceeds vertical screen bounds + Rect mBoundingRect; ///< Bounding Rect Popup must stay within +}; + +/** + * Confine actor to the x axis boundaries of reference actor (e.g. Parent) + */ +struct ParentXAxisConstraint +{ + /** + * Confinement constraint constructor. + */ + ParentXAxisConstraint( float handlesMidPoint = 0.0f ) + : mHandlesMidPoint( handlesMidPoint ) + { + } + + float operator()( const float constXPosition, + const PropertyInput& localWidthProperty, + const PropertyInput& anchorPointXProperty ) + { + const float size = localWidthProperty.GetFloat(); + const float anchor = anchorPointXProperty.GetFloat(); + + float newPosition = Clamp( mHandlesMidPoint, constXPosition - size * anchor , constXPosition + size * anchor); + + return newPosition; + } + + float mHandlesMidPoint; }; + } // unnamed namespace namespace Dali @@ -182,9 +222,27 @@ const char* const TextInputPopup::SIGNAL_PRESSED = "pressed"; const char* const TextInputPopup::SIGNAL_HIDE_FINISHED = "hide-finished"; const char* const TextInputPopup::SIGNAL_SHOW_FINISHED = "show-finished"; +const char* const TextInputPopup::OPTION_SELECT_WORD = "option-select_word"; // "Select Word" popup option. +const char* const TextInputPopup::OPTION_SELECT_ALL("option-select_all"); // "Select All" popup option. +const char* const TextInputPopup::OPTION_CUT("option-cut"); // "Cut" popup option. +const char* const TextInputPopup::OPTION_COPY("option-copy"); // "Copy" popup option. +const char* const TextInputPopup::OPTION_PASTE("option-paste"); // "Paste" popup option. +const char* const TextInputPopup::OPTION_CLIPBOARD("option-clipboard"); // "Clipboard" popup option. + TextInputPopup::TextInputPopup() : mState(StateHidden), mRootActor(Layer::New()), + mPopupTailXPosition( 0.0f ), + mContentSize( Vector3::ZERO ), + mCutPasteButtonsColor( DEFAULT_POPUP_BACKGROUND ), + mCutPasteButtonsPressedColor( DEFAULT_POPUP_BUTTON_PRESSED ), + mBorderColor( DEFAULT_BORDER_COLOR ), + mSelectOptionPriority(1), + mSelectAllOptionPriority(2), + mCutOptionPriority(3), + mCopyOptionPriority(4), + mPasteOptionPriority(5), + mClipboardOptionPriority(6), mPressedSignal(), mHideFinishedSignal(), mShowFinishedSignal() @@ -220,11 +278,70 @@ void TextInputPopup::ApplyConfinementConstraint() LocalSource( mAlternativeOffsetProperty ), ConfinementConstraint( DEFAULT_POPUP_INDICATOR_OFFSET, Vector2::ZERO, - false, - true) ); + true, + true, mBoundingRect ) ); mRootActor.ApplyConstraint(constraint); } +void TextInputPopup::ApplyTailConstraint() +{ + mTail.RemoveConstraints(); + Constraint constraint = Constraint::New( Actor::POSITION_X, + LocalSource( Actor::SIZE_WIDTH ), + LocalSource( Actor::ANCHOR_POINT_X ), + ParentXAxisConstraint()); +} + +void TextInputPopup::CreateLayer( const Vector2& size ) +{ + mLayer = Layer::New(); + mLayer.SetParentOrigin(ParentOrigin::CENTER); + mLayer.SetAnchorPoint(AnchorPoint::CENTER); + mLayer.SetSize( size ); // matches stencil size + mLayer.SetName("popup-mLayer"); +} + +void TextInputPopup::CreateStencil( const Vector2& size ) +{ + mStencil = CreateSolidColorActor( Color::BLUE ); + mStencil.SetParentOrigin( Vector3( ParentOrigin::CENTER ) ); + mStencil.SetAnchorPoint( AnchorPoint::CENTER ); + mStencil.SetDrawMode( DrawMode::STENCIL ); + mStencil.SetSize( size ); // slightly smaller than layer and stencil so over shoot always inside. + mStencil.SetVisible( true ); + mStencil.SetName("popup-stencil"); +} + +void TextInputPopup::OnScrollStarted( const Vector3& position ) +{ + mBackground.SetSensitive( false ); +} + +void TextInputPopup::OnScrollCompleted( const Vector3& position ) +{ + mBackground.SetSensitive( true ); +} + +void TextInputPopup::CreateScrollView( const Vector2& domainSize, const Vector2& visibleSize ) +{ + mScrollView = Toolkit::ScrollView::New(); + mScrollView.SetName("popup-scroll-view"); + mScrollView.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + mScrollView.SetParentOrigin( ParentOrigin::TOP_LEFT ); + mScrollView.SetSize( visibleSize.x, visibleSize.y ); + mScrollView.SetScrollingDirection( PanGestureDetector::DIRECTION_HORIZONTAL, Degree( 40.0f ) ); + mScrollView.SetAxisAutoLock( true ); + mScrollView.ScrollStartedSignal().Connect( this, &TextInputPopup::OnScrollStarted ); + mScrollView.ScrollCompletedSignal().Connect( this, &TextInputPopup::OnScrollCompleted ); + + RulerPtr rulerX = new DefaultRuler(); // IntrusivePtr which is unreferenced when ScrollView is destroyed. + RulerPtr rulerY = new DefaultRuler(); // IntrusivePtr which is unreferenced when ScrollView is destroyed. + rulerY->Disable(); + rulerX->SetDomain( RulerDomain( 0, domainSize.width, true ) ); + mScrollView.SetRulerX(rulerX); + mScrollView.SetRulerY(rulerY); +} + void TextInputPopup::RemoveFromStage() { Actor rootActor = Self(); @@ -235,8 +352,11 @@ void TextInputPopup::Clear() { if ( mBackground ) { - mRootActor.Remove( mBackground ); - mBackground.Reset(); + UnparentAndReset( mTail ); + UnparentAndReset( mStencil ); + UnparentAndReset( mBackground ); + UnparentAndReset( mScrollView ); + UnparentAndReset( mLayer ); mButtonContainer.clear(); mDividerContainer.clear(); @@ -276,31 +396,31 @@ void TextInputPopup::CreatePopUpBackground() // Create background-panel if not already created (required if we have at least one option) if ( !mBackground ) { - Image backgroundImage = Image::New( DEFAULT_PANEL_BACKGROUND ); - - mBackground = ImageActor::New( backgroundImage ); - // Expand background from bottom-center of root actor. - mBackground.SetParentOrigin( ParentOrigin::BOTTOM_CENTER ); - mBackground.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER ); - mBackground.SetStyle( ImageActor::STYLE_NINE_PATCH ); - - mBackground.SetNinePatchBorder( Vector4(13.0f, 13.0f, 13.0f, 13.0f) ); - - Self().Add( mBackground ); + mBackground = Toolkit::CreateSolidColorActor( GetCutPastePopUpColor(), true, mBorderColor ); + mBackground.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + mBackground.SetParentOrigin( ParentOrigin::TOP_LEFT ); + mBackground.SetName("pop-up-background"); mContentSize = POPUP_TEXT_OFFSET; - Hide(false); AddToStage(); // Add Tail too. Image tailImage = Image::New( DEFAULT_POPUP_TAIL_BOTTOM ); + Image tailImageOutline = Image::New( DEFAULT_POPUP_TAIL_BOTTOM_OUTLINE ); + + mTailOutline = ImageActor::New ( tailImageOutline ); + mTailOutline.SetParentOrigin( ParentOrigin::CENTER ); + mTailOutline.SetAnchorPoint( AnchorPoint::CENTER ); + mTailOutline.ApplyConstraint( Constraint::New( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) ); mTail = ImageActor::New( tailImage ); mTail.SetParentOrigin( ParentOrigin::BOTTOM_CENTER ); mTail.SetAnchorPoint( AnchorPoint::TOP_CENTER ); - mBackground.Add( mTail ); // TODO: Make tail visible, and positioned in relation to original intended position of popup (i.e. before constrained effects) - mTail.SetVisible(false); + mTail.SetVisible(true); + mTail.SetColor( mCutPasteButtonsColor ); + mTailOutline.SetColor( mBorderColor ); + mTail.Add( mTailOutline); } } @@ -308,51 +428,124 @@ void TextInputPopup::CreateDivider() { if(mButtonContainer.size() > 0) { - Image dividerImage = Image::New( DEFAULT_PANEL_BUTTON_DIVIDER ); - ImageActor divider = ImageActor::New( dividerImage ); + ImageActor divider = Toolkit::CreateSolidColorActor( mBorderColor ); divider.SetParentOrigin( ParentOrigin::TOP_LEFT ); divider.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - divider.SetPosition( Vector3( mContentSize.width, POPUP_TEXT_OFFSET.y + 5.0f, 0.0f ) ); + divider.SetPosition( Vector3( mContentSize.width, POPUP_TEXT_OFFSET.y, 0.0f ) ); // Keep track of all the dividers. As their height's need to be updated to the max. of all // buttons currently added. mDividerContainer.push_back(divider); - mBackground.Add( divider ); mContentSize.width += DIVIDER_WIDTH; } } -ImageActor TextInputPopup::CreatePressedBackground( const Vector3 requiredSize, const bool finalFlag ) +ImageActor TextInputPopup::CreatePressedBackground( const Vector3 requiredSize ) { std::string pressedImageFilename; Vector4 pressedImageBorder; Vector2 pressedImageSize; - if(mButtonContainer.size() == 0) // LEFT - { - pressedImageFilename = DEFAULT_BUTTON_HIGHLIGHT_LEFT; - pressedImageBorder = DEFAULT_BUTTON_HIGHLIGHT_LEFT_BORDER; - } - else if(!finalFlag) // CENTER - { - pressedImageFilename = DEFAULT_BUTTON_HIGHLIGHT_CENTER; - pressedImageBorder = DEFAULT_BUTTON_HIGHLIGHT_CENTER_BORDER; - } - else // RIGHT + ImageActor pressedButtonBg = Toolkit::CreateSolidColorActor( GetCutPastePopUpPressedColor() ); + + pressedButtonBg.SetSize ( requiredSize ); + pressedButtonBg.SetParentOrigin( ParentOrigin::CENTER ); + pressedButtonBg.SetAnchorPoint( AnchorPoint::CENTER ); + + return pressedButtonBg; +} + +TextInputPopup::ButtonRequirement TextInputPopup::CreateRequiredButton( TextInputPopup::Buttons buttonId, std::size_t orderOfPriority, + const std::string& name, const std::string& caption, Image iconImage, bool enabled ) +{ + TextInputPopup::ButtonRequirement currentButton; + + currentButton.buttonId = buttonId; + currentButton.orderOfPriority = orderOfPriority; + currentButton.name = name; + currentButton.caption = caption; + currentButton.iconImage = iconImage; + currentButton.enabled = enabled; + + return currentButton; +} + +void TextInputPopup::CreateOrderedListOfOptions() +{ + mOrderListOfButtons.clear(); + + for ( std::size_t index= 0; index < ButtonsEnumEnd; index++ ) { - pressedImageFilename = DEFAULT_BUTTON_HIGHLIGHT_RIGHT; - pressedImageBorder = DEFAULT_BUTTON_HIGHLIGHT_RIGHT_BORDER; - } + TextInputPopup::ButtonRequirement currentButton; + + // Create button for each possible option using Option priority + switch ( index ) + { + case ButtonsCut: + { + Image cutIcon = Image::New( DEFAULT_ICON_CUT ); + currentButton = CreateRequiredButton( ButtonsCut, mCutOptionPriority, OPTION_CUT, GET_LOCALE_TEXT("IDS_COM_BODY_CUT"), cutIcon, false ); + break; + } + case ButtonsCopy: + { + Image copyIcon = Image::New( DEFAULT_ICON_COPY ); + currentButton = CreateRequiredButton( ButtonsCopy, mCopyOptionPriority, OPTION_COPY, GET_LOCALE_TEXT("IDS_COM_BODY_COPY"), copyIcon, false ); + break; + } + case ButtonsPaste: + { + Image pasteIcon = Image::New( DEFAULT_ICON_PASTE ); + currentButton = CreateRequiredButton( ButtonsPaste, mPasteOptionPriority, OPTION_PASTE, GET_LOCALE_TEXT("IDS_COM_BODY_PASTE"), pasteIcon, false ); + break; + } + case ButtonsSelect: + { + Image selectIcon = Image::New( DEFAULT_ICON_SELECT ); + currentButton = CreateRequiredButton( ButtonsSelect, mSelectOptionPriority, OPTION_SELECT_WORD, GET_LOCALE_TEXT("IDS_COM_SK_SELECT"), selectIcon, false ); + break; + } + case ButtonsSelectAll: + { + Image selectAllIcon = Image::New( DEFAULT_ICON_SELECT_ALL ); + currentButton = CreateRequiredButton( ButtonsSelectAll, mSelectAllOptionPriority, OPTION_SELECT_ALL, GET_LOCALE_TEXT("IDS_COM_BODY_SELECT_ALL"), selectAllIcon, false ); + break; + } + case ButtonsClipboard: + { + Image clipboardIcon = Image::New( DEFAULT_ICON_CLIPBOARD ); + currentButton = CreateRequiredButton( ButtonsClipboard, mClipboardOptionPriority, OPTION_CLIPBOARD, GET_LOCALE_TEXT("IDS_COM_BODY_CLIPBOARD"), clipboardIcon, false ); + break; + } + case ButtonsEnumEnd: + { + DALI_ASSERT_DEBUG( "ButtonsEnumEnd used but an invalid choice"); + currentButton.orderOfPriority = 0; + break; + } + } - Image pressedImage = Image::New( pressedImageFilename ); - ImageActor pressedImageBg = ImageActor::New( pressedImage ); - pressedImageBg.SetStyle( ImageActor::STYLE_NINE_PATCH ); - pressedImageBg.SetNinePatchBorder( pressedImageBorder ); - pressedImageBg.SetSize ( requiredSize ); - pressedImageBg.SetParentOrigin( ParentOrigin::CENTER ); - pressedImageBg.SetAnchorPoint( AnchorPoint::CENTER ); + bool match = false; - return pressedImageBg; + // Insert button in list of buttons in order of priority setting. + for( std::vector::iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt && !match ); ++it ) + { + const ButtonRequirement& button( *it ); + if ( currentButton.orderOfPriority < button.orderOfPriority ) + { + if ( currentButton.orderOfPriority != 0 ) // If order priority 0 then do not add button as not required. + { + mOrderListOfButtons.insert( it, currentButton ); + } + match = true; + } + } + + if ( !match) + { + mOrderListOfButtons.push_back( currentButton ); + } + } } void TextInputPopup::AddOption(const std::string& name, const std::string& caption, const Image iconImage, bool finalOption) @@ -387,12 +580,12 @@ void TextInputPopup::AddOption(const std::string& name, const std::string& capti const Vector3 constrainedTextSize = Min( textSize, TEXT_LABEL_MAX_SIZE ); Vector3 buttonSize( Max(constrainedTextSize + BUTTON_TEXT_ENLARGE, BUTTON_TEXT_MINIMUM_SIZE) ); buttonSize = ( Min(buttonSize, BUTTON_TEXT_MAXIMUM_SIZE) ); - label.SetSize( Min( buttonSize + BUTTON_TEXT_ENLARGE, constrainedTextSize ) ); + label.SetSize( Min( buttonSize, constrainedTextSize ) ); button.SetParentOrigin( ParentOrigin::TOP_LEFT ); button.SetAnchorPoint( AnchorPoint::TOP_LEFT ); button.SetSize( buttonSize ); - button.SetPosition( Vector3( mContentSize.width, POPUP_TEXT_OFFSET.y, 0.0f ) ); + button.SetPosition( Vector3( mContentSize.width, POPUP_BORDER.y, 0.0f ) ); // 2. Add icon ImageActor icon = CreateOptionIcon( iconImage ); @@ -400,7 +593,7 @@ void TextInputPopup::AddOption(const std::string& name, const std::string& capti iconTextContainer.Add( icon ); // 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. - ImageActor pressedImageBg = CreatePressedBackground( buttonSize, finalOption ); + ImageActor pressedImageBg = CreatePressedBackground( buttonSize ); Actor iconPressedTextContainer = Actor::New(); iconPressedTextContainer.SetDrawMode( DrawMode::OVERLAY ); @@ -424,7 +617,7 @@ void TextInputPopup::AddOption(const std::string& name, const std::string& capti // Update content size (represents size of all content i.e. from top-left of first button, to bottom-right of last button) mContentSize.width += buttonSize.width; - mContentSize.height = std::max(mContentSize.height, buttonSize.height); + mContentSize.height = std::max(mContentSize.height + ( POPUP_BORDER.y ), buttonSize.height); mButtonContainer.push_back(button); // resize all dividers based on the height content (i.e. max of all button heights) @@ -433,20 +626,12 @@ void TextInputPopup::AddOption(const std::string& name, const std::string& capti { i->SetSize( DIVIDER_WIDTH, dividerHeight ); } - - Vector3 popupSize( Max(mContentSize + POPUP_TEXT_ENLARGE, POPUP_MINIMUM_SIZE) ); - - mBackground.SetSize( popupSize ); - // Make Root Actor reflect the size of its content - mRootActor.SetSize( popupSize ); - mTail.SetPosition(Vector3(0.0f, -20.0f, 0.0f)); - button.ClickedSignal().Connect( this, &TextInputPopup::OnButtonPressed ); } void TextInputPopup::Hide(bool animate) { - if(mBackground) + if( mRootActor ) { if(mAnimation) { @@ -457,8 +642,8 @@ void TextInputPopup::Hide(bool animate) if(animate) { mAnimation = Animation::New( HIDE_POPUP_ANIMATION_DURATION ); - mAnimation.AnimateTo( Property(mBackground, Actor::SCALE), Vector3::ZERO, AlphaFunctions::EaseOut ); - mAnimation.AnimateTo( Property(mBackground, Actor::COLOR_ALPHA), 0.0f, AlphaFunctions::EaseOut ); + mAnimation.AnimateTo( Property(mRootActor, Actor::SCALE), Vector3::ZERO, AlphaFunctions::EaseOut ); + mAnimation.AnimateTo( Property(mRootActor, Actor::COLOR_ALPHA), 0.0f, AlphaFunctions::EaseOut ); mAnimation.Play(); mAnimation.FinishedSignal().Connect( this, &TextInputPopup::OnHideFinished ); @@ -466,8 +651,8 @@ void TextInputPopup::Hide(bool animate) } else { - mBackground.SetProperty(Actor::SCALE, Vector3::ZERO); - mBackground.SetProperty(Actor::COLOR_ALPHA, 0.0f); + mRootActor.SetProperty(Actor::SCALE, Vector3::ZERO); + mRootActor.SetProperty(Actor::COLOR_ALPHA, 0.0f); mState = StateHidden; } } @@ -475,8 +660,12 @@ void TextInputPopup::Hide(bool animate) void TextInputPopup::Show(bool animate) { - if(mBackground) + if( mRootActor ) { + mRootActor.SetSensitive( true ); + + mTail.SetPosition(Vector3( mPopupTailXPosition, 0.0f, 0.0f)); + if(mAnimation) { mAnimation.Clear(); @@ -486,8 +675,8 @@ void TextInputPopup::Show(bool animate) if(animate) { mAnimation = Animation::New( SHOW_POPUP_ANIMATION_DURATION ); - mAnimation.AnimateTo( Property(mBackground, Actor::SCALE), Vector3::ONE, AlphaFunctions::EaseOut ); - mAnimation.AnimateTo( Property(mBackground, Actor::COLOR_ALPHA), 1.0f, AlphaFunctions::EaseOut ); + mAnimation.AnimateTo( Property(mRootActor, Actor::SCALE), Vector3::ONE, AlphaFunctions::EaseOut ); + mAnimation.AnimateTo( Property(mRootActor, Actor::COLOR_ALPHA), 1.0f, AlphaFunctions::EaseOut ); mAnimation.Play(); mAnimation.FinishedSignal().Connect( this, &TextInputPopup::OnShowFinished ); @@ -495,8 +684,8 @@ void TextInputPopup::Show(bool animate) } else { - mBackground.SetProperty(Actor::SCALE, Vector3::ONE); - mBackground.SetProperty(Actor::COLOR_ALPHA, 1.0f); + mRootActor.SetProperty(Actor::SCALE, Vector3::ONE); + mRootActor.SetProperty(Actor::COLOR_ALPHA, 1.0f); mState = StateShown; } } @@ -518,6 +707,174 @@ Actor TextInputPopup::GetRootActor() const return mRootActor; } +// Styling + +void TextInputPopup::SetCutPastePopUpColor( const Vector4& color ) +{ + mCutPasteButtonsColor = color; +} + +const Vector4& TextInputPopup::GetCutPastePopUpColor() const +{ + return mCutPasteButtonsColor; +} + +void TextInputPopup::SetCutPastePopUpPressedColor( const Vector4& color ) +{ + mCutPasteButtonsPressedColor = color; +} + +const Vector4& TextInputPopup::GetCutPastePopUpPressedColor() const +{ + return mCutPasteButtonsPressedColor; +} + +void TextInputPopup::TogglePopUpButtonOnOff( TextInputPopup::Buttons requiredButton, bool enable ) +{ + bool match ( false ); + for( std::vector::iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt && !match ); ++it ) + { + ButtonRequirement& button( *it ); + if ( requiredButton == button.buttonId ) + { + button.enabled = enable; + match = true; + } + } +} + +void TextInputPopup::SetButtonPriorityPosition( TextInputPopup::Buttons button, unsigned int priority ) +{ + switch ( button ) + { + case ButtonsCut: + { + mCutOptionPriority = priority; + break; + } + case ButtonsCopy: + { + mCopyOptionPriority = priority; + break; + } + case ButtonsPaste: + { + mPasteOptionPriority = priority; + break; + } + case ButtonsSelect: + { + mSelectOptionPriority = priority; + break; + } + case ButtonsSelectAll: + { + mSelectAllOptionPriority = priority; + break; + } + case ButtonsClipboard: + { + mClipboardOptionPriority = priority; + break; + } + case ButtonsEnumEnd: + { + DALI_ASSERT_DEBUG( "ButtonsEnumEnd used but an invalid choice"); + break; + } + } + CreateOrderedListOfOptions(); // Update list of options as priority changed. +} + +unsigned int TextInputPopup::GetButtonPriorityPosition( TextInputPopup::Buttons button ) const +{ + unsigned int priority = 0; + + switch ( button ) + { + case ButtonsCut: + { + priority = mCutOptionPriority; + break; + } + case ButtonsCopy: + { + priority = mCopyOptionPriority; + break; + } + case ButtonsPaste: + { + priority = mPasteOptionPriority; + break; + } + case ButtonsSelect: + { + priority = mSelectOptionPriority; + break; + } + case ButtonsSelectAll: + { + priority = mSelectAllOptionPriority; + break; + } + case ButtonsClipboard: + { + priority = mClipboardOptionPriority; + break; + } + case ButtonsEnumEnd: + { + DALI_ASSERT_DEBUG( "ButtonsEnumEnd used but an invalid choice"); + break; + } + } + + return priority; +} + +void TextInputPopup::AddPopupOptions() +{ + for( std::vector::const_iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt ); ++it ) + { + const ButtonRequirement& button( *it ); + if ( button.enabled ) + { + AddOption( button.name, button.caption, button.iconImage, false ); + } + } + + float visiblePopUpWidth = std::min( mContentSize.width - POP_UP_SCREEN_EDGE_MARGIN*2 , mBoundingRect.width - POP_UP_SCREEN_EDGE_MARGIN *2); + float visbilePopUpHeight = std::max( mContentSize.height, POPUP_MINIMUM_SIZE.height ); + Vector2 visiblePopUpSize = Vector2( visiblePopUpWidth, visbilePopUpHeight ); + + visiblePopUpWidth = std::max( visiblePopUpWidth, POPUP_MINIMUM_SIZE.width ); + + mBackground.SetSize( mContentSize.width, mContentSize.height ); + mRootActor.SetSize( visiblePopUpWidth, visbilePopUpHeight ); // Make Root Actor reflect the size of its content + + CreateLayer( visiblePopUpSize ); + CreateStencil( visiblePopUpSize ); + CreateScrollView( Vector2( mContentSize.width, mContentSize.height ), visiblePopUpSize ); + + mLayer.Add( mStencil ); + mLayer.Add( mScrollView ); + mScrollView.Add( mBackground ); + mRootActor.Add( mTail ); + + Self().Add(mLayer); +} + +void TextInputPopup::SetPopupBoundary( const Rect& boundingRectangle ) +{ + mBoundingRect = boundingRectangle; +} + +void TextInputPopup::SetTailPosition( const Vector3& position ) +{ + mPopupTailXPosition = position.x; + ApplyTailConstraint(); +} + bool TextInputPopup::OnButtonPressed( Toolkit::Button button ) { mPressedSignal.Emit( button ); @@ -559,3 +916,4 @@ TextInputPopup::ShowFinishedSignalV2& TextInputPopup::ShowFinishedSignal() } // namespace Toolkit } // namespace Dali +