/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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.
// EXTERNAL INCLUDES
#include <cstring> // for strcmp
-#include <dali/public-api/adaptor-framework/key.h>
#include <dali/devel-api/adaptor-framework/physical-keyboard.h>
+#include <dali/devel-api/actors/actor-devel.h>
+#include <dali/public-api/object/type-registry-helper.h>
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/adaptor-framework/key.h>
#include <dali/public-api/animation/constraints.h>
-#include <dali/public-api/common/stage.h>
+#include <dali/devel-api/common/stage.h>
#include <dali/public-api/events/key-event.h>
#include <dali/public-api/events/touch-event.h>
-#include <dali/public-api/images/resource-image.h>
#include <dali/public-api/object/type-registry.h>
-#include <dali/devel-api/object/type-registry-helper.h>
+#include <dali/devel-api/scripting/scripting.h>
+#include <dali/devel-api/actors/actor-devel.h>
#include <dali/public-api/size-negotiation/relayout-container.h>
-#include <dali/integration-api/debug.h>
// INTERNAL INCLUDES
-#include <dali-toolkit/public-api/controls/buttons/button.h>
+#include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
+#include <dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h>
#include <dali-toolkit/public-api/controls/control-impl.h>
-#include <dali-toolkit/public-api/controls/default-controls/solid-color-actor.h>
-#include <dali-toolkit/public-api/focus-manager/accessibility-focus-manager.h>
+#include <dali-toolkit/public-api/controls/image-view/image-view.h>
+#include <dali-toolkit/devel-api/accessibility-manager/accessibility-manager.h>
+#include <dali-toolkit/public-api/visuals/color-visual-properties.h>
+#include <dali-toolkit/public-api/visuals/visual-properties.h>
#include <dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h>
-#include <dali-toolkit/internal/controls/buttons/button-impl.h>
using namespace Dali;
namespace
{
+/**
+ * Creation function for main Popup type.
+ * @return Handle to the new popup object.
+ */
BaseHandle Create()
{
return Toolkit::Popup::New();
}
-// Setup properties, signals and actions using the type-registry.
-DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Popup, Toolkit::Control, Create )
+// Toast style defaults.
+const int DEFAULT_TOAST_AUTO_HIDE_DELAY = 3000; ///< Toast will auto-hide after 3000ms (3 seconds)
+const float DEFAULT_TOAST_TRANSITION_TIME = 0.65f; ///< Default time the toast Popup will take to show and hide.
+const Vector3 DEFAULT_TOAST_BOTTOM_PARENT_ORIGIN( 0.5f, 0.94f, 0.5f ); ///< This is similar to BOTTOM_CENTER, but vertically higher up, as a ratio of parent height.
+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.
-DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "touched-outside", SIGNAL_TOUCHED_OUTSIDE )
-DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "hidden", SIGNAL_HIDDEN )
+/**
+ * Creation function for named type "popupToast".
+ * @return Handle to the new toast popup object.
+ */
+BaseHandle CreateToast()
+{
+ Toolkit::Popup popup = Toolkit::Popup::New();
-DALI_TYPE_REGISTRATION_END()
+ // Setup for Toast Popup type.
+ popup.SetProperty( Actor::Property::SIZE_MODE_FACTOR, DEFAULT_TOAST_WIDTH_OF_STAGE_RATIO );
+ popup.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::WIDTH );
+ popup.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT );
+ popup.SetProperty( Toolkit::Popup::Property::CONTEXTUAL_MODE, Toolkit::Popup::NON_CONTEXTUAL );
+ popup.SetProperty( Toolkit::Popup::Property::ANIMATION_DURATION, DEFAULT_TOAST_TRANSITION_TIME );
+ popup.SetProperty( Toolkit::Popup::Property::TAIL_VISIBILITY, false );
+
+ // Disable the dimmed backing.
+ popup.SetProperty( Toolkit::Popup::Property::BACKING_ENABLED, false );
+
+ // The toast popup should fade in (not zoom).
+ popup.SetProperty( Toolkit::Popup::Property::ANIMATION_MODE, Toolkit::Popup::FADE );
+
+ // The toast popup should auto-hide.
+ popup.SetProperty( Toolkit::Popup::Property::AUTO_HIDE_DELAY, DEFAULT_TOAST_AUTO_HIDE_DELAY );
+
+ // Align to the bottom of the screen.
+ popup.SetProperty( Actor::Property::PARENT_ORIGIN, DEFAULT_TOAST_BOTTOM_PARENT_ORIGIN );
+ popup.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER );
+
+ // Let events pass through the toast popup.
+ popup.SetProperty( Toolkit::Popup::Property::TOUCH_TRANSPARENT, true );
-// Properties
-const char* const PROPERTY_TITLE = "title";
-const char* const PROPERTY_STATE = "state";
+ return popup;
+}
+
+// Setup properties, signals and actions using the type-registry.
+DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Popup, Toolkit::Control, Create )
-const float POPUP_ANIMATION_DURATION = 0.45f; ///< Duration of hide/show animations
+// 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, "displayState", STRING, DISPLAY_STATE )
+DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "touchTransparent", BOOLEAN, TOUCH_TRANSPARENT )
+
+// Contextual related properties.
+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, "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, "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, "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 )
-const float POPUP_WIDTH = 720.0f; ///< Width of Popup
-const float POPUP_OUT_MARGIN_WIDTH = 16.f; ///< Space between the screen edge and the popup edge in the horizontal dimension.
-const float POPUP_OUT_MARGIN_HEIGHT = 36.f; ///< Space between the screen edge and the popup edge in the vertical dimension.
-const float POPUP_TITLE_WIDTH = 648.0f; ///<Width of Popup Title
-const float POPUP_BUTTON_BG_HEIGHT = 96.f; ///< Height of Button Background.
-const Vector3 DEFAULT_DIALOG_SIZE = Vector3(POPUP_TITLE_WIDTH/POPUP_WIDTH, 0.5f, 0.0f);
-const Vector3 DEFAULT_BOTTOM_SIZE = Vector3(1.0f, 0.2f, 0.0f);
+DALI_TYPE_REGISTRATION_END()
-} // unnamed namespace
+// Named type registration.
+
+// Toast Popup: Non-modal popup that displays information at the bottom of the screen.
+TypeRegistration typeRegistrationToast( "PopupToast", typeid( Toolkit::Popup ), CreateToast );
+
+// Enumeration to / from string conversion tables
+
+const Scripting::StringEnum DisplayStateTable[] = {
+ { "SHOWING", Toolkit::Popup::SHOWING },
+ { "SHOWN", Toolkit::Popup::SHOWN },
+ { "HIDING", Toolkit::Popup::HIDING },
+ { "HIDDEN", Toolkit::Popup::HIDDEN },
+}; const unsigned int DisplayStateTableCount = sizeof( DisplayStateTable ) / sizeof( DisplayStateTable[0] );
+
+const Scripting::StringEnum AnimationModeTable[] = {
+ { "NONE", Toolkit::Popup::NONE },
+ { "ZOOM", Toolkit::Popup::ZOOM },
+ { "FADE", Toolkit::Popup::FADE },
+ { "CUSTOM", Toolkit::Popup::CUSTOM },
+}; const unsigned int AnimationModeTableCount = sizeof( AnimationModeTable ) / sizeof( AnimationModeTable[0] );
+
+const Scripting::StringEnum ContextualModeTable[] = {
+ { "NON_CONTEXTUAL", Toolkit::Popup::NON_CONTEXTUAL },
+ { "ABOVE", Toolkit::Popup::ABOVE },
+ { "RIGHT", Toolkit::Popup::RIGHT },
+ { "BELOW", Toolkit::Popup::BELOW },
+ { "LEFT", Toolkit::Popup::LEFT },
+}; const unsigned int ContextualModeTableCount = sizeof( ContextualModeTable ) / sizeof( ContextualModeTable[0] );
+
+// Popup defaults.
+const Vector3 DEFAULT_POPUP_PARENT_RELATIVE_SIZE( 0.75f, 1.0f, 1.0f ); ///< Default size percentage of parent.
+const float DEFAULT_POPUP_ANIMATION_DURATION = 0.6f; ///< Duration of hide/show animations.
+const float POPUP_OUT_MARGIN_WIDTH = 16.f; ///< Space between the screen edge and the popup edge in the horizontal dimension.
+const float POPUP_OUT_MARGIN_HEIGHT = 36.f; ///< Space between the screen edge and the popup edge in the vertical dimension.
+const Vector3 DEFAULT_TAIL_POSITION( 0.5f, 1.0f, 0.0f ); ///< Position the tail will be displayed when enabled without setting the position.
+
+// Contextual defaults.
+const Vector2 DEFAULT_CONTEXTUAL_ADJACENCY_MARGIN( 10.0f, 10.0f ); ///< How close the Popup will be to it's contextual parent.
+const Vector2 DEFAULT_CONTEXTUAL_STAGE_BORDER( 15.0f, 15.0f ); ///< How close the Popup can be to the stage edges.
+
+// Popup style defaults.
+const char* DEFAULT_BACKGROUND_IMAGE_FILE_NAME = "00_popup_bg.9.png"; ///< Background image.
+const char* DEFAULT_TAIL_UP_IMAGE_FILE_NAME = "popup_tail_up.png"; ///< Tail up image.
+const char* DEFAULT_TAIL_DOWN_IMAGE_FILE_NAME = "popup_tail_down.png"; ///< Tail down image.
+const char* DEFAULT_TAIL_LEFT_IMAGE_FILE_NAME = "popup_tail_left.png"; ///< Tail left image.
+const char* DEFAULT_TAIL_RIGHT_IMAGE_FILE_NAME = "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 Rect<int> DEFAULT_BACKGROUND_BORDER( 17, 17, 13, 13 ); ///< Default border of the background.
+const Rect<float> 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<float> 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.
+const float DEFAULT_RELATIVE_PARENT_WIDTH = 0.75f; ///< If width is not fixed, relative size to parent is used by default.
+
+} // Unnamed namespace
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Popup
-///////////////////////////////////////////////////////////////////////////////////////////////////
+/*
+ * Implementation.
+ */
Dali::Toolkit::Popup Popup::New()
{
- PopupStylePtr style = PopupStyleDefault::New();
-
// Create the implementation
- PopupPtr popup(new Popup(*style));
+ PopupPtr popup( new Popup() );
- // Pass ownership to CustomActor via derived handle
- Dali::Toolkit::Popup handle(*popup);
+ // Pass ownership to CustomActor via derived handle.
+ Dali::Toolkit::Popup handle( *popup );
- // Second-phase init of the implementation
- // This can only be done after the CustomActor connection has been made...
+ // Second-phase initialisation of the implementation.
+ // This can only be done after the CustomActor connection has been made.
popup->Initialize();
return handle;
}
-Popup::Popup(PopupStyle& style)
-: Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ),
- mShowing(false),
- mState(Toolkit::Popup::POPUP_NONE), // Initially, the popup state should not be set, it's set in OnInitialize
- mAlterAddedChild(false),
- mPopupStyle(PopupStylePtr(&style)),
- mPropertyTitle(Property::INVALID_INDEX),
- mPropertyState(Property::INVALID_INDEX)
+Popup::Popup()
+: Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
+ mTouchedOutsideSignal(),
+ mShowingSignal(),
+ mShownSignal(),
+ mHidingSignal(),
+ mHiddenSignal(),
+ mLayer(),
+ mPopupLayout(),
+ mBacking(),
+ mPreviousFocusedActor(),
+ mTailImage(),
+ mPopupContainer(),
+ mAnimation(),
+ mAlterAddedChild( false ),
+ mLayoutDirty( true ),
+ mAutoHideTimer(),
+ mTouchTransparent( false ),
+ 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(),
+ mTailDownImage(),
+ mTailLeftImage(),
+ mTailRightImage()
{
SetKeyboardNavigationSupport( true );
+
+ const std::string imageDirPath = AssetManager::GetDaliImagePath();
+ mTailUpImage = imageDirPath + DEFAULT_TAIL_UP_IMAGE_FILE_NAME;
+ mTailDownImage = imageDirPath + DEFAULT_TAIL_DOWN_IMAGE_FILE_NAME;
+ mTailLeftImage = imageDirPath + DEFAULT_TAIL_LEFT_IMAGE_FILE_NAME;
+ mTailRightImage = imageDirPath + DEFAULT_TAIL_RIGHT_IMAGE_FILE_NAME;
}
void Popup::OnInitialize()
{
- Dali::Stage stage = Dali::Stage::GetCurrent();
-
Actor self = Self();
- self.SetSensitive(false);
- // Reisize to fit the height of children
- self.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::HEIGHT );
+ self.SetProperty( Dali::Actor::Property::NAME, "popup" );
+
+ // Apply some default resizing rules.
+ self.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
+ self.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
+
+ self.SetProperty( Actor::Property::SIZE_MODE_FACTOR, DEFAULT_POPUP_PARENT_RELATIVE_SIZE );
+ self.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::WIDTH );
+ self.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT );
- // Create Layer
+ // Create a new layer so all Popup components can appear above all other actors.
mLayer = Layer::New();
- mLayer.SetName( "POPUP_LAYER" );
- mLayer.SetParentOrigin(ParentOrigin::CENTER);
- mLayer.SetAnchorPoint(AnchorPoint::CENTER);
+ mLayer.SetProperty( Dali::Actor::Property::NAME, "popupLayer" );
+
+ mLayer.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
+ mLayer.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
mLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
- mLayer.SetDrawMode( DrawMode::OVERLAY );
- // Any content after this point which is added to Self() will be reparented to
- // mContent.
- mAlterAddedChild = true;
- // Add Backing (Dim effect)
- CreateBacking();
- mAlterAddedChild = false;
+ // Important to set as invisible as otherwise, if the popup is parented,
+ // but not shown yet it will appear statically on the screen.
+ mLayer.SetProperty( Actor::Property::VISIBLE, false );
+
+ // Add the layer to the hierarchy.
+ self.Add( mLayer );
- // Add Dialog ( background image, title, content container, button container and tail )
- CreateDialog();
+ // Add Backing (Dimmed effect).
+ mBacking = CreateBacking();
+ mLayer.Add( mBacking );
- mLayer.Add( self );
+ mPopupContainer = Actor::New();
+ mPopupContainer.SetProperty( Dali::Actor::Property::NAME, "popupContainer" );
+ mPopupContainer.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
+ mPopupContainer.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
+ mPopupContainer.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
+ mLayer.Add( mPopupContainer );
+ // Create the Popup layout to contain all main content.
mPopupLayout = Toolkit::TableView::New( 3, 1 );
- mPopupLayout.SetName( "POPUP_LAYOUT_TABLE" );
- mPopupLayout.SetParentOrigin(ParentOrigin::CENTER);
- mPopupLayout.SetAnchorPoint(AnchorPoint::CENTER);
- mPopupLayout.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
+
+ // Adds the default background image.
+ const std::string imageDirPath = AssetManager::GetDaliImagePath();
+ SetPopupBackgroundImage( Toolkit::ImageView::New( imageDirPath + DEFAULT_BACKGROUND_IMAGE_FILE_NAME ) );
+
+ mPopupLayout.SetProperty( Dali::Actor::Property::NAME, "popupLayoutTable" );
+ mPopupLayout.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
+ mPopupLayout.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
+
+ mPopupLayout.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::WIDTH );
mPopupLayout.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT );
- mPopupLayout.SetFitHeight( 0 ); // Set row to fit
- mPopupLayout.SetFitHeight( 1 ); // Set row to fit
- self.Add( mPopupLayout );
+ mPopupLayout.SetProperty( Actor::Property::SIZE, Vector2( Stage::GetCurrent().GetSize().x * DEFAULT_RELATIVE_PARENT_WIDTH, 0.0f ) );
- // Any content after this point which is added to Self() will be reparented to
- // mContent.
- mAlterAddedChild = true;
+ mPopupLayout.SetFitHeight( 0 ); // Set row to fit.
+ mPopupLayout.SetFitHeight( 1 ); // Set row to fit.
- // Default content.
-// ShowTail(ParentOrigin::BOTTOM_CENTER);
+ mPopupLayout.TouchedSignal().Connect( this, &Popup::OnDialogTouched );
- // Hide content by default.
- SetState( Toolkit::Popup::POPUP_HIDE, 0.0f );
+ mPopupContainer.Add( mPopupLayout );
- mPropertyTitle = self.RegisterProperty( PROPERTY_TITLE, "", Property::READ_WRITE );
- mPropertyState = self.RegisterProperty( PROPERTY_STATE, "POPUP_HIDE", Property::READ_WRITE );
+ // Any content after this point which is added to Self() will be re-parented to mContent.
+ mAlterAddedChild = true;
- // Make self as keyboard focusable and focus group
- self.SetKeyboardFocusable(true);
- SetAsKeyboardFocusGroup(true);
+ SetAsKeyboardFocusGroup( true );
}
-void Popup::OnPropertySet( Property::Index index, Property::Value propertyValue )
+Popup::~Popup()
{
- if( index == mPropertyTitle )
- {
- SetTitle(propertyValue.Get<std::string>());
- }
- else if ( index == mPropertyState )
+ mEntryAnimationData.Clear();
+ mExitAnimationData.Clear();
+}
+
+void Popup::LayoutAnimation()
+{
+ // Perform setup based on the currently selected animation.
+ switch( mAnimationMode )
{
- std::string value( propertyValue.Get<std::string>() );
- if(value == "POPUP_SHOW")
+ case Toolkit::Popup::ZOOM:
{
- SetState( Toolkit::Popup::POPUP_SHOW, 0.0f );
+ // Zoom animations start fully zoomed out.
+ mPopupContainer.SetProperty( Actor::Property::SCALE, Vector3::ZERO );
+ break;
}
- else if( value == "POPUP_HIDE")
+
+ case Toolkit::Popup::FADE:
{
- SetState( Toolkit::Popup::POPUP_HIDE, 0.0f );
+ // Fade animations start transparent.
+ mPopupContainer.SetProperty( Actor::Property::OPACITY, 0.0f );
+ break;
}
- }
-}
-Popup::~Popup()
-{
- mLayer.Unparent();
-}
+ case Toolkit::Popup::CUSTOM:
+ {
+ // Initialise the custom animation by playing to the end of it's exit animation instantly.
+ // EG. If it was zooming in, then we zoom out fully instantly so the zoom in works.
+ StartTransitionAnimation( false, true );
+ break;
+ }
-size_t Popup::GetButtonCount() const
-{
- return mButtons.size();
+ case Toolkit::Popup::NONE:
+ {
+ break;
+ }
+ }
}
-void Popup::SetBackgroundImage( Actor image )
+void Popup::StartTransitionAnimation( bool transitionIn, bool instantaneous /* false */ )
{
- // Removes any previous background.
- if( mBackgroundImage && mPopupLayout )
+ // Stop and recreate animation.
+ if ( mAnimation )
{
- mPopupLayout.Remove( mBackgroundImage );
+ mAnimation.Stop();
+ mAnimation.Clear();
+ mAnimation.Reset();
}
+ float duration = GetAnimationDuration();
- // Adds new background to the dialog.
- mBackgroundImage = image;
-
- mBackgroundImage.SetName( "POPUP_BACKGROUND_IMAGE" );
-
- // OnDialogTouched only consume the event. It prevents the touch event to be caught by the backing.
- mBackgroundImage.TouchedSignal().Connect( this, &Popup::OnDialogTouched );
+ // Setup variables ready to start the animations.
+ // If we are performing the animation instantaneously, we do not want to emit a signal.
+ if( !instantaneous )
+ {
+ if( transitionIn )
+ {
+ // Setup variables and signal that we are starting the transition.
+ // Note: We signal even if the transition is instant so signal order is consistent.
+ mShowingSignal.Emit();
+ }
+ else
+ {
+ mHidingSignal.Emit();
+ }
+ }
- mBackgroundImage.SetResizePolicy( ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT, Dimension::ALL_DIMENSIONS );
- mBackgroundImage.SetAnchorPoint( AnchorPoint::CENTER );
- mBackgroundImage.SetParentOrigin( ParentOrigin::CENTER );
+ // Perform chosen animation for the Popup.
+ switch( mAnimationMode )
+ {
+ case Toolkit::Popup::NONE:
+ {
+ mAnimation = Animation::New( 0.0f );
+ break;
+ }
- Vector3 border( mPopupStyle->backgroundOuterBorder.x, mPopupStyle->backgroundOuterBorder.z, 0.0f );
- mBackgroundImage.SetSizeModeFactor( border );
+ case Toolkit::Popup::ZOOM:
+ {
+ mAnimation = Animation::New( duration );
+ if( duration > Math::MACHINE_EPSILON_0 )
+ {
+ if( transitionIn )
+ {
+ mAnimation.AnimateTo( Property( mPopupContainer, Actor::Property::SCALE ), Vector3::ONE, AlphaFunction::EASE_IN_OUT, TimePeriod( duration * 0.25f, duration * 0.75f ) );
+ }
+ else
+ {
+ // Zoom out animation is twice the speed. Modify the duration variable so the backing animation speed is modified also.
+ duration /= 2.0f;
+ mAnimation.SetDuration( duration );
+ mAnimation.AnimateTo( Property( mPopupContainer, Actor::Property::SCALE ), Vector3::ZERO, AlphaFunction::EASE_IN_OUT, TimePeriod( 0.0f, duration ) );
+ }
+ }
+ else
+ {
+ mPopupContainer.SetProperty( Actor::Property::SCALE, transitionIn ? Vector3::ONE : Vector3::ZERO );
+ }
+ break;
+ }
- const bool prevAlter = mAlterAddedChild;
- mAlterAddedChild = false;
- Self().Add( mBackgroundImage );
- mAlterAddedChild = prevAlter;
-}
+ case Toolkit::Popup::FADE:
+ {
+ mAnimation = Animation::New( duration );
+ if( duration > Math::MACHINE_EPSILON_0 )
+ {
+ if( transitionIn )
+ {
+ mAnimation.AnimateTo( Property( mPopupContainer, Actor::Property::COLOR_ALPHA ), 1.0f, AlphaFunction::EASE_IN_OUT, TimePeriod( 0.30f, duration * 0.70f ) );
+ }
+ else
+ {
+ mAnimation.AnimateTo( Property( mPopupContainer, Actor::Property::COLOR_ALPHA ), 0.0f, AlphaFunction::EASE_IN_OUT, TimePeriod( 0.0f, duration * 0.70f ) );
+ }
+ }
+ else
+ {
+ mPopupContainer.SetProperty( Actor::Property::OPACITY, transitionIn ? 1.0f : 0.0f );
+ }
+ break;
+ }
-void Popup::SetButtonAreaImage( Actor image )
-{
- // Removes any previous area image.
- if( mButtonAreaImage && mPopupLayout )
- {
- mPopupLayout.Remove( mButtonAreaImage );
- }
+ case Toolkit::Popup::CUSTOM:
+ {
+ // Use a user specified animation for in and out.
+ // Read the correct animation depending on entry or exit.
+ // Attempt to use animation data defined from script data.
+ Dali::AnimationData* animationData = transitionIn ? &mEntryAnimationData : &mExitAnimationData;
- // Adds new area image to the dialog.
- mButtonAreaImage = image;
+ // Create a new animation from the pre-defined data in the AnimationData class.
+ // If there is no data, mAnimation is invalidated.
+ mAnimation = animationData->CreateAnimation( mPopupContainer, duration );
- // OnDialogTouched only consume the event. It prevents the touch event to be caught by the backing.
- mButtonAreaImage.TouchedSignal().Connect( this, &Popup::OnDialogTouched );
+ // If we don't have a valid animation, provide a blank one so play() can still function generically.
+ if( !mAnimation )
+ {
+ // No animation was configured (even though custom mode was specified). Create a dummy animation to avoid an exception.
+ mAnimation = Animation::New( 0.0f );
+ }
- mButtonAreaImage.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
- mButtonAreaImage.SetAnchorPoint( AnchorPoint::CENTER );
- mButtonAreaImage.SetParentOrigin( ParentOrigin::CENTER );
+ break;
+ }
+ }
- if( GetButtonCount() > 0 )
+ // Animate the backing, if enabled.
+ // This is set up last so that different animation modes can have an effect on the backing animation speed.
+ if( mBackingEnabled )
{
- mBottomBg.Add( mButtonAreaImage );
+ // 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 ), targetAlpha, AlphaFunction::EASE_IN_OUT, TimePeriod( 0.0f, duration * 0.70f ) );
+ }
+ else
+ {
+ mAnimation.AnimateTo( Property( mBacking, Actor::Property::COLOR_ALPHA ), 0.0f, AlphaFunction::EASE_IN_OUT, TimePeriod( 0.30f, duration * 0.70f ) );
+ }
+ }
+ else
+ {
+ mBacking.SetProperty( Actor::Property::COLOR_ALPHA, transitionIn ? targetAlpha : 0.0f );
+ }
}
-}
-void Popup::SetTitle( const std::string& text )
-{
- // Replaces the current title actor.
- if( mPopupLayout )
+ // If we are performing the animation instantaneously, jump to the position directly and do not signal.
+ if( instantaneous )
{
- mPopupLayout.RemoveChildAt( Toolkit::TableView::CellPosition( 0, 0 ) );
+ mAnimation.SetCurrentProgress( 1.0f );
+ mAnimation.Play();
}
-
- mTitle = Toolkit::TextLabel::New( text );
- mTitle.SetName( "POPUP_TITLE" );
- mTitle.SetProperty( Toolkit::TextLabel::Property::MULTI_LINE, true );
- mTitle.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
-
- if( mPopupLayout )
+ else if( duration > Math::MACHINE_EPSILON_0 )
{
- mTitle.SetPadding( Padding( 0.0f, 0.0f, mPopupStyle->margin, mPopupStyle->margin ) );
- mTitle.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
- mTitle.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
- mPopupLayout.AddChild( mTitle, Toolkit::TableView::CellPosition( 0, 0 ) );
+ // Run the animation.
+ mAnimation.FinishedSignal().Connect( this, &Popup::OnDisplayChangeAnimationFinished );
+ mAnimation.Play();
+ }
+ else
+ {
+ // We did not use an animation to achive the transition.
+ // Trigger the state change directly.
+ DisplayStateChangeComplete();
}
+}
- RelayoutRequest();
+void Popup::OnDisplayChangeAnimationFinished( Animation& source )
+{
+ DisplayStateChangeComplete();
}
-std::string Popup::GetTitle() const
+void Popup::DisplayStateChangeComplete()
{
- if( mTitle )
+ // Remove contents from stage if completely hidden.
+ if( mDisplayState == Toolkit::Popup::HIDING )
{
- return mTitle.GetProperty<std::string>( Toolkit::TextLabel::Property::TEXT );
- }
+ mDisplayState = Toolkit::Popup::HIDDEN;
- return std::string();
-}
+ mLayer.SetProperty( Actor::Property::VISIBLE, false );
+ mPopupLayout.SetProperty( Actor::Property::SENSITIVE, false );
-void Popup::CreateFooter()
-{
- if( !mBottomBg )
+ // Guard against destruction during signal emission.
+ Toolkit::Popup handle( GetOwner() );
+ mHiddenSignal.Emit();
+ }
+ else if( mDisplayState == Toolkit::Popup::SHOWING )
{
- // Adds bottom background
- mBottomBg = Actor::New();
- mBottomBg.SetName( "POPUP_BOTTOM_BG" );
- mBottomBg.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
+ mDisplayState = Toolkit::Popup::SHOWN;
+ Toolkit::Popup handle( GetOwner() );
+ mShownSignal.Emit();
- mPopupLayout.SetFixedHeight( 2, mPopupStyle->bottomSize.height ); // Buttons
- mPopupLayout.AddChild( mBottomBg, Toolkit::TableView::CellPosition( 2, 0 ) );
+ // Start a timer to auto-hide if enabled.
+ if( mAutoHideDelay > 0u )
+ {
+ mAutoHideTimer = Timer::New( mAutoHideDelay );
+ mAutoHideTimer.TickSignal().Connect( this, &Popup::OnAutoHideTimeReached );
+ mAutoHideTimer.Start();
+ }
}
}
-void Popup::AddButton( Toolkit::Button button )
+bool Popup::OnAutoHideTimeReached()
{
- mButtons.push_back( button );
- button.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::ALL_DIMENSIONS ); // Size will be assigned to it
+ // Display timer has expired, auto hide the popup exactly as if the user had clicked outside.
+ SetDisplayState( Toolkit::Popup::HIDDEN );
- // If this is the first button added
- if( mButtons.size() == 1 )
+ if( mAutoHideTimer )
{
- CreateFooter();
+ mAutoHideTimer.Stop();
+ mAutoHideTimer.TickSignal().Disconnect( this, &Popup::OnAutoHideTimeReached );
+ mAutoHideTimer.Reset();
+ }
+ return true;
+}
- if( mButtonAreaImage )
+void Popup::SetPopupBackgroundImage( Actor image )
+{
+ // Removes any previous background.
+ if( mPopupBackgroundImage )
+ {
+ mPopupBackgroundImage.Unparent();
+ if( mTailImage )
{
- mBottomBg.Add( mButtonAreaImage );
+ mTailImage.Unparent();
}
}
- mBottomBg.Add( button );
+ // Adds new background to the dialog.
+ mPopupBackgroundImage = image;
+ mPopupBackgroundImage.SetProperty( Dali::Actor::Property::NAME, "popupBackgroundImage" );
+ mPopupBackgroundImage.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
+ mPopupBackgroundImage.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
- RelayoutRequest();
-}
+ // OnDialogTouched only consumes the event. It prevents the touch event to be caught by the backing.
+ mPopupBackgroundImage.TouchedSignal().Connect( this, &Popup::OnDialogTouched );
-void Popup::SetState( Toolkit::Popup::PopupState state )
-{
- SetState( state, POPUP_ANIMATION_DURATION );
-}
+ // Set the popup border to be slightly larger than the layout contents.
+ UpdateBackgroundPositionAndSize();
-void Popup::SetState( Toolkit::Popup::PopupState state, float duration )
-{
- // default animation behaviour.
- HandleStateChange(state, duration);
+ const bool prevAlter = mAlterAddedChild;
+ mAlterAddedChild = false;
+ mPopupContainer.Add( mPopupBackgroundImage );
+ mPopupBackgroundImage.LowerToBottom();
+ mAlterAddedChild = prevAlter;
+
+ if( mTailImage )
+ {
+ mPopupBackgroundImage.Add( mTailImage );
+ }
+
+ mLayoutDirty = true;
}
-Toolkit::Popup::PopupState Popup::GetState() const
+Actor Popup::GetPopupBackgroundImage() const
{
- return mState;
+ return mPopupBackgroundImage;
}
-void Popup::ShowTail(const Vector3& position)
+void Popup::SetTitle( Actor titleActor )
{
- // Replaces the tail actor.
- if(mTailImage && mTailImage.GetParent())
+ // Replaces the current title actor.
+ if( !mPopupLayout )
{
- mTailImage.GetParent().Remove( mTailImage );
- mTailImage.Reset();
+ return;
}
- std::string image = "";
-
- // depending on position of tail around ParentOrigin, a different tail image is used...
- if(position.y < Math::MACHINE_EPSILON_1)
- {
- image = mPopupStyle->tailUpImage;
- }
- else if(position.y > 1.0f - Math::MACHINE_EPSILON_1)
- {
- image = mPopupStyle->tailDownImage;
- }
- else if(position.x < Math::MACHINE_EPSILON_1)
- {
- image = mPopupStyle->tailLeftImage;
- }
- else if(position.x > 1.0f - Math::MACHINE_EPSILON_1)
+ if( mTitle )
{
- image = mPopupStyle->tailRightImage;
+ mPopupLayout.RemoveChildAt( Toolkit::TableView::CellPosition( 0, 0) );
}
+ mTitle = titleActor;
- if(image != "")
+ if( mTitle )
{
- Image tail = ResourceImage::New( image );
- mTailImage = ImageActor::New(tail);
- const Vector3 anchorPoint = AnchorPoint::BOTTOM_RIGHT - position;
+ // Set up padding to give sensible default behaviour
+ // (an application developer can later override this if they wish).
+ mTitle.SetProperty( Actor::Property::PADDING, DEFAULT_TITLE_PADDING );
- mTailImage.SetParentOrigin(position);
- mTailImage.SetAnchorPoint(anchorPoint);
-
- CreateFooter();
-
- mBottomBg.Add(mTailImage);
+ mPopupLayout.AddChild( mTitle, Toolkit::TableView::CellPosition( 0, 0 ) );
}
+
+ mLayoutDirty = true;
+ RelayoutRequest();
}
-void Popup::HideTail()
+Actor Popup::GetTitle() const
{
- ShowTail(ParentOrigin::CENTER);
+ return mTitle;
}
-void Popup::SetStyle(PopupStyle& style)
+void Popup::SetContent( Actor content )
{
- mPopupStyle = PopupStylePtr(&style);
- // update //
+ // Remove previous content actor.
+ if( mPopupLayout )
+ {
+ mPopupLayout.RemoveChildAt( Toolkit::TableView::CellPosition( 1, 0 ) );
+ }
+ // Keep a handle to the new content.
+ mContent = content;
+
+ if( mContent )
+ {
+ mContent.SetProperty( Dali::Actor::Property::NAME, "popupContent" );
+
+ mPopupLayout.AddChild( mContent, Toolkit::TableView::CellPosition( 1, 0 ) );
+ }
+
+ mLayoutDirty = true;
+ RelayoutRequest();
}
-PopupStylePtr Popup::GetStyle() const
+Actor Popup::GetContent() const
{
- return mPopupStyle;
+ return mContent;
}
-void Popup::SetDefaultBackgroundImage()
+void Popup::SetFooter( Actor footer )
{
- Image buttonBg = ResourceImage::New( mPopupStyle->buttonAreaImage );
- ImageActor buttonBgImage = ImageActor::New( buttonBg );
- buttonBgImage.SetStyle( ImageActor::STYLE_NINE_PATCH );
- buttonBgImage.SetNinePatchBorder( mPopupStyle->buttonArea9PatchBorder );
+ // Remove previous content actor.
+ if( mPopupLayout )
+ {
+ mPopupLayout.RemoveChildAt( Toolkit::TableView::CellPosition( 2, 0 ) );
+ }
- SetBackgroundImage( ImageActor::New( ResourceImage::New( mPopupStyle->backgroundImage ) ) );
- SetButtonAreaImage( buttonBgImage );
-}
+ // Keep a handle to the new content.
+ mFooter = footer;
-void Popup::CreateBacking()
-{
- mBacking = Dali::Toolkit::CreateSolidColorActor( mPopupStyle->backingColor );
- mBacking.SetName( "POPUP_BACKING" );
+ if( mFooter )
+ {
+ mFooter.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
- mBacking.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
- mBacking.SetSensitive(true);
+ // The control container has a fixed height.
+ mPopupLayout.SetFitHeight( 2u );
+ mPopupLayout.AddChild( footer, Toolkit::TableView::CellPosition( 2, 0 ) );
+ }
- mLayer.Add( mBacking );
- mBacking.SetOpacity(0.0f);
- mBacking.TouchedSignal().Connect( this, &Popup::OnBackingTouched );
- mBacking.WheelEventSignal().Connect(this, &Popup::OnBackingWheelEvent);
+ mLayoutDirty = true;
+ RelayoutRequest();
}
-void Popup::CreateDialog()
+Actor Popup::GetFooter() const
{
- // Adds default background image.
- SetDefaultBackgroundImage();
+ return mFooter;
}
-void Popup::HandleStateChange( Toolkit::Popup::PopupState state, float duration )
+void Popup::SetDisplayState( Toolkit::Popup::DisplayState displayState )
{
- Vector3 targetSize;
- float targetBackingAlpha;
+ // Convert the 4-way state to a bool, true for show, false for hide.
+ bool display = ( displayState == Toolkit::Popup::SHOWING ) || ( displayState == Toolkit::Popup::SHOWN );
- if(mState == state)
+ // Ignore if we are already at the target display state.
+ if( display == ( ( mDisplayState == Toolkit::Popup::SHOWING ) || ( mDisplayState == Toolkit::Popup::SHOWN ) ) )
{
return;
}
- mState = state;
- switch(state)
+
+ // Convert the bool state to the actual display state to use.
+ mDisplayState = display ? Toolkit::Popup::SHOWING : Toolkit::Popup::HIDING;
+
+ if ( display )
{
- case Toolkit::Popup::POPUP_HIDE:
- {
- targetSize = Vector3(0.0f, 0.0f, 1.0f);
- targetBackingAlpha = 0.0f;
- mShowing = false;
- ClearKeyInputFocus();
+ // Update the state to indicate the current intent.
+ mDisplayState = Toolkit::Popup::SHOWING;
- // Retore the keyboard focus when popup is hidden
- if(mPreviousFocusedActor && mPreviousFocusedActor.IsKeyboardFocusable() )
- {
- Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get();
- if( keyboardFocusManager )
- {
- keyboardFocusManager.SetCurrentFocusActor(mPreviousFocusedActor);
- }
- }
+ // We want the popup to have key input focus when it is displayed
+ SetKeyInputFocus();
- break;
- }
+ // We are displaying so bring the popup layer to the front, and set it visible so it is rendered.
+ mLayer.RaiseToTop();
+ mLayer.SetProperty( Actor::Property::VISIBLE, true );
- case Toolkit::Popup::POPUP_SHOW:
- default:
+ // Set up the layout if this is the first display or the layout has become dirty.
+ if( mLayoutDirty )
{
- targetSize = Vector3(1.0f, 1.0f, 1.0f);
- targetBackingAlpha = 1.0f;
- mShowing = true;
+ // Bake-in any style and layout options to create the Popup layout.
+ LayoutPopup();
+ }
- // Add contents to stage for showing.
- if( !mLayer.GetParent() )
- {
- Dali::Stage stage = Dali::Stage::GetCurrent();
- stage.Add( mLayer );
- mLayer.RaiseToTop();
- }
+ // Allow the popup to catch events.
+ mPopupLayout.SetProperty( Actor::Property::SENSITIVE, true );
- Self().SetSensitive(true);
- SetKeyInputFocus();
+ // Handle the keyboard focus when popup is shown.
+ Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get();
+ if( keyboardFocusManager )
+ {
+ mPreviousFocusedActor = keyboardFocusManager.GetCurrentFocusActor();
- // Handle the keyboard focus when popup is shown
- Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get();
- if( keyboardFocusManager )
+ if( Self().GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE ) )
{
- mPreviousFocusedActor = keyboardFocusManager.GetCurrentFocusActor();
-
- if( mContent && mContent.IsKeyboardFocusable() )
+ // Setup the actgor to start focus from.
+ Actor focusActor;
+ if( mContent && mContent.GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE ) )
{
- // If content is focusable, move the focus to content
- keyboardFocusManager.SetCurrentFocusActor(mContent);
+ // If the content is focusable, move the focus to the content.
+ focusActor = mContent;
}
- else if( !mButtons.empty() )
+ else if( mFooter && mFooter.GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE ) )
{
- // Otherwise, movethe focus to the first button
- keyboardFocusManager.SetCurrentFocusActor(mButtons[0]);
+ // If the footer is focusable, move the focus to the footer.
+ focusActor = mFooter;
}
else
{
- DALI_LOG_WARNING("There is no focusable in popup\n");
+ DALI_LOG_WARNING( "There is no focusable in popup\n" );
+ }
+
+ if( focusActor )
+ {
+ keyboardFocusManager.SetCurrentFocusActor( focusActor );
}
}
- break;
}
}
-
- Actor self = Self();
- if(duration > Math::MACHINE_EPSILON_1)
+ else // Not visible.
{
- if ( mAnimation )
+ mDisplayState = Toolkit::Popup::HIDING;
+ ClearKeyInputFocus();
+
+ // Restore the keyboard focus when popup is hidden.
+ if( mPreviousFocusedActor && mPreviousFocusedActor.GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE ) )
{
- mAnimation.Stop();
- mAnimation.Clear();
- mAnimation.Reset();
+ Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get();
+ if( keyboardFocusManager )
+ {
+ keyboardFocusManager.SetCurrentFocusActor( mPreviousFocusedActor );
+ }
}
- mAnimation = Animation::New(duration);
+ }
+
+ // Perform animation.
+ StartTransitionAnimation( display );
+}
+
+Toolkit::Popup::DisplayState Popup::GetDisplayState() const
+{
+ return mDisplayState;
+}
- if(mShowing)
+void Popup::LayoutPopup()
+{
+ mLayoutDirty = false;
+
+ /* When animating in, we want to respect the origin applied to Self().
+ * For example, if zooming, not only will the final result be anchored to the
+ * selected point, but the zoom will originate from this point also.
+ *
+ * EG: ParentOrigin::TOP_LEFT, AnchorPoint::TOP_LEFT :
+ *
+ * -------- --------
+ * |X| |XXX|
+ * |`` Animates |XXX|
+ * | to: |XXX|
+ * | |````
+ * | |
+ */
+ mPopupContainer.SetProperty( Actor::Property::PARENT_ORIGIN, Self().GetCurrentProperty< Vector3 >( Actor::Property::PARENT_ORIGIN ) );
+ mPopupContainer.SetProperty( Actor::Property::ANCHOR_POINT, Self().GetCurrentProperty< Vector3 >( Actor::Property::ANCHOR_POINT ) );
+
+ // If there is only a title, use less padding.
+ if( mTitle )
+ {
+ if( !mContent && !mFooter )
{
- mAnimation.AnimateTo( Property(mBacking, Actor::Property::COLOR_ALPHA), targetBackingAlpha, AlphaFunction::EASE_IN_OUT, TimePeriod(0.0f, duration * 0.5f) );
- mAnimation.AnimateTo( Property(self, Actor::Property::SCALE), targetSize, AlphaFunction::EASE_IN_OUT, TimePeriod(duration * 0.5f, duration * 0.5f) );
+ mTitle.SetProperty( Actor::Property::PADDING, DEFAULT_TITLE_ONLY_PADDING );
}
else
{
- mAnimation.AnimateTo( Property(mBacking, Actor::Property::COLOR_ALPHA), targetBackingAlpha, AlphaFunction::EASE_IN_OUT, TimePeriod(0.0f, duration * 0.5f) );
- mAnimation.AnimateTo( Property(self, Actor::Property::SCALE), targetSize, AlphaFunction::EASE_IN_OUT, TimePeriod(0.0f, duration * 0.5f) );
+ mTitle.SetProperty( Actor::Property::PADDING, DEFAULT_TITLE_PADDING );
}
- mAnimation.Play();
- mAnimation.FinishedSignal().Connect(this, &Popup::OnStateAnimationFinished);
}
- else
- {
- mBacking.SetOpacity( targetBackingAlpha );
- self.SetScale( targetSize );
- HandleStateChangeComplete();
- }
+ // Allow derived classes to perform any layout they may need to do.
+ OnLayoutSetup();
+
+ // Update background visibility.
+ mPopupContainer.SetProperty( Actor::Property::VISIBLE, !( !mFooter && mPopupLayout.GetChildCount() == 0 ) );
+
+ // Create / destroy / position the tail as needed.
+ LayoutTail();
+
+ // Setup any layout and initialisation required for the selected animation.
+ LayoutAnimation();
+
+ RelayoutRequest();
}
-void Popup::HandleStateChangeComplete()
+void Popup::LayoutTail()
{
- // Remove contents from stage if completely hidden.
- if( ( mState == Toolkit::Popup::POPUP_HIDE ) && mLayer.GetParent() )
+ // Removes the tail actor.
+ if( mTailImage && mTailImage.GetParent() )
{
- mLayer.Unparent();
- Self().SetSensitive( false );
-
- // Guard against destruction during signal emission
- Toolkit::Popup handle( GetOwner() );
- mHiddenSignal.Emit();
+ mTailImage.GetParent().Remove( mTailImage );
+ mTailImage.Reset();
+ }
+
+ if( !mTailVisible )
+ {
+ return;
+ }
+
+ 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( parentOrigin.y < Math::MACHINE_EPSILON_1 )
+ {
+ image = mTailUpImage;
+ anchorPoint = AnchorPoint::BOTTOM_CENTER;
+ position.y = mBackgroundBorder.top;
+ }
+ else if( parentOrigin.y > ( 1.0f - Math::MACHINE_EPSILON_1 ) )
+ {
+ image = mTailDownImage;
+ anchorPoint = AnchorPoint::TOP_CENTER;
+ position.y = - mBackgroundBorder.bottom;
+ }
+ else if( parentOrigin.x < Math::MACHINE_EPSILON_1 )
+ {
+ image = mTailLeftImage;
+ anchorPoint = AnchorPoint::CENTER_RIGHT;
+ position.x = mBackgroundBorder.left;
+ }
+ 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.
+ mTailImage = Toolkit::ImageView::New( image );
+ mTailImage.SetProperty( Dali::Actor::Property::NAME, "tailImage" );
+ mTailImage.SetProperty( Actor::Property::PARENT_ORIGIN, parentOrigin );
+ mTailImage.SetProperty( Actor::Property::ANCHOR_POINT, anchorPoint );
+ mTailImage.SetProperty( Actor::Property::POSITION, position );
+
+ if( mPopupBackgroundImage )
+ {
+ mPopupBackgroundImage.Add( mTailImage );
+ }
}
}
+void Popup::SetContextualMode( Toolkit::Popup::ContextualMode mode )
+{
+ mContextualMode = mode;
+ mLayoutDirty = true;
+}
+
+Toolkit::Popup::ContextualMode Popup::GetContextualMode() const
+{
+ return mContextualMode;
+}
+
+Toolkit::Control Popup::CreateBacking()
+{
+ Toolkit::Control backing = Control::New();
+ backing.SetProperty( Toolkit::Control::Property::BACKGROUND,
+ Property::Map().Add( Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR )
+ .Add( Toolkit::ColorVisual::Property::MIX_COLOR, Vector4( mBackingColor.r, mBackingColor.g, mBackingColor.b, 1.0f ) ) );
+ backing.SetProperty( Dali::Actor::Property::NAME, "popupBacking" );
+
+ // Must always be positioned top-left of stage, regardless of parent.
+ backing.SetProperty( Actor::Property::INHERIT_POSITION, false );
+
+ // Always the full size of the stage.
+ backing.SetResizePolicy( ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS );
+ backing.SetProperty( Actor::Property::SIZE, Stage::GetCurrent().GetSize() );
+
+ // Catch events.
+ backing.SetProperty( Actor::Property::SENSITIVE, true );
+
+ // Default to being transparent.
+ backing.SetProperty( Actor::Property::COLOR_ALPHA, 0.0f );
+ backing.TouchedSignal().Connect( this, &Popup::OnBackingTouched );
+ backing.WheelEventSignal().Connect( this, &Popup::OnBackingWheelEvent );
+ return backing;
+}
+
Toolkit::Popup::TouchedOutsideSignalType& Popup::OutsideTouchedSignal()
{
return mTouchedOutsideSignal;
}
-Toolkit::Popup::HiddenSignalType& Popup::HiddenSignal()
+Toolkit::Popup::DisplayStateChangeSignalType& Popup::ShowingSignal()
+{
+ return mShowingSignal;
+}
+
+Toolkit::Popup::DisplayStateChangeSignalType& Popup::ShownSignal()
+{
+ return mShownSignal;
+}
+
+Toolkit::Popup::DisplayStateChangeSignalType& Popup::HidingSignal()
+{
+ return mHidingSignal;
+}
+
+Toolkit::Popup::DisplayStateChangeSignalType& Popup::HiddenSignal()
{
return mHiddenSignal;
}
+void Popup::SetTailVisibility( bool visible )
+{
+ mTailVisible = visible;
+ mLayoutDirty = true;
+}
+
+const bool Popup::IsTailVisible() const
+{
+ return mTailVisible;
+}
+
+void Popup::SetTailPosition( Vector3 position )
+{
+ mTailPosition = position;
+ mLayoutDirty = true;
+}
+
+const Vector3& Popup::GetTailPosition() const
+{
+ return mTailPosition;
+}
+
+void Popup::SetAnimationDuration( float duration )
+{
+ mAnimationDuration = duration;
+ mLayoutDirty = true;
+}
+
+float Popup::GetAnimationDuration() const
+{
+ return mAnimationDuration;
+}
+
+void Popup::SetAnimationMode( Toolkit::Popup::AnimationMode animationMode )
+{
+ mAnimationMode = animationMode;
+ mLayoutDirty = true;
+}
+
+Toolkit::Popup::AnimationMode Popup::GetAnimationMode() const
+{
+ return mAnimationMode;
+}
+
+void Popup::SetEntryAnimationData( const Property::Map& map )
+{
+ mEntryAnimationData.Clear();
+ Scripting::NewAnimation( map, mEntryAnimationData );
+}
+
+void Popup::SetExitAnimationData( const Property::Map& map )
+{
+ mExitAnimationData.Clear();
+ Scripting::NewAnimation( map, mExitAnimationData );
+}
+
+void Popup::UpdateBackgroundPositionAndSize()
+{
+ if( mPopupBackgroundImage )
+ {
+ mPopupBackgroundImage.SetResizePolicy( ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT, Dimension::ALL_DIMENSIONS );
+ mPopupBackgroundImage.SetProperty( Actor::Property::SIZE_MODE_FACTOR, 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.SetProperty( Actor::Property::POSITION, Vector2( ( mBackgroundBorder.right - mBackgroundBorder.left ) * 0.5f, ( mBackgroundBorder.bottom - mBackgroundBorder.top ) * 0.5f ));
+ }
+}
+
+void Popup::SetAutoHideDelay( int delay )
+{
+ mAutoHideDelay = delay;
+}
+
+int Popup::GetAutoHideDelay() const
+{
+ return mAutoHideDelay;
+}
+
+void Popup::SetBackingEnabled( bool enabled )
+{
+ mBackingEnabled = enabled;
+ mLayoutDirty = true;
+}
+
+const bool Popup::IsBackingEnabled() const
+{
+ return mBackingEnabled;
+}
+
+void Popup::SetBackingColor( Vector4 color )
+{
+ mBackingColor = color;
+ mBacking.SetBackgroundColor( Vector4( color.r, color.g, color.b, 1.0f ) );
+ mLayoutDirty = true;
+}
+
+const Vector4& Popup::GetBackingColor() const
+{
+ return mBackingColor;
+}
+
+void Popup::SetTailUpImage( std::string image )
+{
+ mTailUpImage = image;
+ mLayoutDirty = true;
+ LayoutTail();
+}
+
+const std::string& Popup::GetTailUpImage() const
+{
+ return mTailUpImage;
+}
+
+void Popup::SetTailDownImage( std::string image )
+{
+ mTailDownImage = image;
+ mLayoutDirty = true;
+ LayoutTail();
+}
+
+const std::string& Popup::GetTailDownImage() const
+{
+ return mTailDownImage;
+}
+
+void Popup::SetTailLeftImage( std::string image )
+{
+ mTailLeftImage = image;
+ mLayoutDirty = true;
+ LayoutTail();
+}
+
+const std::string& Popup::GetTailLeftImage() const
+{
+ return mTailLeftImage;
+}
+
+void Popup::SetTailRightImage( std::string image )
+{
+ mTailRightImage = image;
+ mLayoutDirty = true;
+ LayoutTail();
+}
+
+const std::string& Popup::GetTailRightImage() const
+{
+ return mTailRightImage;
+}
+
+void Popup::SetTouchTransparent( bool enabled )
+{
+ mTouchTransparent = enabled;
+}
+
+const bool Popup::IsTouchTransparent() const
+{
+ return mTouchTransparent;
+}
+
+void Popup::SetProperty( BaseObject* object, Property::Index propertyIndex, const Property::Value& value )
+{
+ Toolkit::Popup popup = Toolkit::Popup::DownCast( Dali::BaseHandle( object ) );
+
+ if ( popup )
+ {
+ Popup& popupImpl( GetImpl( popup ) );
+
+ switch ( propertyIndex )
+ {
+ case Toolkit::Popup::Property::TITLE:
+ {
+ Property::Map valueMap;
+ if( value.Get( valueMap ) )
+ {
+ popupImpl.SetTitle( Scripting::NewActor( valueMap ) );
+ }
+ break;
+ }
+ case Toolkit::Popup::Property::CONTENT:
+ {
+ Property::Map valueMap;
+ if( value.Get( valueMap ) )
+ {
+ popupImpl.SetContent( Scripting::NewActor( valueMap ) );
+ }
+ break;
+ }
+ case Toolkit::Popup::Property::FOOTER:
+ {
+ Property::Map valueMap;
+ if( value.Get( valueMap ) )
+ {
+ popupImpl.SetFooter( Scripting::NewActor( valueMap ) );
+ }
+ break;
+ }
+ case Toolkit::Popup::Property::DISPLAY_STATE:
+ {
+ std::string valueString;
+ if( value.Get( valueString ) )
+ {
+ Toolkit::Popup::DisplayState displayState( Toolkit::Popup::HIDDEN );
+ if( Scripting::GetEnumeration< Toolkit::Popup::DisplayState >( valueString.c_str(), DisplayStateTable, DisplayStateTableCount, displayState ) )
+ {
+ popupImpl.SetDisplayState( displayState );
+ }
+ }
+ break;
+ }
+ case Toolkit::Popup::Property::TOUCH_TRANSPARENT:
+ {
+ bool valueBool;
+ if( value.Get( valueBool ) )
+ {
+ popupImpl.SetTouchTransparent( valueBool );
+ }
+ break;
+ }
+ case Toolkit::Popup::Property::TAIL_VISIBILITY:
+ {
+ bool valueBool;
+ if( value.Get( valueBool ) )
+ {
+ popupImpl.SetTailVisibility( valueBool );
+ }
+ break;
+ }
+ case Toolkit::Popup::Property::TAIL_POSITION:
+ {
+ Vector3 valueVector3;
+ if( value.Get( valueVector3 ) )
+ {
+ popupImpl.SetTailPosition( valueVector3 );
+ }
+ break;
+ }
+ case Toolkit::Popup::Property::CONTEXTUAL_MODE:
+ {
+ std::string valueString;
+ if( value.Get( valueString ) )
+ {
+ Toolkit::Popup::ContextualMode contextualMode( Toolkit::Popup::BELOW );
+ if( Scripting::GetEnumeration< Toolkit::Popup::ContextualMode >( valueString.c_str(), ContextualModeTable, ContextualModeTableCount, contextualMode ) )
+ {
+ popupImpl.SetContextualMode( contextualMode );
+ }
+ }
+ break;
+ }
+ case Toolkit::Popup::Property::ANIMATION_DURATION:
+ {
+ float valueFloat;
+ if( value.Get( valueFloat ) )
+ {
+ popupImpl.SetAnimationDuration( valueFloat );
+ }
+ break;
+ }
+ case Toolkit::Popup::Property::ANIMATION_MODE:
+ {
+ std::string valueString;
+ if( value.Get( valueString ) )
+ {
+ Toolkit::Popup::AnimationMode animationMode( Toolkit::Popup::FADE );
+ if( Scripting::GetEnumeration< Toolkit::Popup::AnimationMode >( valueString.c_str(), AnimationModeTable, AnimationModeTableCount, animationMode ) )
+ {
+ popupImpl.SetAnimationMode( animationMode );
+ }
+ }
+ break;
+ }
+ case Toolkit::Popup::Property::ENTRY_ANIMATION:
+ {
+ Property::Map valueMap;
+ if( value.Get( valueMap ) )
+ {
+ popupImpl.SetEntryAnimationData( valueMap );
+ }
+ break;
+ }
+ case Toolkit::Popup::Property::EXIT_ANIMATION:
+ {
+ Property::Map valueMap;
+ if( value.Get( valueMap ) )
+ {
+ popupImpl.SetExitAnimationData( valueMap );
+ }
+ break;
+ }
+ case Toolkit::Popup::Property::AUTO_HIDE_DELAY:
+ {
+ int valueInt;
+ if( value.Get( valueInt ) )
+ {
+ popupImpl.SetAutoHideDelay( valueInt );
+ }
+ break;
+ }
+ case Toolkit::Popup::Property::BACKING_ENABLED:
+ {
+ bool valueBool;
+ if( value.Get( valueBool ) )
+ {
+ popupImpl.SetBackingEnabled( valueBool );
+ }
+ break;
+ }
+ case Toolkit::Popup::Property::BACKING_COLOR:
+ {
+ Vector4 valueVector4;
+ if( value.Get( valueVector4 ) )
+ {
+ popupImpl.SetBackingColor( valueVector4 );
+ }
+ break;
+ }
+ case Toolkit::Popup::Property::POPUP_BACKGROUND_IMAGE:
+ {
+ std::string valueString;
+ if( value.Get( valueString ) )
+ {
+ 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;
+ }
+ case Toolkit::Popup::Property::TAIL_UP_IMAGE:
+ {
+ std::string valueString;
+ if( value.Get( valueString ) )
+ {
+ popupImpl.SetTailUpImage( valueString );
+ }
+ break;
+ }
+ case Toolkit::Popup::Property::TAIL_DOWN_IMAGE:
+ {
+ std::string valueString;
+ if( value.Get( valueString ) )
+ {
+ popupImpl.SetTailDownImage( valueString );
+ }
+ break;
+ }
+ case Toolkit::Popup::Property::TAIL_LEFT_IMAGE:
+ {
+ std::string valueString;
+ if( value.Get( valueString ) )
+ {
+ popupImpl.SetTailLeftImage( valueString );
+ }
+ break;
+ }
+ case Toolkit::Popup::Property::TAIL_RIGHT_IMAGE:
+ {
+ std::string valueString;
+ if( value.Get( valueString ) )
+ {
+ popupImpl.SetTailRightImage( valueString );
+ }
+ break;
+ }
+ }
+ }
+}
+
+Property::Value Popup::GetProperty( BaseObject* object, Property::Index propertyIndex )
+{
+ Property::Value value;
+
+ Toolkit::Popup popup = Toolkit::Popup::DownCast( Dali::BaseHandle( object ) );
+
+ if ( popup )
+ {
+ Popup& popupImpl( GetImpl( popup ) );
+
+ switch ( propertyIndex )
+ {
+ case Toolkit::Popup::Property::TITLE:
+ {
+ Property::Map map;
+ Scripting::CreatePropertyMap( popupImpl.GetTitle(), map );
+ value = map;
+ break;
+ }
+ case Toolkit::Popup::Property::CONTENT:
+ {
+ Property::Map map;
+ Scripting::CreatePropertyMap( popupImpl.GetContent(), map );
+ value = map;
+ break;
+ }
+ case Toolkit::Popup::Property::FOOTER:
+ {
+ Property::Map map;
+ Scripting::CreatePropertyMap( popupImpl.GetFooter(), map );
+ value = map;
+ break;
+ }
+ case Toolkit::Popup::Property::DISPLAY_STATE:
+ {
+ value = Scripting::GetLinearEnumerationName< Toolkit::Popup::DisplayState >( popupImpl.GetDisplayState(), DisplayStateTable, DisplayStateTableCount );
+ break;
+ }
+ case Toolkit::Popup::Property::TOUCH_TRANSPARENT:
+ {
+ value = popupImpl.IsTouchTransparent();
+ break;
+ }
+ case Toolkit::Popup::Property::TAIL_VISIBILITY:
+ {
+ value = popupImpl.IsTailVisible();
+ break;
+ }
+ case Toolkit::Popup::Property::TAIL_POSITION:
+ {
+ value = popupImpl.GetTailPosition();
+ break;
+ }
+ case Toolkit::Popup::Property::CONTEXTUAL_MODE:
+ {
+ value = Scripting::GetLinearEnumerationName< Toolkit::Popup::ContextualMode >( popupImpl.GetContextualMode(), ContextualModeTable, ContextualModeTableCount );
+ break;
+ }
+ case Toolkit::Popup::Property::ANIMATION_DURATION:
+ {
+ value = popupImpl.GetAnimationDuration();
+ break;
+ }
+ case Toolkit::Popup::Property::ANIMATION_MODE:
+ {
+ value = Scripting::GetLinearEnumerationName< Toolkit::Popup::AnimationMode >( popupImpl.GetAnimationMode(), AnimationModeTable, AnimationModeTableCount );
+ break;
+ }
+ case Toolkit::Popup::Property::ENTRY_ANIMATION:
+ {
+ // Note: Cannot retrieve property map from animation.
+ Property::Map map;
+ value = map;
+ break;
+ }
+ case Toolkit::Popup::Property::EXIT_ANIMATION:
+ {
+ // Note: Cannot retrieve property map from animation.
+ Property::Map map;
+ value = map;
+ break;
+ }
+ case Toolkit::Popup::Property::AUTO_HIDE_DELAY:
+ {
+ value = popupImpl.GetAutoHideDelay();
+ break;
+ }
+ case Toolkit::Popup::Property::BACKING_ENABLED:
+ {
+ value = popupImpl.IsBackingEnabled();
+ break;
+ }
+ case Toolkit::Popup::Property::BACKING_COLOR:
+ {
+ value = popupImpl.GetBackingColor();
+ break;
+ }
+ case Toolkit::Popup::Property::POPUP_BACKGROUND_IMAGE:
+ {
+ Toolkit::ImageView imageView = Toolkit::ImageView::DownCast( popupImpl.GetPopupBackgroundImage() );
+ if( imageView )
+ {
+ 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();
+ break;
+ }
+ case Toolkit::Popup::Property::TAIL_DOWN_IMAGE:
+ {
+ value = popupImpl.GetTailDownImage();
+ break;
+ }
+ case Toolkit::Popup::Property::TAIL_LEFT_IMAGE:
+ {
+ value = popupImpl.GetTailLeftImage();
+ break;
+ }
+ case Toolkit::Popup::Property::TAIL_RIGHT_IMAGE:
+ {
+ value = popupImpl.GetTailRightImage();
+ break;
+ }
+ }
+ }
+
+ return value;
+}
+
bool Popup::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
{
Dali::BaseHandle handle( object );
{
popup.OutsideTouchedSignal().Connect( tracker, functor );
}
+ else if( 0 == strcmp( signalName.c_str(), SIGNAL_SHOWING ) )
+ {
+ popup.ShowingSignal().Connect( tracker, functor );
+ }
+ else if( 0 == strcmp( signalName.c_str(), SIGNAL_SHOWN ) )
+ {
+ popup.ShownSignal().Connect( tracker, functor );
+ }
+ else if( 0 == strcmp( signalName.c_str(), SIGNAL_HIDING ) )
+ {
+ popup.HidingSignal().Connect( tracker, functor );
+ }
else if( 0 == strcmp( signalName.c_str(), SIGNAL_HIDDEN ) )
{
popup.HiddenSignal().Connect( tracker, functor );
return connected;
}
-void Popup::OnStateAnimationFinished( Animation& source )
+bool Popup::OnBackingTouched( Actor actor, const TouchEvent& touch )
{
- HandleStateChangeComplete();
-}
-
-bool Popup::OnBackingTouched(Actor actor, const TouchEvent& event)
-{
- if(event.GetPointCount()>0)
+ // Allow events to pass through if touch transparency is enabled.
+ if( mTouchTransparent )
{
- const TouchPoint& point = event.GetPoint(0);
+ return false;
+ }
- if(point.state == TouchPoint::Down)
+ if( touch.GetPointCount() > 0 )
+ {
+ if( touch.GetState( 0 ) == PointState::DOWN )
{
- // Guard against destruction during signal emission
+ // Guard against destruction during signal emission.
Toolkit::Popup handle( GetOwner() );
mTouchedOutsideSignal.Emit();
}
}
+ // Block anything behind backing becoming touched.
+ mLayer.SetProperty( Layer::Property::CONSUMES_TOUCH, true );
return true;
}
-bool Popup::OnBackingWheelEvent(Actor actor, const WheelEvent& event)
+bool Popup::OnBackingWheelEvent( Actor actor, const WheelEvent& event )
{
- // consume wheel event in dimmed backing actor
+ // Allow events to pass through if touch transparency is enabled.
+ if( mTouchTransparent )
+ {
+ return false;
+ }
+
+ // Consume wheel event in dimmed backing actor.
+ mLayer.SetProperty( Layer::Property::CONSUMES_TOUCH, true );
return true;
}
-bool Popup::OnDialogTouched(Actor actor, const TouchEvent& event)
+bool Popup::OnDialogTouched( Actor actor, const TouchEvent& touch )
{
- // consume event (stops backing actor receiving touch events)
+ // Allow events to pass through if touch transparency is enabled.
+ if( mTouchTransparent )
+ {
+ return false;
+ }
+
+ // Consume event (stops backing actor receiving touch events)
+ mLayer.SetProperty( Layer::Property::CONSUMES_TOUCH, true );
return true;
}
-void Popup::OnControlChildAdd( Actor& child )
+void Popup::OnSceneConnection( int depth )
{
- // reparent any children added by user to the body layer.
- if( mAlterAddedChild )
- {
- // Removes previously added content.
- if( mContent )
- {
- mPopupLayout.RemoveChildAt( Toolkit::TableView::CellPosition( 1, 0 ) );
- }
-
- // keep a handle to the new content.
- mContent = child;
+ mLayoutDirty = true;
+ RelayoutRequest();
- mPopupLayout.AddChild( mContent, Toolkit::TableView::CellPosition( 1, 0 ) );
- }
+ Control::OnSceneConnection( depth );
}
-void Popup::OnRelayout( const Vector2& size, RelayoutContainer& container )
+void Popup::OnChildAdd( Actor& child )
{
- // Hide the background image
- mBackgroundImage.SetVisible( !( mButtons.empty() && mPopupLayout.GetChildCount() == 0 ) );
-
- // Relayout All buttons
- if( !mButtons.empty() )
+ // Re-parent any children added by user to the body layer.
+ if( mAlterAddedChild )
{
- // All buttons should be the same size and fill the button area. The button spacing needs to be accounted for as well.
- Vector2 buttonSize( ( ( size.width - mPopupStyle->buttonSpacing * ( mButtons.size() + 1 ) ) / mButtons.size() ),
- mPopupStyle->bottomSize.height - mPopupStyle->margin );
-
- Vector3 buttonPosition( mPopupStyle->buttonSpacing, 0.0f, 0.0f );
+ SetContent( child );
+ }
+ else
+ {
+ mLayoutDirty = true;
+ RelayoutRequest();
+ }
- for( std::vector< Actor >::iterator iter = mButtons.begin(), endIter = mButtons.end();
- iter != endIter;
- ++iter, buttonPosition.x += mPopupStyle->buttonSpacing + buttonSize.width )
- {
- Actor button = *iter;
+ Control::OnChildAdd( child );
+}
- // If there is only one button, it needs to be laid out on center.
- if ( mButtons.size() == 1 )
- {
- buttonPosition.x = 0.0f;
- button.SetAnchorPoint( AnchorPoint::CENTER );
- button.SetParentOrigin( ParentOrigin::CENTER );
- }
- else
- {
- button.SetAnchorPoint( AnchorPoint::CENTER_LEFT );
- button.SetParentOrigin( ParentOrigin::CENTER_LEFT );
- }
+void Popup::LayoutContext( const Vector2& size )
+{
+ // Do nothing if not in a contextual mode (or there is no parent context).
+ Actor self = Self();
+ Actor parent = self.GetParent();
+ if( ( mContextualMode == Toolkit::Popup::NON_CONTEXTUAL ) || !parent )
+ {
+ return;
+ }
- button.SetPosition( buttonPosition );
+ mPopupContainer.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
+ // We always anchor to the CENTER, rather than a different anchor point for each contextual
+ // mode to allow code-reuse of the bound checking code (for maintainability).
+ mPopupContainer.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
- //Todo: Use the size negotiation pass instead of SetSize directly
- button.SetSize( buttonSize );
- }
- }
-}
+ // Setup with some pre-calculations for speed.
+ Vector3 halfStageSize( Stage().GetCurrent().GetSize() / 2.0f );
+ Vector3 parentPosition( parent.GetCurrentProperty< Vector3 >( Actor::Property::POSITION ) );
+ Vector2 halfSize( size / 2.0f );
+ Vector2 halfParentSize( parent.GetRelayoutSize( Dimension::WIDTH ) / 2.0f, parent.GetRelayoutSize( Dimension::HEIGHT ) / 2.0f );
+ Vector3 newPosition( Vector3::ZERO );
-void Popup::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
-{
- if( mPopupLayout )
+ // Perform different positioning based on the specified contextual layout mode.
+ switch( mContextualMode )
{
- if( policy == ResizePolicy::FIT_TO_CHILDREN )
+ case Toolkit::Popup::BELOW:
{
- mPopupLayout.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, dimension );
- if( dimension & Dimension::HEIGHT )
- {
- mPopupLayout.SetFitHeight( 1 );
- }
+ newPosition.x += halfSize.x - halfParentSize.x;
+ newPosition.y += halfSize.y + halfParentSize.y + DEFAULT_CONTEXTUAL_ADJACENCY_MARGIN.y;
+ break;
}
- else
+ case Toolkit::Popup::ABOVE:
{
- mPopupLayout.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, dimension );
- // Make the content cell fill the whole of the available space
- if( dimension & Dimension::HEIGHT )
- {
- mPopupLayout.SetRelativeHeight( 1, 1.0f );
- }
+ newPosition.x += halfSize.x - halfParentSize.x;
+ newPosition.y -= halfSize.y + halfParentSize.y + DEFAULT_CONTEXTUAL_ADJACENCY_MARGIN.y;
+ break;
+ }
+ case Toolkit::Popup::RIGHT:
+ {
+ newPosition.x += halfSize.x + halfParentSize.x + DEFAULT_CONTEXTUAL_ADJACENCY_MARGIN.x;
+ newPosition.y += halfSize.y - halfParentSize.y;
+ break;
+ }
+ case Toolkit::Popup::LEFT:
+ {
+ newPosition.x -= halfSize.x + halfParentSize.x + DEFAULT_CONTEXTUAL_ADJACENCY_MARGIN.x;
+ newPosition.y += halfSize.y - halfParentSize.y;
+ break;
+ }
+ case Toolkit::Popup::NON_CONTEXTUAL:
+ {
+ // Code won't reach here (caught earlier).
+ break;
}
}
-}
-bool Popup::OnKeyEvent(const KeyEvent& event)
-{
- bool consumed = false;
-
- if(event.state == KeyEvent::Down)
+ // On-screen position checking.
+ // Check new position is not too far right. If so, correct it.
+ // Note: Check for right rather than left first, so if popup is too wide, the left check overrides
+ // the right check and we at least see the left portion of the popup (as this is more useful).
+ if( newPosition.x >= ( halfStageSize.x - parentPosition.x - halfSize.x - DEFAULT_CONTEXTUAL_STAGE_BORDER.x ) )
{
- if (event.keyCode == Dali::DALI_KEY_ESCAPE || event.keyCode == Dali::DALI_KEY_BACK)
- {
- SetState(Toolkit::Popup::POPUP_HIDE);
- consumed = true;
- }
+ newPosition.x = halfStageSize.x - parentPosition.x - halfSize.x - DEFAULT_CONTEXTUAL_STAGE_BORDER.x;
+ }
+ // Check new position is not too far left. If so, correct it.
+ if( newPosition.x < halfSize.x - ( parentPosition.x + halfStageSize.x ) + DEFAULT_CONTEXTUAL_STAGE_BORDER.x )
+ {
+ newPosition.x = halfSize.x - ( parentPosition.x + halfStageSize.x ) + DEFAULT_CONTEXTUAL_STAGE_BORDER.x;// - parentSize.x;
+ }
+ // Check new position is not too far down. If so, correct it.
+ if( newPosition.y >= ( halfStageSize.y - parentPosition.y - halfSize.y - DEFAULT_CONTEXTUAL_STAGE_BORDER.y ) )
+ {
+ newPosition.y = halfStageSize.y - parentPosition.y - halfSize.y - DEFAULT_CONTEXTUAL_STAGE_BORDER.y;
+ }
+ // Check new position is not too far up. If so, correct it.
+ if( newPosition.y < halfSize.y - ( parentPosition.y + halfStageSize.y ) + DEFAULT_CONTEXTUAL_STAGE_BORDER.y )
+ {
+ newPosition.y = halfSize.y - ( parentPosition.y + halfStageSize.y ) + DEFAULT_CONTEXTUAL_STAGE_BORDER.y;
}
- return consumed;
+ // Set the final position.
+ mPopupContainer.SetProperty( Actor::Property::POSITION, newPosition );
}
-Vector3 Popup::GetNaturalSize()
+void Popup::OnRelayout( const Vector2& size, RelayoutContainer& container )
{
- float margin = 2.0f * ( POPUP_OUT_MARGIN_WIDTH + mPopupStyle->margin );
- const float maxWidth = Stage::GetCurrent().GetSize().width - margin;
+ Vector2 useSize( size );
+
+ // Use the Popup layouts size, unless requested to use a fixed size.
+ // In which case take the size set for the Popup itself.
+ ResizePolicy::Type widthPolicy = Self().GetResizePolicy( Dimension::WIDTH );
+ ResizePolicy::Type heightPolicy = Self().GetResizePolicy( Dimension::HEIGHT );
- Vector3 naturalSize( 0.0f, 0.0f, 0.0f );
+ // Width calculations:
+ if( widthPolicy == ResizePolicy::USE_NATURAL_SIZE || widthPolicy == ResizePolicy::FIT_TO_CHILDREN )
+ {
+ // If we using a child-based policy, take the size from the popup layout.
+ mPopupLayout.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::WIDTH );
+ useSize.width = mPopupLayout.GetRelayoutSize( Dimension::WIDTH );
- if ( mTitle )
+ mPopupLayout.SetFitWidth( 0u );
+ }
+ else
{
- Vector3 titleNaturalSize = mTitle.GetImplementation().GetNaturalSize();
- // Buffer to avoid errors. The width of the popup could potentially be the width of the title text.
- // It was observed in this case that text wrapping was then inconsistent when seen on device
- const float titleBuffer = 0.5f;
- titleNaturalSize.width += titleBuffer;
+ // If we using a parent-based policy, take the size from the popup object itself (self).
+ mPopupLayout.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::WIDTH );
+
+ mPopupLayout.SetFixedWidth( 0u, useSize.width );
+ }
+
+ // Height calculations:
+ // Title: Let the title be as high as it needs to be.
+ mPopupLayout.SetFitHeight( 0u );
- // As TextLabel GetNaturalSize does not take wrapping into account, limit the width
- // to that of the stage
- if( titleNaturalSize.width >= maxWidth)
+ // Footer: Convert the footer's resize policy to a TableView row policy.
+ if( mFooter )
+ {
+ ResizePolicy::Type footerHeightPolicy = mFooter.GetResizePolicy( Dimension::HEIGHT );
+ if( ( footerHeightPolicy == ResizePolicy::USE_NATURAL_SIZE ) ||
+ ( footerHeightPolicy == ResizePolicy::FIT_TO_CHILDREN ) )
{
- naturalSize.width = maxWidth;
- naturalSize.height = mTitle.GetImplementation().GetHeightForWidth( naturalSize.width );
+ mPopupLayout.SetFitHeight( 2u );
+ }
+ else if( footerHeightPolicy == ResizePolicy::FIXED )
+ {
+ mPopupLayout.SetFixedHeight( 2u, mFooter.GetRelayoutSize( Dimension::HEIGHT) );
}
else
{
- naturalSize += titleNaturalSize;
+ mPopupLayout.SetRelativeHeight( 2u, 1.0f );
}
+ }
+ else
+ {
+ mPopupLayout.SetFixedHeight( 2u, 0.0f );
+ }
+
+ // Popup contents: Adjust the tableview's policies based on the popup's policies.
+ if( heightPolicy == ResizePolicy::USE_NATURAL_SIZE || heightPolicy == ResizePolicy::FIT_TO_CHILDREN )
+ {
+ mPopupLayout.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT );
- naturalSize.height += mPopupStyle->margin;
+ // Let both the contents expand as necessary.
+ mPopupLayout.SetFitHeight( 1u );
+ useSize.height = mPopupLayout.GetRelayoutSize( Dimension::HEIGHT );
}
+ else
+ {
+ mPopupLayout.SetResizePolicy( heightPolicy, Dimension::HEIGHT );
+
+ // Let the content expand to fill the remaining space.
+ mPopupLayout.SetRelativeHeight( 1u, 1.0f );
+ mPopupLayout.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::HEIGHT );
+ }
+
+ // Relayout the popup-layout to give it it's new size this frame.
+ container.Add( mPopupLayout, useSize );
if( mContent )
{
- Vector3 contentSize = mContent.GetNaturalSize();
- // Choose the biggest width
- naturalSize.width = std::max( naturalSize.width, contentSize.width );
- if( naturalSize.width > maxWidth )
- {
- naturalSize.width = maxWidth;
- contentSize.height = mContent.GetHeightForWidth( maxWidth );
- }
- naturalSize.height += contentSize.height + mPopupStyle->margin;
+ container.Add( mContent, Vector2( mContent.GetRelayoutSize( Dimension::WIDTH ), mContent.GetRelayoutSize( Dimension::HEIGHT ) ) );
}
- if( !mButtons.empty() )
+ // Perform contextual layout setup if required.
+ // This is done each time in case the parent moves.
+ // This will have no effect if no contextual mode is selected.
+ LayoutContext( useSize );
+}
+
+void Popup::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
+{
+ // To get the popup to emulate fit-to-children, we need to actually set use-natural-size.
+ if( ( dimension & Dimension::HEIGHT ) && ( policy == ResizePolicy::FIT_TO_CHILDREN ) )
{
- naturalSize.height += mPopupStyle->bottomSize.height;
+ Self().SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT );
}
- // Add the margins
- naturalSize.width += margin;
- naturalSize.height += margin;
+ mLayoutDirty = true;
+ return;
+}
- return naturalSize;
+Vector3 Popup::GetNaturalSize()
+{
+ return mPopupLayout.GetNaturalSize();
}
float Popup::GetHeightForWidth( float width )
{
- float height( 0.0f );
- float popupWidth( width - 2.f * ( POPUP_OUT_MARGIN_WIDTH + mPopupStyle->margin ) );
+ return mPopupLayout.GetHeightForWidth( width );
+}
+
+float Popup::GetWidthForHeight( float height )
+{
+ return mPopupLayout.GetWidthForHeight( height );
+}
- if ( mTitle )
+bool Popup::OnKeyEvent( const KeyEvent& event )
+{
+ // Allow events to pass through if touch transparency is enabled.
+ if( mTouchTransparent )
{
- height += mTitle.GetImplementation().GetHeightForWidth( popupWidth );
- height += mPopupStyle->margin;
+ return false;
}
- if( mContent )
+ bool consumed = false;
+
+ if( event.GetState() == KeyEvent::DOWN )
{
- height += mContent.GetHeightForWidth( popupWidth ) + mPopupStyle->margin;
+ if (event.GetKeyCode() == Dali::DALI_KEY_ESCAPE || event.GetKeyCode() == Dali::DALI_KEY_BACK)
+ {
+ SetDisplayState( Toolkit::Popup::HIDDEN );
+ consumed = true;
+ }
}
- if( !mButtons.empty() )
+ return consumed;
+}
+
+void Popup::AddFocusableChildrenRecursive( Actor parent, std::vector< Actor >& focusableActors )
+{
+ if( parent )
{
- height += mPopupStyle->bottomSize.height;
- }
+ Toolkit::Control control = Toolkit::Control::DownCast( parent );
+ bool layoutControl = control && GetImplementation( control ).IsKeyboardNavigationSupported();
- // Add the margins
- float margin( 2.0f * ( POPUP_OUT_MARGIN_WIDTH + mPopupStyle->margin ) );
- height += margin;
+ if( parent.GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE ) || layoutControl )
+ {
+ focusableActors.push_back( parent );
- return height;
+ if( !layoutControl )
+ {
+ for( unsigned int i = 0, numberChildren = parent.GetChildCount(); i < numberChildren; ++i )
+ {
+ Actor child( parent.GetChildAt( i ) );
+ AddFocusableChildrenRecursive( child, focusableActors );
+ }
+ }
+ }
+ }
}
-float Popup::GetWidthForHeight( float height )
+void Popup::AddFocusableChildren( Actor parent, std::vector< Actor >& focusableActors )
{
- return GetNaturalSize().width;
+ 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)
+Actor Popup::GetNextKeyboardFocusableActor( Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled )
{
+ std::string currentStr;
+ if( currentFocusedActor )
+ {
+ currentStr = currentFocusedActor.GetProperty< std::string >( Dali::Actor::Property::NAME );
+ }
+
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
- if( mContent && mContent.IsKeyboardFocusable() )
+ // The current focused actor is not within popup.
+ if( mContent && mContent.GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE ) )
{
- // If content is focusable, move the focus to content
+ // If the content is focusable, move the focus to the content.
nextFocusableActor = mContent;
}
- else if( !mButtons.empty() )
+ else if( mFooter && mFooter.GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE ) )
{
- // Otherwise, movethe focus to the first button
- nextFocusableActor = mButtons[0];
+ // If the footer is focusable, move the focus to the footer.
+ nextFocusableActor = mFooter;
}
}
else
{
- // Rebuild the focus chain because button or content can be added or removed dynamically
+ // Rebuild the focus chain because controls or content can be added or removed dynamically
std::vector< Actor > focusableActors;
- if( mContent && mContent.IsKeyboardFocusable() )
- {
- focusableActors.push_back(mContent);
- }
- for(unsigned int i = 0; i < mButtons.size(); i++)
+ 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 )
{
- if( mButtons[i] && mButtons[i].IsKeyboardFocusable() )
+ if( currentFocusedActor == *iterator )
{
- focusableActors.push_back(mButtons[i]);
+ 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 ( *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 );
- }
- }
-
- if ( *iter == mContent && !mButtons.empty() )
- {
- nextFocusableActor = mButtons[0];
- }
- 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;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+
+ if( !nextFocusableActor )
+ {
+ DALI_LOG_WARNING( "Can not decide next focusable actor\n" );
}
}
}