2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali-toolkit/internal/controls/popup/popup-impl.h>
22 #include <cstring> // for strcmp
23 #include <dali/devel-api/adaptor-framework/physical-keyboard.h>
24 #include <dali/devel-api/object/type-registry-helper.h>
25 #include <dali/integration-api/debug.h>
26 #include <dali/public-api/adaptor-framework/key.h>
27 #include <dali/public-api/animation/constraints.h>
28 #include <dali/public-api/common/stage.h>
29 #include <dali/public-api/events/key-event.h>
30 #include <dali/public-api/events/touch-event.h>
31 #include <dali/public-api/images/resource-image.h>
32 #include <dali/public-api/object/type-registry.h>
33 #include <dali/devel-api/scripting/scripting.h>
34 #include <dali/public-api/size-negotiation/relayout-container.h>
37 #include <dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h>
38 #include <dali-toolkit/public-api/controls/control-impl.h>
39 #include <dali-toolkit/public-api/controls/default-controls/solid-color-actor.h>
40 #include <dali-toolkit/public-api/accessibility-manager/accessibility-manager.h>
41 #include <dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h>
58 * Creation function for main Popup type.
59 * @return Handle to the new popup object.
63 return Toolkit::Popup::New();
66 // Toast style defaults.
67 const int DEFAULT_TOAST_AUTO_HIDE_DELAY = 3000; ///< Toast will auto-hide after 3000ms (3 seconds)
68 const float DEFAULT_TOAST_TRANSITION_TIME = 0.65f; ///< Default time the toast Popup will take to show and hide.
69 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.
70 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.
73 * Creation function for named type "popup-toast".
74 * @return Handle to the new toast popup object.
76 BaseHandle CreateToast()
78 Toolkit::Popup popup = Toolkit::Popup::New();
80 // Setup for Toast Popup type.
81 popup.SetSizeModeFactor( DEFAULT_TOAST_WIDTH_OF_STAGE_RATIO );
82 popup.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::WIDTH );
83 popup.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT );
84 popup.SetProperty( Toolkit::Popup::Property::CONTEXTUAL_MODE, Toolkit::Popup::NON_CONTEXTUAL );
85 popup.SetProperty( Toolkit::Popup::Property::ANIMATION_DURATION, DEFAULT_TOAST_TRANSITION_TIME );
86 popup.SetProperty( Toolkit::Popup::Property::TAIL_VISIBILITY, false );
88 // Disable the dimmed backing.
89 popup.SetProperty( Toolkit::Popup::Property::BACKING_ENABLED, false );
91 // The toast popup should fade in (not zoom).
92 popup.SetProperty( Toolkit::Popup::Property::ANIMATION_MODE, Toolkit::Popup::FADE );
94 // The toast popup should auto-hide.
95 popup.SetProperty( Toolkit::Popup::Property::AUTO_HIDE_DELAY, DEFAULT_TOAST_AUTO_HIDE_DELAY );
97 // Align to the bottom of the screen.
98 popup.SetParentOrigin( DEFAULT_TOAST_BOTTOM_PARENT_ORIGIN );
99 popup.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
101 // Let events pass through the toast popup.
102 popup.SetProperty( Toolkit::Popup::Property::TOUCH_TRANSPARENT, true );
107 // Setup properties, signals and actions using the type-registry.
108 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Popup, Toolkit::Control, Create )
110 // Main content related properties.
111 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "title", MAP, TITLE )
112 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "content", MAP, CONTENT )
113 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "footer", MAP, FOOTER )
114 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "display-state", STRING, DISPLAY_STATE )
115 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "touch-transparent", BOOLEAN, TOUCH_TRANSPARENT )
117 // Contextual related properties.
118 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tail-visibility", BOOLEAN, TAIL_VISIBILITY )
119 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tail-position", VECTOR3, TAIL_POSITION )
120 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "contextual-mode", STRING, CONTEXTUAL_MODE )
122 // Animation related properties.
123 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "animation-duration", FLOAT, ANIMATION_DURATION )
124 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "animation-mode", STRING, ANIMATION_MODE )
125 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "entry-animation", MAP, ENTRY_ANIMATION )
126 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "exit-animation", MAP, EXIT_ANIMATION )
127 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "auto-hide-delay", INTEGER, AUTO_HIDE_DELAY )
129 // Style related properties.
130 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "backing-enabled", BOOLEAN, BACKING_ENABLED )
131 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "backing-color", VECTOR4, BACKING_COLOR )
132 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "popup-background-image", STRING, POPUP_BACKGROUND_IMAGE )
133 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tail-up-image", STRING, TAIL_UP_IMAGE )
134 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tail-down-image", STRING, TAIL_DOWN_IMAGE )
135 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tail-left-image", STRING, TAIL_LEFT_IMAGE )
136 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tail-right-image", STRING, TAIL_RIGHT_IMAGE )
139 DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "touched-outside", SIGNAL_TOUCHED_OUTSIDE )
140 DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "showing", SIGNAL_SHOWING )
141 DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "shown", SIGNAL_SHOWN )
142 DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "hiding", SIGNAL_HIDING )
143 DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "hidden", SIGNAL_HIDDEN )
145 DALI_TYPE_REGISTRATION_END()
147 // Named type registration.
149 // Toast Popup: Non-modal popup that displays information at the bottom of the screen.
150 TypeRegistration typeRegistrationToast( "popup-toast", typeid( Toolkit::Popup ), CreateToast );
152 // Enumeration to / from string conversion tables
154 const Scripting::StringEnum DisplayStateTable[] = {
155 { "SHOWING", Toolkit::Popup::SHOWING },
156 { "SHOWN", Toolkit::Popup::SHOWN },
157 { "HIDING", Toolkit::Popup::HIDING },
158 { "HIDDEN", Toolkit::Popup::HIDDEN },
159 }; const unsigned int DisplayStateTableCount = sizeof( DisplayStateTable ) / sizeof( DisplayStateTable[0] );
161 const Scripting::StringEnum AnimationModeTable[] = {
162 { "NONE", Toolkit::Popup::NONE },
163 { "ZOOM", Toolkit::Popup::ZOOM },
164 { "FADE", Toolkit::Popup::FADE },
165 { "CUSTOM", Toolkit::Popup::CUSTOM },
166 }; const unsigned int AnimationModeTableCount = sizeof( AnimationModeTable ) / sizeof( AnimationModeTable[0] );
168 const Scripting::StringEnum ContextualModeTable[] = {
169 { "NON_CONTEXTUAL", Toolkit::Popup::NON_CONTEXTUAL },
170 { "ABOVE", Toolkit::Popup::ABOVE },
171 { "RIGHT", Toolkit::Popup::RIGHT },
172 { "BELOW", Toolkit::Popup::BELOW },
173 { "LEFT", Toolkit::Popup::LEFT },
174 }; const unsigned int ContextualModeTableCount = sizeof( ContextualModeTable ) / sizeof( ContextualModeTable[0] );
177 const Vector3 DEFAULT_POPUP_PARENT_RELATIVE_SIZE( 0.75f, 1.0f, 1.0f ); ///< Default size percentage of parent.
178 const float DEFAULT_POPUP_ANIMATION_DURATION = 0.6f; ///< Duration of hide/show animations.
179 const float POPUP_OUT_MARGIN_WIDTH = 16.f; ///< Space between the screen edge and the popup edge in the horizontal dimension.
180 const float POPUP_OUT_MARGIN_HEIGHT = 36.f; ///< Space between the screen edge and the popup edge in the vertical dimension.
181 const Vector3 DEFAULT_TAIL_POSITION( 0.5f, 1.0f, 0.0f ); ///< Position the tail will be displayed when enabled without setting the position.
183 // Contextual defaults.
184 const Vector2 DEFAULT_CONTEXTUAL_ADJACENCY_MARGIN( 10.0f, 10.0f ); ///< How close the Popup will be to it's contextual parent.
185 const Vector2 DEFAULT_CONTEXTUAL_STAGE_BORDER( 15.0f, 15.0f ); ///< How close the Popup can be to the stage edges.
187 // Popup style defaults.
188 const char* DEFAULT_BACKGROUND_IMAGE_PATH = DALI_IMAGE_DIR "00_popup_bg.9.png"; ///< Background image.
189 const char* DEFAULT_TAIL_UP_IMAGE_PATH = DALI_IMAGE_DIR "popup_tail_up.png"; ///< Tail up image.
190 const char* DEFAULT_TAIL_DOWN_IMAGE_PATH = DALI_IMAGE_DIR "popup_tail_down.png"; ///< Tail down image.
191 const char* DEFAULT_TAIL_LEFT_IMAGE_PATH = DALI_IMAGE_DIR "popup_tail_left.png"; ///< Tail left image.
192 const char* DEFAULT_TAIL_RIGHT_IMAGE_PATH = DALI_IMAGE_DIR "popup_tail_right.png"; ///< Tail right image.
194 const Vector4 DEFAULT_BACKING_COLOR( 0.0f, 0.0f, 0.0f, 0.5f ); ///< Color of the dimmed backing.
195 const Vector3 BACKGROUND_OUTER_BORDER( 40.0f, 30.0f, 0.0f ); ///< External border.
196 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).
197 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).
198 const Vector3 FOOTER_SIZE( 620.0f, 96.0f,0.0f ); ///< Default size of the bottom control area.
199 const float DEFAULT_RELATIVE_PARENT_WIDTH = 0.75f; ///< If width is not fixed, relative size to parent is used by default.
201 } // Unnamed namespace
207 Dali::Toolkit::Popup Popup::New()
209 // Create the implementation
210 PopupPtr popup( new Popup() );
212 // Pass ownership to CustomActor via derived handle.
213 Dali::Toolkit::Popup handle( *popup );
215 // Second-phase initialisation of the implementation.
216 // This can only be done after the CustomActor connection has been made.
223 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ),
225 mAlterAddedChild( false ),
226 mLayoutDirty( true ),
227 mTouchTransparent( false ),
229 // Property variables:
230 mDisplayState( Toolkit::Popup::HIDDEN ), // Hidden until shown with SetDisplayState()
231 mTailVisible( false ),
232 mTailPosition( DEFAULT_TAIL_POSITION ),
233 mContextualMode( Toolkit::Popup::NON_CONTEXTUAL ),
234 mAnimationDuration( DEFAULT_POPUP_ANIMATION_DURATION ),
235 mAnimationMode( Toolkit::Popup::FADE ),
237 mBackingEnabled( true ),
238 mBackingColor( DEFAULT_BACKING_COLOR ),
239 mTailUpImage( DEFAULT_TAIL_UP_IMAGE_PATH ),
240 mTailDownImage( DEFAULT_TAIL_DOWN_IMAGE_PATH ),
241 mTailLeftImage( DEFAULT_TAIL_LEFT_IMAGE_PATH ),
242 mTailRightImage( DEFAULT_TAIL_RIGHT_IMAGE_PATH )
244 SetKeyboardNavigationSupport( true );
247 void Popup::OnInitialize()
250 self.SetName( "popup" );
252 // Apply some default resizing rules.
253 self.SetParentOrigin( ParentOrigin::CENTER );
254 self.SetAnchorPoint( AnchorPoint::CENTER );
256 self.SetSizeModeFactor( DEFAULT_POPUP_PARENT_RELATIVE_SIZE );
257 self.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::WIDTH );
258 self.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT );
260 // Create a new layer so all Popup components can appear above all other actors.
261 mLayer = Layer::New();
262 mLayer.SetName( "popup-layer" );
264 mLayer.SetParentOrigin( ParentOrigin::CENTER );
265 mLayer.SetAnchorPoint( AnchorPoint::CENTER );
266 mLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
268 // Important to set as invisible as otherwise, if the popup is parented,
269 // but not shown yet it will appear statically on the screen.
270 mLayer.SetVisible( false );
272 // Add the layer to the hierarchy.
275 // Add Backing (Dimmed effect).
276 mLayer.Add( CreateBacking() );
278 mPopupContainer = Actor::New();
279 mPopupContainer.SetName( "popup-container" );
280 mPopupContainer.SetParentOrigin( ParentOrigin::CENTER );
281 mPopupContainer.SetAnchorPoint( AnchorPoint::CENTER );
282 mPopupContainer.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
283 mLayer.Add( mPopupContainer );
285 // Create the Popup layout to contain all main content.
286 mPopupLayout = Toolkit::TableView::New( 3, 1 );
288 // Adds the default background image.
289 SetPopupBackgroundImage( ImageActor::New( ResourceImage::New( DEFAULT_BACKGROUND_IMAGE_PATH ) ) );
291 mPopupLayout.SetName( "popup-layout-table" );
292 mPopupLayout.SetParentOrigin( ParentOrigin::CENTER );
293 mPopupLayout.SetAnchorPoint( AnchorPoint::CENTER );
295 mPopupLayout.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::WIDTH );
296 mPopupLayout.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT );
297 mPopupLayout.SetSize( Stage::GetCurrent().GetSize().x * DEFAULT_RELATIVE_PARENT_WIDTH, 0.0f );
299 mPopupLayout.SetFitHeight( 0 ); // Set row to fit.
300 mPopupLayout.SetFitHeight( 1 ); // Set row to fit.
302 mPopupLayout.TouchedSignal().Connect( this, &Popup::OnDialogTouched );
304 mPopupContainer.Add( mPopupLayout );
306 // Any content after this point which is added to Self() will be re-parented to mContent.
307 mAlterAddedChild = true;
309 // Make self keyboard focusable and a focus group.
310 self.SetKeyboardFocusable( true );
311 SetAsKeyboardFocusGroup( true );
316 mEntryAnimationData.Clear();
317 mExitAnimationData.Clear();
320 void Popup::LayoutAnimation()
322 // Perform setup based on the currently selected animation.
323 switch( mAnimationMode )
325 case Toolkit::Popup::ZOOM:
327 // Zoom animations start fully zoomed out.
328 mPopupContainer.SetScale( Vector3::ZERO );
332 case Toolkit::Popup::FADE:
334 // Fade animations start transparent.
335 mPopupContainer.SetOpacity( 0.0f );
339 case Toolkit::Popup::CUSTOM:
341 // Initialise the custom animation by playing to the end of it's exit animation instantly.
342 // EG. If it was zooming in, then we zoom out fully instantly so the zoom in works.
343 StartTransitionAnimation( false, true );
347 case Toolkit::Popup::NONE:
354 void Popup::StartTransitionAnimation( bool transitionIn, bool instantaneous /* false */ )
356 // Stop and recreate animation.
363 float duration = GetAnimationDuration();
365 // Setup variables ready to start the animations.
366 // If we are performing the animation instantaneously, we do not want to emit a signal.
371 // Setup variables and signal that we are starting the transition.
372 // Note: We signal even if the transition is instant so signal order is consistent.
373 mShowingSignal.Emit();
377 mHidingSignal.Emit();
381 // Perform chosen animation for the Popup.
382 switch( mAnimationMode )
384 case Toolkit::Popup::NONE:
386 mAnimation = Animation::New( 0.0f );
390 case Toolkit::Popup::ZOOM:
392 mAnimation = Animation::New( duration );
393 if( duration > Math::MACHINE_EPSILON_0 )
397 mAnimation.AnimateTo( Property( mPopupContainer, Actor::Property::SCALE ), Vector3::ONE, AlphaFunction::EASE_IN_OUT, TimePeriod( duration * 0.25f, duration * 0.75f ) );
401 // Zoom out animation is twice the speed. Modify the duration variable so the backing animation speed is modified also.
403 mAnimation.SetDuration( duration );
404 mAnimation.AnimateTo( Property( mPopupContainer, Actor::Property::SCALE ), Vector3::ZERO, AlphaFunction::EASE_IN_OUT, TimePeriod( 0.0f, duration ) );
409 mPopupContainer.SetScale( transitionIn ? Vector3::ONE : Vector3::ZERO );
414 case Toolkit::Popup::FADE:
416 mAnimation = Animation::New( duration );
417 if( duration > Math::MACHINE_EPSILON_0 )
421 mAnimation.AnimateTo( Property( mPopupContainer, Actor::Property::COLOR_ALPHA ), 1.0f, AlphaFunction::EASE_IN_OUT, TimePeriod( 0.30f, duration * 0.70f ) );
425 mAnimation.AnimateTo( Property( mPopupContainer, Actor::Property::COLOR_ALPHA ), 0.0f, AlphaFunction::EASE_IN_OUT, TimePeriod( 0.0f, duration * 0.70f ) );
430 mPopupContainer.SetOpacity( transitionIn ? 1.0f : 0.0f );
435 case Toolkit::Popup::CUSTOM:
437 // Use a user specified animation for in and out.
438 // Read the correct animation depending on entry or exit.
439 // Attempt to use animation data defined from script data.
440 Dali::AnimationData* animationData = transitionIn ? &mEntryAnimationData : &mExitAnimationData;
442 // Create a new animation from the pre-defined data in the AnimationData class.
443 // If there is no data, mAnimation is invalidated.
444 mAnimation = animationData->CreateAnimation( mPopupContainer, duration );
446 // If we don't have a valid animation, provide a blank one so play() can still function generically.
449 // No animation was configured (even though custom mode was specified). Create a dummy animation to avoid an exception.
450 mAnimation = Animation::New( 0.0f );
457 // Animate the backing, if enabled.
458 // This is set up last so that different animation modes can have an effect on the backing animation speed.
459 if( mBackingEnabled )
461 if( duration > Math::MACHINE_EPSILON_0 )
465 mAnimation.AnimateTo( Property( mBacking, Actor::Property::COLOR_ALPHA ), 1.0f, AlphaFunction::EASE_IN_OUT, TimePeriod( 0.0f, duration * 0.70f ) );
469 mAnimation.AnimateTo( Property( mBacking, Actor::Property::COLOR_ALPHA ), 0.0f, AlphaFunction::EASE_IN_OUT, TimePeriod( 0.30f, duration * 0.70f ) );
474 mBacking.SetOpacity( transitionIn ? 1.0f : 0.0f );
478 // If we are performing the animation instantaneously, jump to the position directly and do not signal.
481 mAnimation.SetCurrentProgress( 1.0f );
484 else if( duration > Math::MACHINE_EPSILON_0 )
486 // Run the animation.
487 mAnimation.FinishedSignal().Connect( this, &Popup::OnDisplayChangeAnimationFinished );
492 // We did not use an animation to achive the transition.
493 // Trigger the state change directly.
494 DisplayStateChangeComplete();
498 void Popup::OnDisplayChangeAnimationFinished( Animation& source )
500 DisplayStateChangeComplete();
503 void Popup::DisplayStateChangeComplete()
505 // Remove contents from stage if completely hidden.
506 if( mDisplayState == Toolkit::Popup::HIDING )
508 mDisplayState = Toolkit::Popup::HIDDEN;
510 mLayer.SetVisible( false );
511 mPopupLayout.SetSensitive( false );
513 // Guard against destruction during signal emission.
514 Toolkit::Popup handle( GetOwner() );
515 mHiddenSignal.Emit();
517 else if( mDisplayState == Toolkit::Popup::SHOWING )
519 mDisplayState = Toolkit::Popup::SHOWN;
520 Toolkit::Popup handle( GetOwner() );
523 // Start a timer to auto-hide if enabled.
524 if( mAutoHideDelay > 0u )
526 mAutoHideTimer = Timer::New( mAutoHideDelay );
527 mAutoHideTimer.TickSignal().Connect( this, &Popup::OnAutoHideTimeReached );
528 mAutoHideTimer.Start();
533 bool Popup::OnAutoHideTimeReached()
535 // Display timer has expired, auto hide the popup exactly as if the user had clicked outside.
536 SetDisplayState( Toolkit::Popup::HIDDEN );
540 mAutoHideTimer.Stop();
541 mAutoHideTimer.TickSignal().Disconnect( this, &Popup::OnAutoHideTimeReached );
542 mAutoHideTimer.Reset();
547 void Popup::SetPopupBackgroundImage( Actor image )
549 // Removes any previous background.
550 if( mPopupBackgroundImage )
552 mPopupContainer.Remove( mPopupBackgroundImage );
555 // Adds new background to the dialog.
556 mPopupBackgroundImage = image;
557 mPopupBackgroundImage.SetName( "popup-background-image" );
558 mPopupBackgroundImage.SetAnchorPoint( AnchorPoint::CENTER );
559 mPopupBackgroundImage.SetParentOrigin( ParentOrigin::CENTER );
561 // OnDialogTouched only consumes the event. It prevents the touch event to be caught by the backing.
562 mPopupBackgroundImage.TouchedSignal().Connect( this, &Popup::OnDialogTouched );
564 // Set the popup border to be slightly larger than the layout contents.
565 mPopupBackgroundImage.SetResizePolicy( ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT, Dimension::ALL_DIMENSIONS );
566 mPopupBackgroundImage.SetSizeModeFactor( BACKGROUND_OUTER_BORDER );
568 const bool prevAlter = mAlterAddedChild;
569 mAlterAddedChild = false;
570 mPopupContainer.Add( mPopupBackgroundImage );
571 mAlterAddedChild = prevAlter;
576 Actor Popup::GetPopupBackgroundImage() const
578 return mPopupBackgroundImage;
581 void Popup::SetTitle( Actor titleActor )
583 // Replaces the current title actor.
591 mPopupLayout.RemoveChildAt( Toolkit::TableView::CellPosition( 0, 0) );
597 // Set up padding to give sensible default behaviour
598 // (an application developer can later override this if they wish).
599 mTitle.SetPadding( DEFAULT_TITLE_PADDING );
601 mPopupLayout.AddChild( mTitle, Toolkit::TableView::CellPosition( 0, 0 ) );
608 Actor Popup::GetTitle() const
613 void Popup::SetContent( Actor content )
615 // Remove previous content actor.
618 mPopupLayout.RemoveChildAt( Toolkit::TableView::CellPosition( 1, 0 ) );
620 // Keep a handle to the new content.
625 mContent.SetName( "popup-content" );
627 mPopupLayout.AddChild( mContent, Toolkit::TableView::CellPosition( 1, 0 ) );
634 Actor Popup::GetContent() const
639 void Popup::SetFooter( Actor footer )
641 // Remove previous content actor.
644 mPopupLayout.RemoveChildAt( Toolkit::TableView::CellPosition( 2, 0 ) );
647 // Keep a handle to the new content.
652 mFooter.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
654 // The control container has a fixed height.
655 mPopupLayout.SetFitHeight( 2u );
656 mPopupLayout.AddChild( footer, Toolkit::TableView::CellPosition( 2, 0 ) );
663 Actor Popup::GetFooter() const
668 void Popup::SetDisplayState( Toolkit::Popup::DisplayState displayState )
670 // Convert the 4-way state to a bool, true for show, false for hide.
671 bool display = ( displayState == Toolkit::Popup::SHOWING ) || ( displayState == Toolkit::Popup::SHOWN );
673 // Ignore if we are already at the target display state.
674 if( display == ( ( mDisplayState == Toolkit::Popup::SHOWING ) || ( mDisplayState == Toolkit::Popup::SHOWN ) ) )
679 // Convert the bool state to the actual display state to use.
680 mDisplayState = display ? Toolkit::Popup::SHOWING : Toolkit::Popup::HIDING;
684 // Update the state to indicate the current intent.
685 mDisplayState = Toolkit::Popup::SHOWING;
687 // We are displaying so bring the popup layer to the front, and set it visible so it is rendered.
689 mLayer.SetVisible( true );
691 // Set up the layout if this is the first display or the layout has become dirty.
694 // Bake-in any style and layout options to create the Popup layout.
698 // Allow the popup to catch events.
699 mPopupLayout.SetSensitive( true );
702 // Handle the keyboard focus when popup is shown.
703 Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get();
704 if( keyboardFocusManager )
706 mPreviousFocusedActor = keyboardFocusManager.GetCurrentFocusActor();
708 if( mContent && mContent.IsKeyboardFocusable() )
710 // If content is focusable, move the focus to content.
711 keyboardFocusManager.SetCurrentFocusActor( mContent );
715 DALI_LOG_WARNING( "There is no focusable in popup\n" );
721 mDisplayState = Toolkit::Popup::HIDING;
722 ClearKeyInputFocus();
724 // Restore the keyboard focus when popup is hidden.
725 if( mPreviousFocusedActor && mPreviousFocusedActor.IsKeyboardFocusable() )
727 Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get();
728 if( keyboardFocusManager )
730 keyboardFocusManager.SetCurrentFocusActor( mPreviousFocusedActor );
735 // Perform animation.
736 StartTransitionAnimation( display );
739 Toolkit::Popup::DisplayState Popup::GetDisplayState() const
741 return mDisplayState;
744 void Popup::LayoutPopup()
746 mLayoutDirty = false;
748 /* When animating in, we want to respect the origin applied to Self().
749 * For example, if zooming, not only will the final result be anchored to the
750 * selected point, but the zoom will originate from this point also.
752 * EG: ParentOrigin::TOP_LEFT, AnchorPoint::TOP_LEFT :
761 mPopupContainer.SetParentOrigin( Self().GetCurrentParentOrigin() );
762 mPopupContainer.SetAnchorPoint( Self().GetCurrentAnchorPoint() );
764 // If there is only a title, use less padding.
767 if( !mContent && !mFooter )
769 mTitle.SetPadding( DEFAULT_TITLE_ONLY_PADDING );
773 mTitle.SetPadding( DEFAULT_TITLE_PADDING );
777 // Allow derived classes to perform any layout they may need to do.
780 // Update background visibility.
781 mPopupContainer.SetVisible( !( !mFooter && mPopupLayout.GetChildCount() == 0 ) );
783 // Create / destroy / position the tail as needed.
786 // Setup any layout and initialisation required for the selected animation.
792 void Popup::LayoutTail()
794 // Removes the tail actor.
795 if( mTailImage && mTailImage.GetParent() )
797 mTailImage.GetParent().Remove( mTailImage );
806 const Vector3& position = GetTailPosition();
809 // depending on position of tail around ParentOrigin, a different tail image is used...
810 if( position.y < Math::MACHINE_EPSILON_1 )
812 image = mTailUpImage;
814 else if( position.y > 1.0f - Math::MACHINE_EPSILON_1 )
816 image = mTailDownImage;
818 else if( position.x < Math::MACHINE_EPSILON_1 )
820 image = mTailLeftImage;
822 else if( position.x > 1.0f - Math::MACHINE_EPSILON_1 )
824 image = mTailRightImage;
829 // Adds the tail actor.
830 Image tail = ResourceImage::New( image );
831 mTailImage = ImageActor::New( tail );
832 mTailImage.SetName( "tail-image" );
833 const Vector3 anchorPoint = AnchorPoint::BOTTOM_RIGHT - position;
834 mTailImage.SetParentOrigin( position );
835 mTailImage.SetAnchorPoint( anchorPoint );
837 mLayer.Add( mTailImage );
841 void Popup::SetContextualMode( Toolkit::Popup::ContextualMode mode )
843 mContextualMode = mode;
847 Toolkit::Popup::ContextualMode Popup::GetContextualMode() const
849 return mContextualMode;
852 ImageActor Popup::CreateBacking()
854 mBacking = Dali::Toolkit::CreateSolidColorActor( mBackingColor );
855 mBacking.SetName( "popup-backing" );
857 // Must always be positioned top-left of stage, regardless of parent.
858 mBacking.SetPositionInheritanceMode( DONT_INHERIT_POSITION );
859 mBacking.SetAnchorPoint( AnchorPoint::TOP_LEFT );
861 // Always the full size of the stage.
862 mBacking.SetResizePolicy( ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS );
863 mBacking.SetSize( Stage::GetCurrent().GetSize() );
866 mBacking.SetSensitive( true );
868 // Default to being transparent.
869 mBacking.SetOpacity( 0.0f );
870 mBacking.TouchedSignal().Connect( this, &Popup::OnBackingTouched );
871 mBacking.WheelEventSignal().Connect( this, &Popup::OnBackingWheelEvent );
875 Toolkit::Popup::TouchedOutsideSignalType& Popup::OutsideTouchedSignal()
877 return mTouchedOutsideSignal;
880 Toolkit::Popup::DisplayStateChangeSignalType& Popup::ShowingSignal()
882 return mShowingSignal;
885 Toolkit::Popup::DisplayStateChangeSignalType& Popup::ShownSignal()
890 Toolkit::Popup::DisplayStateChangeSignalType& Popup::HidingSignal()
892 return mHidingSignal;
895 Toolkit::Popup::DisplayStateChangeSignalType& Popup::HiddenSignal()
897 return mHiddenSignal;
900 void Popup::SetTailVisibility( bool visible )
902 mTailVisible = visible;
906 const bool Popup::IsTailVisible() const
911 void Popup::SetTailPosition( Vector3 position )
913 mTailPosition = position;
917 const Vector3& Popup::GetTailPosition() const
919 return mTailPosition;
922 void Popup::SetAnimationDuration( float duration )
924 mAnimationDuration = duration;
928 float Popup::GetAnimationDuration() const
930 return mAnimationDuration;
933 void Popup::SetAnimationMode( Toolkit::Popup::AnimationMode animationMode )
935 mAnimationMode = animationMode;
939 Toolkit::Popup::AnimationMode Popup::GetAnimationMode() const
941 return mAnimationMode;
944 void Popup::SetEntryAnimationData( const Property::Map& map )
946 mEntryAnimationData.Clear();
947 Scripting::NewAnimation( map, mEntryAnimationData );
950 void Popup::SetExitAnimationData( const Property::Map& map )
952 mExitAnimationData.Clear();
953 Scripting::NewAnimation( map, mExitAnimationData );
956 void Popup::SetAutoHideDelay( int delay )
958 mAutoHideDelay = delay;
961 int Popup::GetAutoHideDelay() const
963 return mAutoHideDelay;
966 void Popup::SetBackingEnabled( bool enabled )
968 mBackingEnabled = enabled;
972 const bool Popup::IsBackingEnabled() const
974 return mBackingEnabled;
977 void Popup::SetBackingColor( Vector4 color )
979 mBackingColor = color;
983 const Vector4& Popup::GetBackingColor() const
985 return mBackingColor;
988 void Popup::SetTailUpImage( std::string image )
990 mTailUpImage = image;
994 const std::string& Popup::GetTailUpImage() const
999 void Popup::SetTailDownImage( std::string image )
1001 mTailDownImage = image;
1002 mLayoutDirty = true;
1005 const std::string& Popup::GetTailDownImage() const
1007 return mTailDownImage;
1010 void Popup::SetTailLeftImage( std::string image )
1012 mTailLeftImage = image;
1013 mLayoutDirty = true;
1016 const std::string& Popup::GetTailLeftImage() const
1018 return mTailLeftImage;
1021 void Popup::SetTailRightImage( std::string image )
1023 mTailRightImage = image;
1024 mLayoutDirty = true;
1027 const std::string& Popup::GetTailRightImage() const
1029 return mTailRightImage;
1032 void Popup::SetTouchTransparent( bool enabled )
1034 mTouchTransparent = enabled;
1037 const bool Popup::IsTouchTransparent() const
1039 return mTouchTransparent;
1042 void Popup::SetProperty( BaseObject* object, Property::Index propertyIndex, const Property::Value& value )
1044 Toolkit::Popup popup = Toolkit::Popup::DownCast( Dali::BaseHandle( object ) );
1048 Popup& popupImpl( GetImpl( popup ) );
1050 switch ( propertyIndex )
1052 case Toolkit::Popup::Property::TITLE:
1054 Property::Map valueMap;
1055 if( value.Get( valueMap ) )
1057 popupImpl.SetTitle( Scripting::NewActor( valueMap ) );
1061 case Toolkit::Popup::Property::CONTENT:
1063 Property::Map valueMap;
1064 if( value.Get( valueMap ) )
1066 popupImpl.SetContent( Scripting::NewActor( valueMap ) );
1070 case Toolkit::Popup::Property::FOOTER:
1072 Property::Map valueMap;
1073 if( value.Get( valueMap ) )
1075 popupImpl.SetFooter( Scripting::NewActor( valueMap ) );
1079 case Toolkit::Popup::Property::DISPLAY_STATE:
1081 std::string valueString;
1082 if( value.Get( valueString ) )
1084 Toolkit::Popup::DisplayState displayState( Toolkit::Popup::HIDDEN );
1085 if( Scripting::GetEnumeration< Toolkit::Popup::DisplayState >( valueString.c_str(), DisplayStateTable, DisplayStateTableCount, displayState ) )
1087 popupImpl.SetDisplayState( displayState );
1092 case Toolkit::Popup::Property::TOUCH_TRANSPARENT:
1095 if( value.Get( valueBool ) )
1097 popupImpl.SetTouchTransparent( valueBool );
1101 case Toolkit::Popup::Property::TAIL_VISIBILITY:
1104 if( value.Get( valueBool ) )
1106 popupImpl.SetTailVisibility( valueBool );
1110 case Toolkit::Popup::Property::TAIL_POSITION:
1112 Vector3 valueVector3;
1113 if( value.Get( valueVector3 ) )
1115 popupImpl.SetTailPosition( valueVector3 );
1119 case Toolkit::Popup::Property::CONTEXTUAL_MODE:
1121 std::string valueString;
1122 if( value.Get( valueString ) )
1124 Toolkit::Popup::ContextualMode contextualMode( Toolkit::Popup::BELOW );
1125 if( Scripting::GetEnumeration< Toolkit::Popup::ContextualMode >( valueString.c_str(), ContextualModeTable, ContextualModeTableCount, contextualMode ) )
1127 popupImpl.SetContextualMode( contextualMode );
1132 case Toolkit::Popup::Property::ANIMATION_DURATION:
1135 if( value.Get( valueFloat ) )
1137 popupImpl.SetAnimationDuration( valueFloat );
1141 case Toolkit::Popup::Property::ANIMATION_MODE:
1143 std::string valueString;
1144 if( value.Get( valueString ) )
1146 Toolkit::Popup::AnimationMode animationMode( Toolkit::Popup::FADE );
1147 if( Scripting::GetEnumeration< Toolkit::Popup::AnimationMode >( valueString.c_str(), AnimationModeTable, AnimationModeTableCount, animationMode ) )
1149 popupImpl.SetAnimationMode( animationMode );
1154 case Toolkit::Popup::Property::ENTRY_ANIMATION:
1156 Property::Map valueMap;
1157 if( value.Get( valueMap ) )
1159 popupImpl.SetEntryAnimationData( valueMap );
1163 case Toolkit::Popup::Property::EXIT_ANIMATION:
1165 Property::Map valueMap;
1166 if( value.Get( valueMap ) )
1168 popupImpl.SetExitAnimationData( valueMap );
1172 case Toolkit::Popup::Property::AUTO_HIDE_DELAY:
1175 if( value.Get( valueInt ) )
1177 popupImpl.SetAutoHideDelay( valueInt );
1181 case Toolkit::Popup::Property::BACKING_ENABLED:
1184 if( value.Get( valueBool ) )
1186 popupImpl.SetBackingEnabled( valueBool );
1190 case Toolkit::Popup::Property::BACKING_COLOR:
1192 Vector4 valueVector4;
1193 if( value.Get( valueVector4 ) )
1195 popupImpl.SetBackingColor( valueVector4 );
1199 case Toolkit::Popup::Property::POPUP_BACKGROUND_IMAGE:
1201 std::string valueString;
1202 if( value.Get( valueString ) )
1204 Image image = ResourceImage::New( valueString );
1207 ImageActor actor = ImageActor::New( image );
1208 popupImpl.SetPopupBackgroundImage( actor );
1213 case Toolkit::Popup::Property::TAIL_UP_IMAGE:
1215 std::string valueString;
1216 if( value.Get( valueString ) )
1218 popupImpl.SetTailUpImage( valueString );
1222 case Toolkit::Popup::Property::TAIL_DOWN_IMAGE:
1224 std::string valueString;
1225 if( value.Get( valueString ) )
1227 popupImpl.SetTailDownImage( valueString );
1231 case Toolkit::Popup::Property::TAIL_LEFT_IMAGE:
1233 std::string valueString;
1234 if( value.Get( valueString ) )
1236 popupImpl.SetTailLeftImage( valueString );
1240 case Toolkit::Popup::Property::TAIL_RIGHT_IMAGE:
1242 std::string valueString;
1243 if( value.Get( valueString ) )
1245 popupImpl.SetTailRightImage( valueString );
1253 Property::Value Popup::GetProperty( BaseObject* object, Property::Index propertyIndex )
1255 Property::Value value;
1257 Toolkit::Popup popup = Toolkit::Popup::DownCast( Dali::BaseHandle( object ) );
1261 Popup& popupImpl( GetImpl( popup ) );
1263 switch ( propertyIndex )
1265 case Toolkit::Popup::Property::TITLE:
1268 Scripting::CreatePropertyMap( popupImpl.GetTitle(), map );
1272 case Toolkit::Popup::Property::CONTENT:
1275 Scripting::CreatePropertyMap( popupImpl.GetContent(), map );
1279 case Toolkit::Popup::Property::FOOTER:
1282 Scripting::CreatePropertyMap( popupImpl.GetFooter(), map );
1286 case Toolkit::Popup::Property::DISPLAY_STATE:
1288 value = Scripting::GetLinearEnumerationName< Toolkit::Popup::DisplayState >( popupImpl.GetDisplayState(), DisplayStateTable, DisplayStateTableCount );
1291 case Toolkit::Popup::Property::TOUCH_TRANSPARENT:
1293 value = popupImpl.IsTouchTransparent();
1296 case Toolkit::Popup::Property::TAIL_VISIBILITY:
1298 value = popupImpl.IsTailVisible();
1301 case Toolkit::Popup::Property::TAIL_POSITION:
1303 value = popupImpl.GetTailPosition();
1306 case Toolkit::Popup::Property::CONTEXTUAL_MODE:
1308 value = Scripting::GetLinearEnumerationName< Toolkit::Popup::ContextualMode >( popupImpl.GetContextualMode(), ContextualModeTable, ContextualModeTableCount );
1311 case Toolkit::Popup::Property::ANIMATION_DURATION:
1313 value = popupImpl.GetAnimationDuration();
1316 case Toolkit::Popup::Property::ANIMATION_MODE:
1318 value = Scripting::GetLinearEnumerationName< Toolkit::Popup::AnimationMode >( popupImpl.GetAnimationMode(), AnimationModeTable, AnimationModeTableCount );
1321 case Toolkit::Popup::Property::ENTRY_ANIMATION:
1323 // Note: Cannot retrieve property map from animation.
1328 case Toolkit::Popup::Property::EXIT_ANIMATION:
1330 // Note: Cannot retrieve property map from animation.
1335 case Toolkit::Popup::Property::AUTO_HIDE_DELAY:
1337 value = popupImpl.GetAutoHideDelay();
1340 case Toolkit::Popup::Property::BACKING_ENABLED:
1342 value = popupImpl.IsBackingEnabled();
1345 case Toolkit::Popup::Property::BACKING_COLOR:
1347 value = popupImpl.GetBackingColor();
1350 case Toolkit::Popup::Property::POPUP_BACKGROUND_IMAGE:
1352 ResourceImage image = ResourceImage::DownCast( popupImpl.GetPopupBackgroundImage() );
1355 value = image.GetUrl();
1359 case Toolkit::Popup::Property::TAIL_UP_IMAGE:
1361 value = popupImpl.GetTailUpImage();
1364 case Toolkit::Popup::Property::TAIL_DOWN_IMAGE:
1366 value = popupImpl.GetTailDownImage();
1369 case Toolkit::Popup::Property::TAIL_LEFT_IMAGE:
1371 value = popupImpl.GetTailLeftImage();
1374 case Toolkit::Popup::Property::TAIL_RIGHT_IMAGE:
1376 value = popupImpl.GetTailRightImage();
1385 bool Popup::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1387 Dali::BaseHandle handle( object );
1389 bool connected( true );
1390 Toolkit::Popup popup = Toolkit::Popup::DownCast( handle );
1392 if( 0 == strcmp( signalName.c_str(), SIGNAL_TOUCHED_OUTSIDE ) )
1394 popup.OutsideTouchedSignal().Connect( tracker, functor );
1396 else if( 0 == strcmp( signalName.c_str(), SIGNAL_SHOWING ) )
1398 popup.ShowingSignal().Connect( tracker, functor );
1400 else if( 0 == strcmp( signalName.c_str(), SIGNAL_SHOWN ) )
1402 popup.ShownSignal().Connect( tracker, functor );
1404 else if( 0 == strcmp( signalName.c_str(), SIGNAL_HIDING ) )
1406 popup.HidingSignal().Connect( tracker, functor );
1408 else if( 0 == strcmp( signalName.c_str(), SIGNAL_HIDDEN ) )
1410 popup.HiddenSignal().Connect( tracker, functor );
1414 // signalName does not match any signal
1421 bool Popup::OnBackingTouched( Actor actor, const TouchEvent& event )
1423 // Allow events to pass through if touch transparency is enabled.
1424 if( mTouchTransparent )
1429 if( event.GetPointCount() > 0 )
1431 const TouchPoint& point = event.GetPoint( 0 );
1433 if( point.state == TouchPoint::Down )
1435 // Guard against destruction during signal emission.
1436 Toolkit::Popup handle( GetOwner() );
1438 mTouchedOutsideSignal.Emit();
1442 // Block anything behind backing becoming touched.
1443 mLayer.SetTouchConsumed( true );
1447 bool Popup::OnBackingWheelEvent( Actor actor, const WheelEvent& event )
1449 // Allow events to pass through if touch transparency is enabled.
1450 if( mTouchTransparent )
1455 // Consume wheel event in dimmed backing actor.
1456 mLayer.SetTouchConsumed( true );
1460 bool Popup::OnDialogTouched(Actor actor, const TouchEvent& event)
1462 // Allow events to pass through if touch transparency is enabled.
1463 if( mTouchTransparent )
1468 // Consume event (stops backing actor receiving touch events)
1469 mLayer.SetTouchConsumed( true );
1473 void Popup::OnControlStageConnection()
1475 mLayoutDirty = true;
1479 void Popup::OnControlChildAdd( Actor& child )
1481 // Re-parent any children added by user to the body layer.
1482 if( mAlterAddedChild )
1484 SetContent( child );
1488 mLayoutDirty = true;
1493 void Popup::LayoutContext( const Vector2& size )
1495 // Do nothing if not in a contextual mode (or there is no parent context).
1496 Actor self = Self();
1497 Actor parent = self.GetParent();
1498 if( ( mContextualMode == Toolkit::Popup::NON_CONTEXTUAL ) || !parent )
1503 mPopupContainer.SetParentOrigin( ParentOrigin::CENTER );
1504 // We always anchor to the CENTER, rather than a different anchor point for each contextual
1505 // mode to allow code-reuse of the bound checking code (for maintainability).
1506 mPopupContainer.SetAnchorPoint( AnchorPoint::CENTER );
1508 // Setup with some pre-calculations for speed.
1509 Vector3 halfStageSize( Stage().GetCurrent().GetSize() / 2.0f );
1510 Vector3 parentPosition( parent.GetCurrentPosition() );
1511 Vector2 halfSize( size / 2.0f );
1512 Vector2 halfParentSize( parent.GetRelayoutSize( Dimension::WIDTH ) / 2.0f, parent.GetRelayoutSize( Dimension::HEIGHT ) / 2.0f );
1513 Vector3 newPosition( Vector3::ZERO );
1515 // Perform different positioning based on the specified contextual layout mode.
1516 switch( mContextualMode )
1518 case Toolkit::Popup::BELOW:
1520 newPosition.x += halfSize.x - halfParentSize.x;
1521 newPosition.y += halfSize.y + halfParentSize.y + DEFAULT_CONTEXTUAL_ADJACENCY_MARGIN.y;
1524 case Toolkit::Popup::ABOVE:
1526 newPosition.x += halfSize.x - halfParentSize.x;
1527 newPosition.y -= halfSize.y + halfParentSize.y + DEFAULT_CONTEXTUAL_ADJACENCY_MARGIN.y;
1530 case Toolkit::Popup::RIGHT:
1532 newPosition.x += halfSize.x + halfParentSize.x + DEFAULT_CONTEXTUAL_ADJACENCY_MARGIN.x;
1533 newPosition.y += halfSize.y - halfParentSize.y;
1536 case Toolkit::Popup::LEFT:
1538 newPosition.x -= halfSize.x + halfParentSize.x + DEFAULT_CONTEXTUAL_ADJACENCY_MARGIN.x;
1539 newPosition.y += halfSize.y - halfParentSize.y;
1542 case Toolkit::Popup::NON_CONTEXTUAL:
1544 // Code won't reach here (caught earlier).
1549 // On-screen position checking.
1550 // Check new position is not too far right. If so, correct it.
1551 // Note: Check for right rather than left first, so if popup is too wide, the left check overrides
1552 // the right check and we at least see the left portion of the popup (as this is more useful).
1553 if( newPosition.x >= ( halfStageSize.x - parentPosition.x - halfSize.x - DEFAULT_CONTEXTUAL_STAGE_BORDER.x ) )
1555 newPosition.x = halfStageSize.x - parentPosition.x - halfSize.x - DEFAULT_CONTEXTUAL_STAGE_BORDER.x;
1557 // Check new position is not too far left. If so, correct it.
1558 if( newPosition.x < halfSize.x - ( parentPosition.x + halfStageSize.x ) + DEFAULT_CONTEXTUAL_STAGE_BORDER.x )
1560 newPosition.x = halfSize.x - ( parentPosition.x + halfStageSize.x ) + DEFAULT_CONTEXTUAL_STAGE_BORDER.x;// - parentSize.x;
1562 // Check new position is not too far down. If so, correct it.
1563 if( newPosition.y >= ( halfStageSize.y - parentPosition.y - halfSize.y - DEFAULT_CONTEXTUAL_STAGE_BORDER.y ) )
1565 newPosition.y = halfStageSize.y - parentPosition.y - halfSize.y - DEFAULT_CONTEXTUAL_STAGE_BORDER.y;
1567 // Check new position is not too far up. If so, correct it.
1568 if( newPosition.y < halfSize.y - ( parentPosition.y + halfStageSize.y ) + DEFAULT_CONTEXTUAL_STAGE_BORDER.y )
1570 newPosition.y = halfSize.y - ( parentPosition.y + halfStageSize.y ) + DEFAULT_CONTEXTUAL_STAGE_BORDER.y;
1573 // Set the final position.
1574 mPopupContainer.SetPosition( newPosition );
1577 void Popup::OnRelayout( const Vector2& size, RelayoutContainer& container )
1579 Vector2 useSize( size );
1581 // Use the Popup layouts size, unless requested to use a fixed size.
1582 // In which case take the size set for the Popup itself.
1583 ResizePolicy::Type widthPolicy = Self().GetResizePolicy( Dimension::WIDTH );
1584 ResizePolicy::Type heightPolicy = Self().GetResizePolicy( Dimension::HEIGHT );
1586 // Width calculations:
1587 if( widthPolicy == ResizePolicy::USE_NATURAL_SIZE || widthPolicy == ResizePolicy::FIT_TO_CHILDREN )
1589 // If we using a child-based policy, take the size from the popup layout.
1590 mPopupLayout.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::WIDTH );
1591 useSize.width = mPopupLayout.GetRelayoutSize( Dimension::WIDTH );
1593 mPopupLayout.SetFitWidth( 0u );
1597 // If we using a parent-based policy, take the size from the popup object itself (self).
1598 mPopupLayout.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::WIDTH );
1600 mPopupLayout.SetFixedWidth( 0u, useSize.width );
1603 // Height calculations:
1604 // Title: Let the title be as high as it needs to be.
1605 mPopupLayout.SetFitHeight( 0u );
1607 // Footer: Convert the footer's resize policy to a TableView row policy.
1610 ResizePolicy::Type footerHeightPolicy = mFooter.GetResizePolicy( Dimension::HEIGHT );
1611 if( ( footerHeightPolicy == ResizePolicy::USE_NATURAL_SIZE ) ||
1612 ( footerHeightPolicy == ResizePolicy::FIT_TO_CHILDREN ) )
1614 mPopupLayout.SetFitHeight( 2u );
1616 else if( footerHeightPolicy == ResizePolicy::FIXED )
1618 mPopupLayout.SetFixedHeight( 2u, mFooter.GetRelayoutSize( Dimension::HEIGHT) );
1622 mPopupLayout.SetRelativeHeight( 2u, 1.0f );
1627 mPopupLayout.SetFixedHeight( 2u, 0.0f );
1630 // Popup contents: Adjust the tableview's policies based on the popup's policies.
1631 if( heightPolicy == ResizePolicy::USE_NATURAL_SIZE || heightPolicy == ResizePolicy::FIT_TO_CHILDREN )
1633 mPopupLayout.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT );
1635 // Let both the contents expand as necessary.
1636 mPopupLayout.SetFitHeight( 1u );
1637 useSize.height = mPopupLayout.GetRelayoutSize( Dimension::HEIGHT );
1641 mPopupLayout.SetResizePolicy( heightPolicy, Dimension::HEIGHT );
1643 // Let the content expand to fill the remaining space.
1644 mPopupLayout.SetRelativeHeight( 1u, 1.0f );
1645 mPopupLayout.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::HEIGHT );
1648 // Relayout the popup-layout to give it it's new size this frame.
1649 container.Add( mPopupLayout, useSize );
1653 container.Add( mContent, Vector2( mContent.GetRelayoutSize( Dimension::WIDTH ), mContent.GetRelayoutSize( Dimension::HEIGHT ) ) );
1656 // Perform contextual layout setup if required.
1657 // This is done each time in case the parent moves.
1658 // This will have no effect if no contextual mode is selected.
1659 LayoutContext( useSize );
1662 void Popup::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1664 // To get the popup to emulate fit-to-children, we need to actually set use-natural-size.
1665 if( ( dimension & Dimension::HEIGHT ) && ( policy == ResizePolicy::FIT_TO_CHILDREN ) )
1667 Self().SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT );
1670 mLayoutDirty = true;
1674 Vector3 Popup::GetNaturalSize()
1676 return mPopupLayout.GetNaturalSize();
1679 float Popup::GetHeightForWidth( float width )
1681 return mPopupLayout.GetHeightForWidth( width );
1684 float Popup::GetWidthForHeight( float height )
1686 return mPopupLayout.GetWidthForHeight( height );
1689 bool Popup::OnKeyEvent( const KeyEvent& event )
1691 // Allow events to pass through if touch transparency is enabled.
1692 if( mTouchTransparent )
1697 bool consumed = false;
1699 if( event.state == KeyEvent::Down )
1701 if (event.keyCode == Dali::DALI_KEY_ESCAPE || event.keyCode == Dali::DALI_KEY_BACK)
1703 SetDisplayState( Toolkit::Popup::HIDDEN );
1711 Actor Popup::GetNextKeyboardFocusableActor( Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled )
1713 Actor nextFocusableActor( currentFocusedActor );
1715 // TODO: Needs to be optimised
1716 if( !currentFocusedActor || ( currentFocusedActor && KeyboardFocusManager::Get().GetFocusGroup( currentFocusedActor ) != Self() ) )
1718 // The current focused actor is not within popup
1719 if( mContent && mContent.IsKeyboardFocusable() )
1721 // If content is focusable, move the focus to content
1722 nextFocusableActor = mContent;
1727 // Rebuild the focus chain because controls or content can be added or removed dynamically
1728 std::vector< Actor > focusableActors;
1729 if( mContent && mContent.IsKeyboardFocusable() )
1731 focusableActors.push_back( mContent );
1734 for( std::vector< Actor >::iterator iter = focusableActors.begin(), end = focusableActors.end(); iter != end; ++iter )
1736 if( currentFocusedActor == *iter )
1740 case Toolkit::Control::KeyboardFocus::LEFT:
1742 if( iter == focusableActors.begin() )
1744 nextFocusableActor = *( focusableActors.end() - 1 );
1748 nextFocusableActor = *( iter - 1 );
1752 case Toolkit::Control::KeyboardFocus::RIGHT:
1754 if( iter == focusableActors.end() - 1 )
1756 nextFocusableActor = *( focusableActors.begin() );
1760 nextFocusableActor = *( iter + 1 );
1765 case Toolkit::Control::KeyboardFocus::UP:
1767 if( mContent && *iter == mContent )
1769 nextFocusableActor = *( focusableActors.end() - 1 );
1773 if( mContent && mContent.IsKeyboardFocusable() )
1775 nextFocusableActor = mContent;
1779 if ( iter == focusableActors.begin() )
1781 nextFocusableActor = *( focusableActors.end() - 1 );
1785 nextFocusableActor = *( iter - 1 );
1792 case Toolkit::Control::KeyboardFocus::DOWN:
1794 if( mContent && mContent.IsKeyboardFocusable() )
1796 nextFocusableActor = mContent;
1800 if( iter == focusableActors.end() - 1 )
1802 nextFocusableActor = *( focusableActors.begin() );
1806 nextFocusableActor = *( iter + 1 );
1813 if( !nextFocusableActor )
1815 DALI_LOG_WARNING( "Can not decide next focusable actor\n" );
1823 return nextFocusableActor;
1826 } // namespace Internal
1828 } // namespace Toolkit