X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fcontrols%2Fpopup%2Fpopup-impl.cpp;h=e59dc0cbd623fbcc95a328001efa5f9425baf1bf;hp=cc7ae5d67b745dd9b9e4d272198ea11153471069;hb=4107c0f5ea45cd9e4e61d30c30e99de0e00287fc;hpb=8ad943a28e16767f5fe2fc92d18b38f8808bdc99 diff --git a/dali-toolkit/internal/controls/popup/popup-impl.cpp b/dali-toolkit/internal/controls/popup/popup-impl.cpp index cc7ae5d..e59dc0c 100755 --- a/dali-toolkit/internal/controls/popup/popup-impl.cpp +++ b/dali-toolkit/internal/controls/popup/popup-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Copyright (c) 2016 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. @@ -21,14 +21,13 @@ // EXTERNAL INCLUDES #include // for strcmp #include -#include +#include #include #include #include #include #include -#include -#include +#include #include #include #include @@ -36,7 +35,7 @@ // INTERNAL INCLUDES #include #include -#include +#include #include #include @@ -70,7 +69,7 @@ const Vector3 DEFAULT_TOAST_BOTTOM_PARENT_ORIGIN( 0.5f, 0.94f, 0.5f ); const Vector3 DEFAULT_TOAST_WIDTH_OF_STAGE_RATIO( 0.75f, 0.75f, 0.75f ); ///< Amount of the stage's width that the toast popup will take up. /** - * Creation function for named type "popup-toast". + * Creation function for named type "popupToast". * @return Handle to the new toast popup object. */ BaseHandle CreateToast() @@ -108,46 +107,47 @@ BaseHandle CreateToast() DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Popup, Toolkit::Control, Create ) // Main content related properties. -DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "title", MAP, TITLE ) -DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "content", MAP, CONTENT ) -DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "footer", MAP, FOOTER ) -DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "display-state", STRING, DISPLAY_STATE ) -DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "touch-transparent", BOOLEAN, TOUCH_TRANSPARENT ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "title", MAP, TITLE ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "content", MAP, CONTENT ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "footer", MAP, FOOTER ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "displayState", STRING, DISPLAY_STATE ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "touchTransparent", BOOLEAN, TOUCH_TRANSPARENT ) // Contextual related properties. -DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tail-visibility", BOOLEAN, TAIL_VISIBILITY ) -DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tail-position", VECTOR3, TAIL_POSITION ) -DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "contextual-mode", STRING, CONTEXTUAL_MODE ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tailVisibility", BOOLEAN, TAIL_VISIBILITY ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tailPosition", VECTOR3, TAIL_POSITION ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "contextualMode", STRING, CONTEXTUAL_MODE ) // Animation related properties. -DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "animation-duration", FLOAT, ANIMATION_DURATION ) -DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "animation-mode", STRING, ANIMATION_MODE ) -DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "entry-animation", MAP, ENTRY_ANIMATION ) -DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "exit-animation", MAP, EXIT_ANIMATION ) -DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "auto-hide-delay", INTEGER, AUTO_HIDE_DELAY ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "animationDuration", FLOAT, ANIMATION_DURATION ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "animationMode", STRING, ANIMATION_MODE ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "entryAnimation", MAP, ENTRY_ANIMATION ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "exitAnimation", MAP, EXIT_ANIMATION ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "autoHideDelay", INTEGER, AUTO_HIDE_DELAY ) // Style related properties. -DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "backing-enabled", BOOLEAN, BACKING_ENABLED ) -DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "backing-color", VECTOR4, BACKING_COLOR ) -DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "popup-background-image", STRING, POPUP_BACKGROUND_IMAGE ) -DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tail-up-image", STRING, TAIL_UP_IMAGE ) -DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tail-down-image", STRING, TAIL_DOWN_IMAGE ) -DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tail-left-image", STRING, TAIL_LEFT_IMAGE ) -DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tail-right-image", STRING, TAIL_RIGHT_IMAGE ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "backingEnabled", BOOLEAN, BACKING_ENABLED ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "backingColor", VECTOR4, BACKING_COLOR ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "popupBackgroundImage", STRING, POPUP_BACKGROUND_IMAGE ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "popupBackgroundBorder", RECTANGLE, POPUP_BACKGROUND_BORDER ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tailUpImage", STRING, TAIL_UP_IMAGE ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tailDownImage", STRING, TAIL_DOWN_IMAGE ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tailLeftImage", STRING, TAIL_LEFT_IMAGE ) +DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tailRightImage", STRING, TAIL_RIGHT_IMAGE ) // Signals. -DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "touched-outside", SIGNAL_TOUCHED_OUTSIDE ) -DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "showing", SIGNAL_SHOWING ) -DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "shown", SIGNAL_SHOWN ) -DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "hiding", SIGNAL_HIDING ) -DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "hidden", SIGNAL_HIDDEN ) +DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "touchedOutside", SIGNAL_TOUCHED_OUTSIDE ) +DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "showing", SIGNAL_SHOWING ) +DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "shown", SIGNAL_SHOWN ) +DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "hiding", SIGNAL_HIDING ) +DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "hidden", SIGNAL_HIDDEN ) DALI_TYPE_REGISTRATION_END() // Named type registration. // Toast Popup: Non-modal popup that displays information at the bottom of the screen. -TypeRegistration typeRegistrationToast( "popup-toast", typeid( Toolkit::Popup ), CreateToast ); +TypeRegistration typeRegistrationToast( "PopupToast", typeid( Toolkit::Popup ), CreateToast ); // Enumeration to / from string conversion tables @@ -192,7 +192,7 @@ const char* DEFAULT_TAIL_LEFT_IMAGE_PATH = DALI_IMAGE_DIR "popup_tail_lef const char* DEFAULT_TAIL_RIGHT_IMAGE_PATH = DALI_IMAGE_DIR "popup_tail_right.png"; ///< Tail right image. const Vector4 DEFAULT_BACKING_COLOR( 0.0f, 0.0f, 0.0f, 0.5f ); ///< Color of the dimmed backing. -const Vector3 BACKGROUND_OUTER_BORDER( 40.0f, 30.0f, 0.0f ); ///< External border. +const Rect DEFAULT_BACKGROUND_BORDER( 17, 17, 13, 13 ); ///< Default border of the background. const Rect DEFAULT_TITLE_PADDING( 20.0f, 20.0f, 20.0f, 20.0f ); ///< Title padding used on popups with content and/or controls (from Tizen GUI UX). const Rect DEFAULT_TITLE_ONLY_PADDING( 8.0f, 8.0f, 8.0f, 8.0f ); ///< Title padding used on popups with a title only (like toast popups). const Vector3 FOOTER_SIZE( 620.0f, 96.0f,0.0f ); ///< Default size of the bottom control area. @@ -220,22 +220,40 @@ Dali::Toolkit::Popup Popup::New() } Popup::Popup() -: Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ), - // Main variables: +: Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ), + mTouchedOutsideSignal(), + mShowingSignal(), + mShownSignal(), + mHidingSignal(), + mHiddenSignal(), + mLayer(), + mPopupLayout(), + mBacking(), + mPreviousFocusedActor(), + mTailImage(), + mPopupContainer(), + mAnimation(), mAlterAddedChild( false ), mLayoutDirty( true ), + mAutoHideTimer(), mTouchTransparent( false ), - - // Property variables: + mTitle(), + mContent(), + mFooter(), mDisplayState( Toolkit::Popup::HIDDEN ), // Hidden until shown with SetDisplayState() mTailVisible( false ), mTailPosition( DEFAULT_TAIL_POSITION ), mContextualMode( Toolkit::Popup::NON_CONTEXTUAL ), mAnimationDuration( DEFAULT_POPUP_ANIMATION_DURATION ), mAnimationMode( Toolkit::Popup::FADE ), + mEntryAnimationData(), + mExitAnimationData(), mAutoHideDelay( 0 ), mBackingEnabled( true ), mBackingColor( DEFAULT_BACKING_COLOR ), + mPopupBackgroundImage(), + mBackgroundBorder( DEFAULT_BACKGROUND_BORDER ), + mMargin(), mTailUpImage( DEFAULT_TAIL_UP_IMAGE_PATH ), mTailDownImage( DEFAULT_TAIL_DOWN_IMAGE_PATH ), mTailLeftImage( DEFAULT_TAIL_LEFT_IMAGE_PATH ), @@ -259,7 +277,7 @@ void Popup::OnInitialize() // Create a new layer so all Popup components can appear above all other actors. mLayer = Layer::New(); - mLayer.SetName( "popup-layer" ); + mLayer.SetName( "popupLayer" ); mLayer.SetParentOrigin( ParentOrigin::CENTER ); mLayer.SetAnchorPoint( AnchorPoint::CENTER ); @@ -273,10 +291,11 @@ void Popup::OnInitialize() self.Add( mLayer ); // Add Backing (Dimmed effect). - mLayer.Add( CreateBacking() ); + mBacking = CreateBacking(); + mLayer.Add( mBacking ); mPopupContainer = Actor::New(); - mPopupContainer.SetName( "popup-container" ); + mPopupContainer.SetName( "popupContainer" ); mPopupContainer.SetParentOrigin( ParentOrigin::CENTER ); mPopupContainer.SetAnchorPoint( AnchorPoint::CENTER ); mPopupContainer.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS ); @@ -286,9 +305,9 @@ void Popup::OnInitialize() mPopupLayout = Toolkit::TableView::New( 3, 1 ); // Adds the default background image. - SetPopupBackgroundImage( ImageActor::New( ResourceImage::New( DEFAULT_BACKGROUND_IMAGE_PATH ) ) ); + SetPopupBackgroundImage( Toolkit::ImageView::New( DEFAULT_BACKGROUND_IMAGE_PATH ) ); - mPopupLayout.SetName( "popup-layout-table" ); + mPopupLayout.SetName( "popupLayoutTable" ); mPopupLayout.SetParentOrigin( ParentOrigin::CENTER ); mPopupLayout.SetAnchorPoint( AnchorPoint::CENTER ); @@ -299,15 +318,13 @@ void Popup::OnInitialize() mPopupLayout.SetFitHeight( 0 ); // Set row to fit. mPopupLayout.SetFitHeight( 1 ); // Set row to fit. - mPopupLayout.TouchedSignal().Connect( this, &Popup::OnDialogTouched ); + mPopupLayout.TouchSignal().Connect( this, &Popup::OnDialogTouched ); mPopupContainer.Add( mPopupLayout ); // Any content after this point which is added to Self() will be re-parented to mContent. mAlterAddedChild = true; - // Make self keyboard focusable and a focus group. - self.SetKeyboardFocusable( true ); SetAsKeyboardFocusGroup( true ); } @@ -458,11 +475,13 @@ void Popup::StartTransitionAnimation( bool transitionIn, bool instantaneous /* f // This is set up last so that different animation modes can have an effect on the backing animation speed. if( mBackingEnabled ) { + // Use the alpha from the user-specified color. + float targetAlpha = mBackingColor.a; if( duration > Math::MACHINE_EPSILON_0 ) { if( transitionIn ) { - mAnimation.AnimateTo( Property( mBacking, Actor::Property::COLOR_ALPHA ), 1.0f, AlphaFunction::EASE_IN_OUT, TimePeriod( 0.0f, duration * 0.70f ) ); + mAnimation.AnimateTo( Property( mBacking, Actor::Property::COLOR_ALPHA ), targetAlpha, AlphaFunction::EASE_IN_OUT, TimePeriod( 0.0f, duration * 0.70f ) ); } else { @@ -471,7 +490,7 @@ void Popup::StartTransitionAnimation( bool transitionIn, bool instantaneous /* f } else { - mBacking.SetOpacity( transitionIn ? 1.0f : 0.0f ); + mBacking.SetProperty( Actor::Property::COLOR_ALPHA, transitionIn ? targetAlpha : 0.0f ); } } @@ -549,27 +568,35 @@ void Popup::SetPopupBackgroundImage( Actor image ) // Removes any previous background. if( mPopupBackgroundImage ) { - mPopupContainer.Remove( mPopupBackgroundImage ); + mPopupBackgroundImage.Unparent(); + if( mTailImage ) + { + mTailImage.Unparent(); + } } // Adds new background to the dialog. mPopupBackgroundImage = image; - mPopupBackgroundImage.SetName( "popup-background-image" ); + mPopupBackgroundImage.SetName( "popupBackgroundImage" ); mPopupBackgroundImage.SetAnchorPoint( AnchorPoint::CENTER ); mPopupBackgroundImage.SetParentOrigin( ParentOrigin::CENTER ); // OnDialogTouched only consumes the event. It prevents the touch event to be caught by the backing. - mPopupBackgroundImage.TouchedSignal().Connect( this, &Popup::OnDialogTouched ); + mPopupBackgroundImage.TouchSignal().Connect( this, &Popup::OnDialogTouched ); // Set the popup border to be slightly larger than the layout contents. - mPopupBackgroundImage.SetResizePolicy( ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT, Dimension::ALL_DIMENSIONS ); - mPopupBackgroundImage.SetSizeModeFactor( BACKGROUND_OUTER_BORDER ); + UpdateBackgroundPositionAndSize(); const bool prevAlter = mAlterAddedChild; mAlterAddedChild = false; mPopupContainer.Add( mPopupBackgroundImage ); mAlterAddedChild = prevAlter; + if( mTailImage ) + { + mPopupBackgroundImage.Add( mTailImage ); + } + mLayoutDirty = true; } @@ -622,7 +649,7 @@ void Popup::SetContent( Actor content ) if( mContent ) { - mContent.SetName( "popup-content" ); + mContent.SetName( "popupContent" ); mPopupLayout.AddChild( mContent, Toolkit::TableView::CellPosition( 1, 0 ) ); } @@ -684,6 +711,9 @@ void Popup::SetDisplayState( Toolkit::Popup::DisplayState displayState ) // Update the state to indicate the current intent. mDisplayState = Toolkit::Popup::SHOWING; + // We want the popup to have key input focus when it is displayed + SetKeyInputFocus(); + // We are displaying so bring the popup layer to the front, and set it visible so it is rendered. mLayer.RaiseToTop(); mLayer.SetVisible( true ); @@ -697,7 +727,6 @@ void Popup::SetDisplayState( Toolkit::Popup::DisplayState displayState ) // Allow the popup to catch events. mPopupLayout.SetSensitive( true ); - SetKeyInputFocus(); // Handle the keyboard focus when popup is shown. Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get(); @@ -705,14 +734,29 @@ void Popup::SetDisplayState( Toolkit::Popup::DisplayState displayState ) { mPreviousFocusedActor = keyboardFocusManager.GetCurrentFocusActor(); - if( mContent && mContent.IsKeyboardFocusable() ) - { - // If content is focusable, move the focus to content. - keyboardFocusManager.SetCurrentFocusActor( mContent ); - } - else + if( Self().IsKeyboardFocusable() ) { - DALI_LOG_WARNING( "There is no focusable in popup\n" ); + // Setup the actgor to start focus from. + Actor focusActor; + if( mContent && mContent.IsKeyboardFocusable() ) + { + // If the content is focusable, move the focus to the content. + focusActor = mContent; + } + else if( mFooter && mFooter.IsKeyboardFocusable() ) + { + // If the footer is focusable, move the focus to the footer. + focusActor = mFooter; + } + else + { + DALI_LOG_WARNING( "There is no focusable in popup\n" ); + } + + if( focusActor ) + { + keyboardFocusManager.SetCurrentFocusActor( focusActor ); + } } } } @@ -803,38 +847,50 @@ void Popup::LayoutTail() return; } - const Vector3& position = GetTailPosition(); + const Vector3& parentOrigin = GetTailPosition(); + Vector3 position; std::string image; + Vector3 anchorPoint; // depending on position of tail around ParentOrigin, a different tail image is used... - if( position.y < Math::MACHINE_EPSILON_1 ) + if( parentOrigin.y < Math::MACHINE_EPSILON_1 ) { image = mTailUpImage; + anchorPoint = AnchorPoint::BOTTOM_CENTER; + position.y = mBackgroundBorder.top; } - else if( position.y > 1.0f - Math::MACHINE_EPSILON_1 ) + else if( parentOrigin.y > ( 1.0f - Math::MACHINE_EPSILON_1 ) ) { image = mTailDownImage; + anchorPoint = AnchorPoint::TOP_CENTER; + position.y = - mBackgroundBorder.bottom; } - else if( position.x < Math::MACHINE_EPSILON_1 ) + else if( parentOrigin.x < Math::MACHINE_EPSILON_1 ) { image = mTailLeftImage; + anchorPoint = AnchorPoint::CENTER_RIGHT; + position.x = mBackgroundBorder.left; } - else if( position.x > 1.0f - Math::MACHINE_EPSILON_1 ) + else if( parentOrigin.x > ( 1.0f - Math::MACHINE_EPSILON_1 ) ) { image = mTailRightImage; + anchorPoint = AnchorPoint::CENTER_LEFT; + position.x = - mBackgroundBorder.right; } if( !image.empty() ) { // Adds the tail actor. - Image tail = ResourceImage::New( image ); - mTailImage = ImageActor::New( tail ); - mTailImage.SetName( "tail-image" ); - const Vector3 anchorPoint = AnchorPoint::BOTTOM_RIGHT - position; - mTailImage.SetParentOrigin( position ); + mTailImage = Toolkit::ImageView::New( image ); + mTailImage.SetName( "tailImage" ); + mTailImage.SetParentOrigin( parentOrigin ); mTailImage.SetAnchorPoint( anchorPoint ); + mTailImage.SetPosition( position ); - mLayer.Add( mTailImage ); + if( mPopupBackgroundImage ) + { + mPopupBackgroundImage.Add( mTailImage ); + } } } @@ -849,27 +905,28 @@ Toolkit::Popup::ContextualMode Popup::GetContextualMode() const return mContextualMode; } -ImageActor Popup::CreateBacking() +Toolkit::Control Popup::CreateBacking() { - mBacking = Dali::Toolkit::CreateSolidColorActor( mBackingColor ); - mBacking.SetName( "popup-backing" ); + Toolkit::Control backing = Control::New(); + backing.SetBackgroundColor( Vector4( mBackingColor.r, mBackingColor.g, mBackingColor.b, 1.0f ) ); + backing.SetName( "popupBacking" ); // Must always be positioned top-left of stage, regardless of parent. - mBacking.SetPositionInheritanceMode( DONT_INHERIT_POSITION ); - mBacking.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + backing.SetInheritPosition(false); + backing.SetAnchorPoint( AnchorPoint::TOP_LEFT ); // Always the full size of the stage. - mBacking.SetResizePolicy( ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS ); - mBacking.SetSize( Stage::GetCurrent().GetSize() ); + backing.SetResizePolicy( ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS ); + backing.SetSize( Stage::GetCurrent().GetSize() ); // Catch events. - mBacking.SetSensitive( true ); + backing.SetSensitive( true ); // Default to being transparent. - mBacking.SetOpacity( 0.0f ); - mBacking.TouchedSignal().Connect( this, &Popup::OnBackingTouched ); - mBacking.WheelEventSignal().Connect( this, &Popup::OnBackingWheelEvent ); - return mBacking; + backing.SetProperty( Actor::Property::COLOR_ALPHA, 0.0f ); + backing.TouchSignal().Connect( this, &Popup::OnBackingTouched ); + backing.WheelEventSignal().Connect( this, &Popup::OnBackingWheelEvent ); + return backing; } Toolkit::Popup::TouchedOutsideSignalType& Popup::OutsideTouchedSignal() @@ -953,6 +1010,18 @@ void Popup::SetExitAnimationData( const Property::Map& map ) Scripting::NewAnimation( map, mExitAnimationData ); } +void Popup::UpdateBackgroundPositionAndSize() +{ + if( mPopupBackgroundImage ) + { + mPopupBackgroundImage.SetResizePolicy( ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT, Dimension::ALL_DIMENSIONS ); + mPopupBackgroundImage.SetSizeModeFactor( Vector3( mBackgroundBorder.left + mBackgroundBorder.right, mBackgroundBorder.top + mBackgroundBorder.bottom, 0.0f ) ); + + // Adjust the position of the background so the transparent areas are set appropriately + mPopupBackgroundImage.SetPosition( ( mBackgroundBorder.right - mBackgroundBorder.left ) * 0.5f, ( mBackgroundBorder.bottom - mBackgroundBorder.top ) * 0.5f ); + } +} + void Popup::SetAutoHideDelay( int delay ) { mAutoHideDelay = delay; @@ -977,6 +1046,7 @@ const bool Popup::IsBackingEnabled() const void Popup::SetBackingColor( Vector4 color ) { mBackingColor = color; + mBacking.SetBackgroundColor( Vector4( color.r, color.g, color.b, 1.0f ) ); mLayoutDirty = true; } @@ -989,6 +1059,7 @@ void Popup::SetTailUpImage( std::string image ) { mTailUpImage = image; mLayoutDirty = true; + LayoutTail(); } const std::string& Popup::GetTailUpImage() const @@ -1000,6 +1071,7 @@ void Popup::SetTailDownImage( std::string image ) { mTailDownImage = image; mLayoutDirty = true; + LayoutTail(); } const std::string& Popup::GetTailDownImage() const @@ -1011,6 +1083,7 @@ void Popup::SetTailLeftImage( std::string image ) { mTailLeftImage = image; mLayoutDirty = true; + LayoutTail(); } const std::string& Popup::GetTailLeftImage() const @@ -1022,6 +1095,7 @@ void Popup::SetTailRightImage( std::string image ) { mTailRightImage = image; mLayoutDirty = true; + LayoutTail(); } const std::string& Popup::GetTailRightImage() const @@ -1201,12 +1275,33 @@ void Popup::SetProperty( BaseObject* object, Property::Index propertyIndex, cons std::string valueString; if( value.Get( valueString ) ) { - Image image = ResourceImage::New( valueString ); - if( image ) - { - ImageActor actor = ImageActor::New( image ); - popupImpl.SetPopupBackgroundImage( actor ); - } + Toolkit::ImageView actor = Toolkit::ImageView::New( valueString ); + popupImpl.SetPopupBackgroundImage( actor ); + } + break; + } + case Toolkit::Popup::Property::POPUP_BACKGROUND_BORDER: + { + bool valueUpdated = false; + + Vector4 valueVector4; + if( value.Get( popupImpl.mBackgroundBorder ) ) + { + valueUpdated = true; + } + else if( value.Get( valueVector4 ) ) + { + popupImpl.mBackgroundBorder.left = valueVector4.x; + popupImpl.mBackgroundBorder.right = valueVector4.y; + popupImpl.mBackgroundBorder.bottom = valueVector4.z; + popupImpl.mBackgroundBorder.top = valueVector4.w; + valueUpdated = true; + } + + if( valueUpdated ) + { + popupImpl.LayoutTail(); // Update the tail if required + popupImpl.UpdateBackgroundPositionAndSize(); // Update the background's size and position } break; } @@ -1349,13 +1444,18 @@ Property::Value Popup::GetProperty( BaseObject* object, Property::Index property } case Toolkit::Popup::Property::POPUP_BACKGROUND_IMAGE: { - ResourceImage image = ResourceImage::DownCast( popupImpl.GetPopupBackgroundImage() ); - if( image ) + Toolkit::ImageView imageView = Toolkit::ImageView::DownCast( popupImpl.GetPopupBackgroundImage() ); + if( imageView ) { - value = image.GetUrl(); + value = imageView.GetProperty( Toolkit::ImageView::Property::IMAGE ); } break; } + case Toolkit::Popup::Property::POPUP_BACKGROUND_BORDER: + { + value = popupImpl.mBackgroundBorder; + break; + } case Toolkit::Popup::Property::TAIL_UP_IMAGE: { value = popupImpl.GetTailUpImage(); @@ -1418,7 +1518,7 @@ bool Popup::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tra return connected; } -bool Popup::OnBackingTouched( Actor actor, const TouchEvent& event ) +bool Popup::OnBackingTouched( Actor actor, const TouchData& touch ) { // Allow events to pass through if touch transparency is enabled. if( mTouchTransparent ) @@ -1426,11 +1526,9 @@ bool Popup::OnBackingTouched( Actor actor, const TouchEvent& event ) return false; } - if( event.GetPointCount() > 0 ) + if( touch.GetPointCount() > 0 ) { - const TouchPoint& point = event.GetPoint( 0 ); - - if( point.state == TouchPoint::Down ) + if( touch.GetState( 0 ) == PointState::DOWN ) { // Guard against destruction during signal emission. Toolkit::Popup handle( GetOwner() ); @@ -1457,7 +1555,7 @@ bool Popup::OnBackingWheelEvent( Actor actor, const WheelEvent& event ) return true; } -bool Popup::OnDialogTouched(Actor actor, const TouchEvent& event) +bool Popup::OnDialogTouched( Actor actor, const TouchData& touch ) { // Allow events to pass through if touch transparency is enabled. if( mTouchTransparent ) @@ -1470,14 +1568,18 @@ bool Popup::OnDialogTouched(Actor actor, const TouchEvent& event) return true; } -void Popup::OnControlStageConnection() +void Popup::OnStageConnection( int depth ) { + Control::OnStageConnection( depth ); + mLayoutDirty = true; RelayoutRequest(); } -void Popup::OnControlChildAdd( Actor& child ) +void Popup::OnChildAdd( Actor& child ) { + Control::OnChildAdd( child ); + // Re-parent any children added by user to the body layer. if( mAlterAddedChild ) { @@ -1708,114 +1810,145 @@ bool Popup::OnKeyEvent( const KeyEvent& event ) return consumed; } +void Popup::AddFocusableChildrenRecursive( Actor parent, std::vector< Actor >& focusableActors ) +{ + if( parent ) + { + Toolkit::Control control = Toolkit::Control::DownCast( parent ); + bool layoutControl = control && GetImplementation( control ).IsKeyboardNavigationSupported(); + + if( parent.IsKeyboardFocusable() || layoutControl ) + { + focusableActors.push_back( parent ); + + if( !layoutControl ) + { + for( unsigned int i = 0, numberChildren = parent.GetChildCount(); i < numberChildren; ++i ) + { + Actor child( parent.GetChildAt( i ) ); + AddFocusableChildrenRecursive( child, focusableActors ); + } + } + } + } +} + +void Popup::AddFocusableChildren( Actor parent, std::vector< Actor >& focusableActors ) +{ + if( parent ) + { + Toolkit::Control control = Toolkit::Control::DownCast( parent ); + if( !GetImplementation( control ).IsKeyboardNavigationSupported() ) + { + for( unsigned int i = 0, numberChildren = parent.GetChildCount(); i < numberChildren; ++i ) + { + Actor child( parent.GetChildAt( i ) ); + AddFocusableChildrenRecursive( child, focusableActors ); + } + } + else + { + focusableActors.push_back( parent ); + } + } +} + Actor Popup::GetNextKeyboardFocusableActor( Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled ) { + std::string currentStr; + if( currentFocusedActor ) + { + currentStr = currentFocusedActor.GetName(); + } + Actor nextFocusableActor( currentFocusedActor ); + Actor currentFocusGroup; + if( currentFocusedActor ) + { + currentFocusGroup = KeyboardFocusManager::Get().GetFocusGroup( currentFocusedActor ); + } // TODO: Needs to be optimised - if( !currentFocusedActor || ( currentFocusedActor && KeyboardFocusManager::Get().GetFocusGroup( currentFocusedActor ) != Self() ) ) + // The following statement checks that if we have a current focused actor, then the current focus group is not the popup content or footer. + // This is to detect if the focus is currently outside the popup, and if so, move it inside. + if( !currentFocusedActor || + ( currentFocusedActor && ( ( !mContent || ( currentFocusGroup != mContent ) ) && ( !mFooter || ( currentFocusGroup != mFooter ) ) ) ) ) { - // The current focused actor is not within popup + // The current focused actor is not within popup. if( mContent && mContent.IsKeyboardFocusable() ) { - // If content is focusable, move the focus to content + // If the content is focusable, move the focus to the content. nextFocusableActor = mContent; } + else if( mFooter && mFooter.IsKeyboardFocusable() ) + { + // If the footer is focusable, move the focus to the footer. + nextFocusableActor = mFooter; + } } else { // Rebuild the focus chain because controls or content can be added or removed dynamically std::vector< Actor > focusableActors; - if( mContent && mContent.IsKeyboardFocusable() ) + + AddFocusableChildren( mContent, focusableActors ); + AddFocusableChildren( mFooter, focusableActors ); + + std::vector< Actor >::iterator endIterator = focusableActors.end(); + std::vector< Actor >::iterator currentIterator = focusableActors.begin(); + for( std::vector< Actor >::iterator iterator = focusableActors.begin(); iterator != endIterator; ++iterator ) { - focusableActors.push_back( mContent ); + if( currentFocusedActor == *iterator ) + { + currentIterator = iterator; + } } - for( std::vector< Actor >::iterator iter = focusableActors.begin(), end = focusableActors.end(); iter != end; ++iter ) + if( currentIterator != endIterator ) { - if( currentFocusedActor == *iter ) + switch( direction ) { - switch( direction ) + case Toolkit::Control::KeyboardFocus::LEFT: { - case Toolkit::Control::KeyboardFocus::LEFT: + if( currentIterator == focusableActors.begin() ) { - if( iter == focusableActors.begin() ) - { - nextFocusableActor = *( focusableActors.end() - 1 ); - } - else - { - nextFocusableActor = *( iter - 1 ); - } - break; + nextFocusableActor = *( endIterator - 1 ); } - case Toolkit::Control::KeyboardFocus::RIGHT: + else { - if( iter == focusableActors.end() - 1 ) - { - nextFocusableActor = *( focusableActors.begin() ); - } - else - { - nextFocusableActor = *( iter + 1 ); - } - break; + nextFocusableActor = *( currentIterator - 1 ); } - - case Toolkit::Control::KeyboardFocus::UP: + break; + } + case Toolkit::Control::KeyboardFocus::RIGHT: + { + if( currentIterator == endIterator - 1 ) { - if( mContent && *iter == mContent ) - { - nextFocusableActor = *( focusableActors.end() - 1 ); - } - else - { - if( mContent && mContent.IsKeyboardFocusable() ) - { - nextFocusableActor = mContent; - } - else - { - if ( iter == focusableActors.begin() ) - { - nextFocusableActor = *( focusableActors.end() - 1 ); - } - else - { - nextFocusableActor = *( iter - 1 ); - } - } - } - break; + nextFocusableActor = *( focusableActors.begin() ); } - - case Toolkit::Control::KeyboardFocus::DOWN: + else { - if( mContent && mContent.IsKeyboardFocusable() ) - { - nextFocusableActor = mContent; - } - else - { - if( iter == focusableActors.end() - 1 ) - { - nextFocusableActor = *( focusableActors.begin() ); - } - else - { - nextFocusableActor = *( iter + 1 ); - } - } - break; + nextFocusableActor = *( currentIterator + 1 ); } + break; } - if( !nextFocusableActor ) + case Toolkit::Control::KeyboardFocus::UP: { - DALI_LOG_WARNING( "Can not decide next focusable actor\n" ); + nextFocusableActor = *( focusableActors.begin() ); + break; } - break; + case Toolkit::Control::KeyboardFocus::DOWN: + { + nextFocusableActor = *( endIterator - 1 ); + break; + } + } + + if( !nextFocusableActor ) + { + DALI_LOG_WARNING( "Can not decide next focusable actor\n" ); } } } @@ -1823,6 +1956,7 @@ Actor Popup::GetNextKeyboardFocusableActor( Actor currentFocusedActor, Toolkit:: return nextFocusableActor; } + } // namespace Internal } // namespace Toolkit