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/controls/image-view/image-view.h>
41 #include <dali-toolkit/public-api/accessibility-manager/accessibility-manager.h>
42 #include <dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h>
59 * Creation function for main Popup type.
60 * @return Handle to the new popup object.
64 return Toolkit::Popup::New();
67 // Toast style defaults.
68 const int DEFAULT_TOAST_AUTO_HIDE_DELAY = 3000; ///< Toast will auto-hide after 3000ms (3 seconds)
69 const float DEFAULT_TOAST_TRANSITION_TIME = 0.65f; ///< Default time the toast Popup will take to show and hide.
70 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.
71 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.
74 * Creation function for named type "popupToast".
75 * @return Handle to the new toast popup object.
77 BaseHandle CreateToast()
79 Toolkit::Popup popup = Toolkit::Popup::New();
81 // Setup for Toast Popup type.
82 popup.SetSizeModeFactor( DEFAULT_TOAST_WIDTH_OF_STAGE_RATIO );
83 popup.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::WIDTH );
84 popup.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT );
85 popup.SetProperty( Toolkit::Popup::Property::CONTEXTUAL_MODE, Toolkit::Popup::NON_CONTEXTUAL );
86 popup.SetProperty( Toolkit::Popup::Property::ANIMATION_DURATION, DEFAULT_TOAST_TRANSITION_TIME );
87 popup.SetProperty( Toolkit::Popup::Property::TAIL_VISIBILITY, false );
89 // Disable the dimmed backing.
90 popup.SetProperty( Toolkit::Popup::Property::BACKING_ENABLED, false );
92 // The toast popup should fade in (not zoom).
93 popup.SetProperty( Toolkit::Popup::Property::ANIMATION_MODE, Toolkit::Popup::FADE );
95 // The toast popup should auto-hide.
96 popup.SetProperty( Toolkit::Popup::Property::AUTO_HIDE_DELAY, DEFAULT_TOAST_AUTO_HIDE_DELAY );
98 // Align to the bottom of the screen.
99 popup.SetParentOrigin( DEFAULT_TOAST_BOTTOM_PARENT_ORIGIN );
100 popup.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
102 // Let events pass through the toast popup.
103 popup.SetProperty( Toolkit::Popup::Property::TOUCH_TRANSPARENT, true );
108 // Setup properties, signals and actions using the type-registry.
109 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Popup, Toolkit::Control, Create )
111 // Main content related properties.
112 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "title", MAP, TITLE )
113 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "content", MAP, CONTENT )
114 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "footer", MAP, FOOTER )
115 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "displayState", STRING, DISPLAY_STATE )
116 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "touchTransparent", BOOLEAN, TOUCH_TRANSPARENT )
118 // Contextual related properties.
119 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tailVisibility", BOOLEAN, TAIL_VISIBILITY )
120 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tailPosition", VECTOR3, TAIL_POSITION )
121 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "contextualMode", STRING, CONTEXTUAL_MODE )
123 // Animation related properties.
124 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "animationDuration", FLOAT, ANIMATION_DURATION )
125 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "animationMode", STRING, ANIMATION_MODE )
126 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "entryAnimation", MAP, ENTRY_ANIMATION )
127 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "exitAnimation", MAP, EXIT_ANIMATION )
128 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "autoHideDelay", INTEGER, AUTO_HIDE_DELAY )
130 // Style related properties.
131 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "backingEnabled", BOOLEAN, BACKING_ENABLED )
132 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "backingColor", VECTOR4, BACKING_COLOR )
133 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "popupBackgroundImage", STRING, POPUP_BACKGROUND_IMAGE )
134 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tailUpImage", STRING, TAIL_UP_IMAGE )
135 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tailDownImage", STRING, TAIL_DOWN_IMAGE )
136 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tailLeftImage", STRING, TAIL_LEFT_IMAGE )
137 DALI_PROPERTY_REGISTRATION( Toolkit, Popup, "tailRightImage", STRING, TAIL_RIGHT_IMAGE )
140 DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "touchedOutside", SIGNAL_TOUCHED_OUTSIDE )
141 DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "showing", SIGNAL_SHOWING )
142 DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "shown", SIGNAL_SHOWN )
143 DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "hiding", SIGNAL_HIDING )
144 DALI_SIGNAL_REGISTRATION( Toolkit, Popup, "hidden", SIGNAL_HIDDEN )
146 DALI_TYPE_REGISTRATION_END()
148 // Named type registration.
150 // Toast Popup: Non-modal popup that displays information at the bottom of the screen.
151 TypeRegistration typeRegistrationToast( "PopupToast", typeid( Toolkit::Popup ), CreateToast );
153 // Enumeration to / from string conversion tables
155 const Scripting::StringEnum DisplayStateTable[] = {
156 { "SHOWING", Toolkit::Popup::SHOWING },
157 { "SHOWN", Toolkit::Popup::SHOWN },
158 { "HIDING", Toolkit::Popup::HIDING },
159 { "HIDDEN", Toolkit::Popup::HIDDEN },
160 }; const unsigned int DisplayStateTableCount = sizeof( DisplayStateTable ) / sizeof( DisplayStateTable[0] );
162 const Scripting::StringEnum AnimationModeTable[] = {
163 { "NONE", Toolkit::Popup::NONE },
164 { "ZOOM", Toolkit::Popup::ZOOM },
165 { "FADE", Toolkit::Popup::FADE },
166 { "CUSTOM", Toolkit::Popup::CUSTOM },
167 }; const unsigned int AnimationModeTableCount = sizeof( AnimationModeTable ) / sizeof( AnimationModeTable[0] );
169 const Scripting::StringEnum ContextualModeTable[] = {
170 { "NON_CONTEXTUAL", Toolkit::Popup::NON_CONTEXTUAL },
171 { "ABOVE", Toolkit::Popup::ABOVE },
172 { "RIGHT", Toolkit::Popup::RIGHT },
173 { "BELOW", Toolkit::Popup::BELOW },
174 { "LEFT", Toolkit::Popup::LEFT },
175 }; const unsigned int ContextualModeTableCount = sizeof( ContextualModeTable ) / sizeof( ContextualModeTable[0] );
178 const Vector3 DEFAULT_POPUP_PARENT_RELATIVE_SIZE( 0.75f, 1.0f, 1.0f ); ///< Default size percentage of parent.
179 const float DEFAULT_POPUP_ANIMATION_DURATION = 0.6f; ///< Duration of hide/show animations.
180 const float POPUP_OUT_MARGIN_WIDTH = 16.f; ///< Space between the screen edge and the popup edge in the horizontal dimension.
181 const float POPUP_OUT_MARGIN_HEIGHT = 36.f; ///< Space between the screen edge and the popup edge in the vertical dimension.
182 const Vector3 DEFAULT_TAIL_POSITION( 0.5f, 1.0f, 0.0f ); ///< Position the tail will be displayed when enabled without setting the position.
184 // Contextual defaults.
185 const Vector2 DEFAULT_CONTEXTUAL_ADJACENCY_MARGIN( 10.0f, 10.0f ); ///< How close the Popup will be to it's contextual parent.
186 const Vector2 DEFAULT_CONTEXTUAL_STAGE_BORDER( 15.0f, 15.0f ); ///< How close the Popup can be to the stage edges.
188 // Popup style defaults.
189 const char* DEFAULT_BACKGROUND_IMAGE_PATH = DALI_IMAGE_DIR "00_popup_bg.9.png"; ///< Background image.
190 const char* DEFAULT_TAIL_UP_IMAGE_PATH = DALI_IMAGE_DIR "popup_tail_up.png"; ///< Tail up image.
191 const char* DEFAULT_TAIL_DOWN_IMAGE_PATH = DALI_IMAGE_DIR "popup_tail_down.png"; ///< Tail down image.
192 const char* DEFAULT_TAIL_LEFT_IMAGE_PATH = DALI_IMAGE_DIR "popup_tail_left.png"; ///< Tail left image.
193 const char* DEFAULT_TAIL_RIGHT_IMAGE_PATH = DALI_IMAGE_DIR "popup_tail_right.png"; ///< Tail right image.
195 const Vector4 DEFAULT_BACKING_COLOR( 0.0f, 0.0f, 0.0f, 0.5f ); ///< Color of the dimmed backing.
196 const Vector3 BACKGROUND_OUTER_BORDER( 40.0f, 30.0f, 0.0f ); ///< External border.
197 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).
198 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).
199 const Vector3 FOOTER_SIZE( 620.0f, 96.0f,0.0f ); ///< Default size of the bottom control area.
200 const float DEFAULT_RELATIVE_PARENT_WIDTH = 0.75f; ///< If width is not fixed, relative size to parent is used by default.
202 } // Unnamed namespace
208 Dali::Toolkit::Popup Popup::New()
210 // Create the implementation
211 PopupPtr popup( new Popup() );
213 // Pass ownership to CustomActor via derived handle.
214 Dali::Toolkit::Popup handle( *popup );
216 // Second-phase initialisation of the implementation.
217 // This can only be done after the CustomActor connection has been made.
224 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ),
225 mTouchedOutsideSignal(),
233 mPreviousFocusedActor(),
237 mAlterAddedChild( false ),
238 mLayoutDirty( true ),
240 mTouchTransparent( false ),
244 mDisplayState( Toolkit::Popup::HIDDEN ), // Hidden until shown with SetDisplayState()
245 mTailVisible( false ),
246 mTailPosition( DEFAULT_TAIL_POSITION ),
247 mContextualMode( Toolkit::Popup::NON_CONTEXTUAL ),
248 mAnimationDuration( DEFAULT_POPUP_ANIMATION_DURATION ),
249 mAnimationMode( Toolkit::Popup::FADE ),
250 mEntryAnimationData(),
251 mExitAnimationData(),
253 mBackingEnabled( true ),
254 mBackingColor( DEFAULT_BACKING_COLOR ),
255 mPopupBackgroundImage(),
256 mBackgroundOuterBorder(),
258 mTailUpImage( DEFAULT_TAIL_UP_IMAGE_PATH ),
259 mTailDownImage( DEFAULT_TAIL_DOWN_IMAGE_PATH ),
260 mTailLeftImage( DEFAULT_TAIL_LEFT_IMAGE_PATH ),
261 mTailRightImage( DEFAULT_TAIL_RIGHT_IMAGE_PATH )
263 SetKeyboardNavigationSupport( true );
266 void Popup::OnInitialize()
269 self.SetName( "popup" );
271 // Apply some default resizing rules.
272 self.SetParentOrigin( ParentOrigin::CENTER );
273 self.SetAnchorPoint( AnchorPoint::CENTER );
275 self.SetSizeModeFactor( DEFAULT_POPUP_PARENT_RELATIVE_SIZE );
276 self.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::WIDTH );
277 self.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT );
279 // Create a new layer so all Popup components can appear above all other actors.
280 mLayer = Layer::New();
281 mLayer.SetName( "popupLayer" );
283 mLayer.SetParentOrigin( ParentOrigin::CENTER );
284 mLayer.SetAnchorPoint( AnchorPoint::CENTER );
285 mLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
287 // Important to set as invisible as otherwise, if the popup is parented,
288 // but not shown yet it will appear statically on the screen.
289 mLayer.SetVisible( false );
291 // Add the layer to the hierarchy.
294 // Add Backing (Dimmed effect).
295 mBacking = CreateBacking();
296 mLayer.Add( mBacking );
298 mPopupContainer = Actor::New();
299 mPopupContainer.SetName( "popupContainer" );
300 mPopupContainer.SetParentOrigin( ParentOrigin::CENTER );
301 mPopupContainer.SetAnchorPoint( AnchorPoint::CENTER );
302 mPopupContainer.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
303 mLayer.Add( mPopupContainer );
305 // Create the Popup layout to contain all main content.
306 mPopupLayout = Toolkit::TableView::New( 3, 1 );
308 // Adds the default background image.
309 SetPopupBackgroundImage( Toolkit::ImageView::New( ResourceImage::New( DEFAULT_BACKGROUND_IMAGE_PATH ) ) );
311 mPopupLayout.SetName( "popupLayoutTable" );
312 mPopupLayout.SetParentOrigin( ParentOrigin::CENTER );
313 mPopupLayout.SetAnchorPoint( AnchorPoint::CENTER );
315 mPopupLayout.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::WIDTH );
316 mPopupLayout.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT );
317 mPopupLayout.SetSize( Stage::GetCurrent().GetSize().x * DEFAULT_RELATIVE_PARENT_WIDTH, 0.0f );
319 mPopupLayout.SetFitHeight( 0 ); // Set row to fit.
320 mPopupLayout.SetFitHeight( 1 ); // Set row to fit.
322 mPopupLayout.TouchedSignal().Connect( this, &Popup::OnDialogTouched );
324 mPopupContainer.Add( mPopupLayout );
326 // Any content after this point which is added to Self() will be re-parented to mContent.
327 mAlterAddedChild = true;
329 SetAsKeyboardFocusGroup( true );
334 mEntryAnimationData.Clear();
335 mExitAnimationData.Clear();
338 void Popup::LayoutAnimation()
340 // Perform setup based on the currently selected animation.
341 switch( mAnimationMode )
343 case Toolkit::Popup::ZOOM:
345 // Zoom animations start fully zoomed out.
346 mPopupContainer.SetScale( Vector3::ZERO );
350 case Toolkit::Popup::FADE:
352 // Fade animations start transparent.
353 mPopupContainer.SetOpacity( 0.0f );
357 case Toolkit::Popup::CUSTOM:
359 // Initialise the custom animation by playing to the end of it's exit animation instantly.
360 // EG. If it was zooming in, then we zoom out fully instantly so the zoom in works.
361 StartTransitionAnimation( false, true );
365 case Toolkit::Popup::NONE:
372 void Popup::StartTransitionAnimation( bool transitionIn, bool instantaneous /* false */ )
374 // Stop and recreate animation.
381 float duration = GetAnimationDuration();
383 // Setup variables ready to start the animations.
384 // If we are performing the animation instantaneously, we do not want to emit a signal.
389 // Setup variables and signal that we are starting the transition.
390 // Note: We signal even if the transition is instant so signal order is consistent.
391 mShowingSignal.Emit();
395 mHidingSignal.Emit();
399 // Perform chosen animation for the Popup.
400 switch( mAnimationMode )
402 case Toolkit::Popup::NONE:
404 mAnimation = Animation::New( 0.0f );
408 case Toolkit::Popup::ZOOM:
410 mAnimation = Animation::New( duration );
411 if( duration > Math::MACHINE_EPSILON_0 )
415 mAnimation.AnimateTo( Property( mPopupContainer, Actor::Property::SCALE ), Vector3::ONE, AlphaFunction::EASE_IN_OUT, TimePeriod( duration * 0.25f, duration * 0.75f ) );
419 // Zoom out animation is twice the speed. Modify the duration variable so the backing animation speed is modified also.
421 mAnimation.SetDuration( duration );
422 mAnimation.AnimateTo( Property( mPopupContainer, Actor::Property::SCALE ), Vector3::ZERO, AlphaFunction::EASE_IN_OUT, TimePeriod( 0.0f, duration ) );
427 mPopupContainer.SetScale( transitionIn ? Vector3::ONE : Vector3::ZERO );
432 case Toolkit::Popup::FADE:
434 mAnimation = Animation::New( duration );
435 if( duration > Math::MACHINE_EPSILON_0 )
439 mAnimation.AnimateTo( Property( mPopupContainer, Actor::Property::COLOR_ALPHA ), 1.0f, AlphaFunction::EASE_IN_OUT, TimePeriod( 0.30f, duration * 0.70f ) );
443 mAnimation.AnimateTo( Property( mPopupContainer, Actor::Property::COLOR_ALPHA ), 0.0f, AlphaFunction::EASE_IN_OUT, TimePeriod( 0.0f, duration * 0.70f ) );
448 mPopupContainer.SetOpacity( transitionIn ? 1.0f : 0.0f );
453 case Toolkit::Popup::CUSTOM:
455 // Use a user specified animation for in and out.
456 // Read the correct animation depending on entry or exit.
457 // Attempt to use animation data defined from script data.
458 Dali::AnimationData* animationData = transitionIn ? &mEntryAnimationData : &mExitAnimationData;
460 // Create a new animation from the pre-defined data in the AnimationData class.
461 // If there is no data, mAnimation is invalidated.
462 mAnimation = animationData->CreateAnimation( mPopupContainer, duration );
464 // If we don't have a valid animation, provide a blank one so play() can still function generically.
467 // No animation was configured (even though custom mode was specified). Create a dummy animation to avoid an exception.
468 mAnimation = Animation::New( 0.0f );
475 // Animate the backing, if enabled.
476 // This is set up last so that different animation modes can have an effect on the backing animation speed.
477 if( mBackingEnabled )
479 // Use the alpha from the user-specified color.
480 float targetAlpha = mBackingColor.a;
481 if( duration > Math::MACHINE_EPSILON_0 )
485 mAnimation.AnimateTo( Property( mBacking, Actor::Property::COLOR_ALPHA ), targetAlpha, AlphaFunction::EASE_IN_OUT, TimePeriod( 0.0f, duration * 0.70f ) );
489 mAnimation.AnimateTo( Property( mBacking, Actor::Property::COLOR_ALPHA ), 0.0f, AlphaFunction::EASE_IN_OUT, TimePeriod( 0.30f, duration * 0.70f ) );
494 mBacking.SetProperty( Actor::Property::COLOR_ALPHA, transitionIn ? targetAlpha : 0.0f );
498 // If we are performing the animation instantaneously, jump to the position directly and do not signal.
501 mAnimation.SetCurrentProgress( 1.0f );
504 else if( duration > Math::MACHINE_EPSILON_0 )
506 // Run the animation.
507 mAnimation.FinishedSignal().Connect( this, &Popup::OnDisplayChangeAnimationFinished );
512 // We did not use an animation to achive the transition.
513 // Trigger the state change directly.
514 DisplayStateChangeComplete();
518 void Popup::OnDisplayChangeAnimationFinished( Animation& source )
520 DisplayStateChangeComplete();
523 void Popup::DisplayStateChangeComplete()
525 // Remove contents from stage if completely hidden.
526 if( mDisplayState == Toolkit::Popup::HIDING )
528 mDisplayState = Toolkit::Popup::HIDDEN;
530 mLayer.SetVisible( false );
531 mPopupLayout.SetSensitive( false );
533 // Guard against destruction during signal emission.
534 Toolkit::Popup handle( GetOwner() );
535 mHiddenSignal.Emit();
537 else if( mDisplayState == Toolkit::Popup::SHOWING )
539 mDisplayState = Toolkit::Popup::SHOWN;
540 Toolkit::Popup handle( GetOwner() );
543 // Start a timer to auto-hide if enabled.
544 if( mAutoHideDelay > 0u )
546 mAutoHideTimer = Timer::New( mAutoHideDelay );
547 mAutoHideTimer.TickSignal().Connect( this, &Popup::OnAutoHideTimeReached );
548 mAutoHideTimer.Start();
553 bool Popup::OnAutoHideTimeReached()
555 // Display timer has expired, auto hide the popup exactly as if the user had clicked outside.
556 SetDisplayState( Toolkit::Popup::HIDDEN );
560 mAutoHideTimer.Stop();
561 mAutoHideTimer.TickSignal().Disconnect( this, &Popup::OnAutoHideTimeReached );
562 mAutoHideTimer.Reset();
567 void Popup::SetPopupBackgroundImage( Actor image )
569 // Removes any previous background.
570 if( mPopupBackgroundImage )
572 mPopupContainer.Remove( mPopupBackgroundImage );
575 // Adds new background to the dialog.
576 mPopupBackgroundImage = image;
577 mPopupBackgroundImage.SetName( "popupBackgroundImage" );
578 mPopupBackgroundImage.SetAnchorPoint( AnchorPoint::CENTER );
579 mPopupBackgroundImage.SetParentOrigin( ParentOrigin::CENTER );
581 // OnDialogTouched only consumes the event. It prevents the touch event to be caught by the backing.
582 mPopupBackgroundImage.TouchedSignal().Connect( this, &Popup::OnDialogTouched );
584 // Set the popup border to be slightly larger than the layout contents.
585 mPopupBackgroundImage.SetResizePolicy( ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT, Dimension::ALL_DIMENSIONS );
586 mPopupBackgroundImage.SetSizeModeFactor( BACKGROUND_OUTER_BORDER );
588 const bool prevAlter = mAlterAddedChild;
589 mAlterAddedChild = false;
590 mPopupContainer.Add( mPopupBackgroundImage );
591 mAlterAddedChild = prevAlter;
596 Actor Popup::GetPopupBackgroundImage() const
598 return mPopupBackgroundImage;
601 void Popup::SetTitle( Actor titleActor )
603 // Replaces the current title actor.
611 mPopupLayout.RemoveChildAt( Toolkit::TableView::CellPosition( 0, 0) );
617 // Set up padding to give sensible default behaviour
618 // (an application developer can later override this if they wish).
619 mTitle.SetPadding( DEFAULT_TITLE_PADDING );
621 mPopupLayout.AddChild( mTitle, Toolkit::TableView::CellPosition( 0, 0 ) );
628 Actor Popup::GetTitle() const
633 void Popup::SetContent( Actor content )
635 // Remove previous content actor.
638 mPopupLayout.RemoveChildAt( Toolkit::TableView::CellPosition( 1, 0 ) );
640 // Keep a handle to the new content.
645 mContent.SetName( "popupContent" );
647 mPopupLayout.AddChild( mContent, Toolkit::TableView::CellPosition( 1, 0 ) );
654 Actor Popup::GetContent() const
659 void Popup::SetFooter( Actor footer )
661 // Remove previous content actor.
664 mPopupLayout.RemoveChildAt( Toolkit::TableView::CellPosition( 2, 0 ) );
667 // Keep a handle to the new content.
672 mFooter.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
674 // The control container has a fixed height.
675 mPopupLayout.SetFitHeight( 2u );
676 mPopupLayout.AddChild( footer, Toolkit::TableView::CellPosition( 2, 0 ) );
683 Actor Popup::GetFooter() const
688 void Popup::SetDisplayState( Toolkit::Popup::DisplayState displayState )
690 // Convert the 4-way state to a bool, true for show, false for hide.
691 bool display = ( displayState == Toolkit::Popup::SHOWING ) || ( displayState == Toolkit::Popup::SHOWN );
693 // Ignore if we are already at the target display state.
694 if( display == ( ( mDisplayState == Toolkit::Popup::SHOWING ) || ( mDisplayState == Toolkit::Popup::SHOWN ) ) )
699 // Convert the bool state to the actual display state to use.
700 mDisplayState = display ? Toolkit::Popup::SHOWING : Toolkit::Popup::HIDING;
704 // Update the state to indicate the current intent.
705 mDisplayState = Toolkit::Popup::SHOWING;
707 // We are displaying so bring the popup layer to the front, and set it visible so it is rendered.
709 mLayer.SetVisible( true );
711 // Set up the layout if this is the first display or the layout has become dirty.
714 // Bake-in any style and layout options to create the Popup layout.
718 // Allow the popup to catch events.
719 mPopupLayout.SetSensitive( true );
721 // Handle the keyboard focus when popup is shown.
722 Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get();
723 if( keyboardFocusManager )
725 mPreviousFocusedActor = keyboardFocusManager.GetCurrentFocusActor();
727 if( Self().IsKeyboardFocusable() )
729 // Setup the actgor to start focus from.
731 if( mContent && mContent.IsKeyboardFocusable() )
733 // If the content is focusable, move the focus to the content.
734 focusActor = mContent;
736 else if( mFooter && mFooter.IsKeyboardFocusable() )
738 // If the footer is focusable, move the focus to the footer.
739 focusActor = mFooter;
743 DALI_LOG_WARNING( "There is no focusable in popup\n" );
749 keyboardFocusManager.SetCurrentFocusActor( focusActor );
756 mDisplayState = Toolkit::Popup::HIDING;
757 ClearKeyInputFocus();
759 // Restore the keyboard focus when popup is hidden.
760 if( mPreviousFocusedActor && mPreviousFocusedActor.IsKeyboardFocusable() )
762 Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get();
763 if( keyboardFocusManager )
765 keyboardFocusManager.SetCurrentFocusActor( mPreviousFocusedActor );
770 // Perform animation.
771 StartTransitionAnimation( display );
774 Toolkit::Popup::DisplayState Popup::GetDisplayState() const
776 return mDisplayState;
779 void Popup::LayoutPopup()
781 mLayoutDirty = false;
783 /* When animating in, we want to respect the origin applied to Self().
784 * For example, if zooming, not only will the final result be anchored to the
785 * selected point, but the zoom will originate from this point also.
787 * EG: ParentOrigin::TOP_LEFT, AnchorPoint::TOP_LEFT :
796 mPopupContainer.SetParentOrigin( Self().GetCurrentParentOrigin() );
797 mPopupContainer.SetAnchorPoint( Self().GetCurrentAnchorPoint() );
799 // If there is only a title, use less padding.
802 if( !mContent && !mFooter )
804 mTitle.SetPadding( DEFAULT_TITLE_ONLY_PADDING );
808 mTitle.SetPadding( DEFAULT_TITLE_PADDING );
812 // Allow derived classes to perform any layout they may need to do.
815 // Update background visibility.
816 mPopupContainer.SetVisible( !( !mFooter && mPopupLayout.GetChildCount() == 0 ) );
818 // Create / destroy / position the tail as needed.
821 // Setup any layout and initialisation required for the selected animation.
827 void Popup::LayoutTail()
829 // Removes the tail actor.
830 if( mTailImage && mTailImage.GetParent() )
832 mTailImage.GetParent().Remove( mTailImage );
841 const Vector3& position = GetTailPosition();
844 // depending on position of tail around ParentOrigin, a different tail image is used...
845 if( position.y < Math::MACHINE_EPSILON_1 )
847 image = mTailUpImage;
849 else if( position.y > 1.0f - Math::MACHINE_EPSILON_1 )
851 image = mTailDownImage;
853 else if( position.x < Math::MACHINE_EPSILON_1 )
855 image = mTailLeftImage;
857 else if( position.x > 1.0f - Math::MACHINE_EPSILON_1 )
859 image = mTailRightImage;
864 // Adds the tail actor.
865 Image tail = ResourceImage::New( image );
866 mTailImage = Toolkit::ImageView::New( tail );
867 mTailImage.SetName( "tailImage" );
868 const Vector3 anchorPoint = AnchorPoint::BOTTOM_RIGHT - position;
869 mTailImage.SetParentOrigin( position );
870 mTailImage.SetAnchorPoint( anchorPoint );
872 mPopupContainer.Add( mTailImage );
876 void Popup::SetContextualMode( Toolkit::Popup::ContextualMode mode )
878 mContextualMode = mode;
882 Toolkit::Popup::ContextualMode Popup::GetContextualMode() const
884 return mContextualMode;
887 Toolkit::Control Popup::CreateBacking()
889 Toolkit::Control backing = Control::New();
890 backing.SetBackgroundColor( Vector4( mBackingColor.r, mBackingColor.g, mBackingColor.b, 1.0f ) );
891 backing.SetName( "popupBacking" );
893 // Must always be positioned top-left of stage, regardless of parent.
894 backing.SetInheritPosition(false);
895 backing.SetAnchorPoint( AnchorPoint::TOP_LEFT );
897 // Always the full size of the stage.
898 backing.SetResizePolicy( ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS );
899 backing.SetSize( Stage::GetCurrent().GetSize() );
902 backing.SetSensitive( true );
904 // Default to being transparent.
905 backing.SetProperty( Actor::Property::COLOR_ALPHA, 0.0f );
906 backing.TouchedSignal().Connect( this, &Popup::OnBackingTouched );
907 backing.WheelEventSignal().Connect( this, &Popup::OnBackingWheelEvent );
911 Toolkit::Popup::TouchedOutsideSignalType& Popup::OutsideTouchedSignal()
913 return mTouchedOutsideSignal;
916 Toolkit::Popup::DisplayStateChangeSignalType& Popup::ShowingSignal()
918 return mShowingSignal;
921 Toolkit::Popup::DisplayStateChangeSignalType& Popup::ShownSignal()
926 Toolkit::Popup::DisplayStateChangeSignalType& Popup::HidingSignal()
928 return mHidingSignal;
931 Toolkit::Popup::DisplayStateChangeSignalType& Popup::HiddenSignal()
933 return mHiddenSignal;
936 void Popup::SetTailVisibility( bool visible )
938 mTailVisible = visible;
942 const bool Popup::IsTailVisible() const
947 void Popup::SetTailPosition( Vector3 position )
949 mTailPosition = position;
953 const Vector3& Popup::GetTailPosition() const
955 return mTailPosition;
958 void Popup::SetAnimationDuration( float duration )
960 mAnimationDuration = duration;
964 float Popup::GetAnimationDuration() const
966 return mAnimationDuration;
969 void Popup::SetAnimationMode( Toolkit::Popup::AnimationMode animationMode )
971 mAnimationMode = animationMode;
975 Toolkit::Popup::AnimationMode Popup::GetAnimationMode() const
977 return mAnimationMode;
980 void Popup::SetEntryAnimationData( const Property::Map& map )
982 mEntryAnimationData.Clear();
983 Scripting::NewAnimation( map, mEntryAnimationData );
986 void Popup::SetExitAnimationData( const Property::Map& map )
988 mExitAnimationData.Clear();
989 Scripting::NewAnimation( map, mExitAnimationData );
992 void Popup::SetAutoHideDelay( int delay )
994 mAutoHideDelay = delay;
997 int Popup::GetAutoHideDelay() const
999 return mAutoHideDelay;
1002 void Popup::SetBackingEnabled( bool enabled )
1004 mBackingEnabled = enabled;
1005 mLayoutDirty = true;
1008 const bool Popup::IsBackingEnabled() const
1010 return mBackingEnabled;
1013 void Popup::SetBackingColor( Vector4 color )
1015 mBackingColor = color;
1016 mBacking.SetBackgroundColor( Vector4( color.r, color.g, color.b, 1.0f ) );
1017 mLayoutDirty = true;
1020 const Vector4& Popup::GetBackingColor() const
1022 return mBackingColor;
1025 void Popup::SetTailUpImage( std::string image )
1027 mTailUpImage = image;
1028 mLayoutDirty = true;
1031 const std::string& Popup::GetTailUpImage() const
1033 return mTailUpImage;
1036 void Popup::SetTailDownImage( std::string image )
1038 mTailDownImage = image;
1039 mLayoutDirty = true;
1042 const std::string& Popup::GetTailDownImage() const
1044 return mTailDownImage;
1047 void Popup::SetTailLeftImage( std::string image )
1049 mTailLeftImage = image;
1050 mLayoutDirty = true;
1053 const std::string& Popup::GetTailLeftImage() const
1055 return mTailLeftImage;
1058 void Popup::SetTailRightImage( std::string image )
1060 mTailRightImage = image;
1061 mLayoutDirty = true;
1064 const std::string& Popup::GetTailRightImage() const
1066 return mTailRightImage;
1069 void Popup::SetTouchTransparent( bool enabled )
1071 mTouchTransparent = enabled;
1074 const bool Popup::IsTouchTransparent() const
1076 return mTouchTransparent;
1079 void Popup::SetProperty( BaseObject* object, Property::Index propertyIndex, const Property::Value& value )
1081 Toolkit::Popup popup = Toolkit::Popup::DownCast( Dali::BaseHandle( object ) );
1085 Popup& popupImpl( GetImpl( popup ) );
1087 switch ( propertyIndex )
1089 case Toolkit::Popup::Property::TITLE:
1091 Property::Map valueMap;
1092 if( value.Get( valueMap ) )
1094 popupImpl.SetTitle( Scripting::NewActor( valueMap ) );
1098 case Toolkit::Popup::Property::CONTENT:
1100 Property::Map valueMap;
1101 if( value.Get( valueMap ) )
1103 popupImpl.SetContent( Scripting::NewActor( valueMap ) );
1107 case Toolkit::Popup::Property::FOOTER:
1109 Property::Map valueMap;
1110 if( value.Get( valueMap ) )
1112 popupImpl.SetFooter( Scripting::NewActor( valueMap ) );
1116 case Toolkit::Popup::Property::DISPLAY_STATE:
1118 std::string valueString;
1119 if( value.Get( valueString ) )
1121 Toolkit::Popup::DisplayState displayState( Toolkit::Popup::HIDDEN );
1122 if( Scripting::GetEnumeration< Toolkit::Popup::DisplayState >( valueString.c_str(), DisplayStateTable, DisplayStateTableCount, displayState ) )
1124 popupImpl.SetDisplayState( displayState );
1129 case Toolkit::Popup::Property::TOUCH_TRANSPARENT:
1132 if( value.Get( valueBool ) )
1134 popupImpl.SetTouchTransparent( valueBool );
1138 case Toolkit::Popup::Property::TAIL_VISIBILITY:
1141 if( value.Get( valueBool ) )
1143 popupImpl.SetTailVisibility( valueBool );
1147 case Toolkit::Popup::Property::TAIL_POSITION:
1149 Vector3 valueVector3;
1150 if( value.Get( valueVector3 ) )
1152 popupImpl.SetTailPosition( valueVector3 );
1156 case Toolkit::Popup::Property::CONTEXTUAL_MODE:
1158 std::string valueString;
1159 if( value.Get( valueString ) )
1161 Toolkit::Popup::ContextualMode contextualMode( Toolkit::Popup::BELOW );
1162 if( Scripting::GetEnumeration< Toolkit::Popup::ContextualMode >( valueString.c_str(), ContextualModeTable, ContextualModeTableCount, contextualMode ) )
1164 popupImpl.SetContextualMode( contextualMode );
1169 case Toolkit::Popup::Property::ANIMATION_DURATION:
1172 if( value.Get( valueFloat ) )
1174 popupImpl.SetAnimationDuration( valueFloat );
1178 case Toolkit::Popup::Property::ANIMATION_MODE:
1180 std::string valueString;
1181 if( value.Get( valueString ) )
1183 Toolkit::Popup::AnimationMode animationMode( Toolkit::Popup::FADE );
1184 if( Scripting::GetEnumeration< Toolkit::Popup::AnimationMode >( valueString.c_str(), AnimationModeTable, AnimationModeTableCount, animationMode ) )
1186 popupImpl.SetAnimationMode( animationMode );
1191 case Toolkit::Popup::Property::ENTRY_ANIMATION:
1193 Property::Map valueMap;
1194 if( value.Get( valueMap ) )
1196 popupImpl.SetEntryAnimationData( valueMap );
1200 case Toolkit::Popup::Property::EXIT_ANIMATION:
1202 Property::Map valueMap;
1203 if( value.Get( valueMap ) )
1205 popupImpl.SetExitAnimationData( valueMap );
1209 case Toolkit::Popup::Property::AUTO_HIDE_DELAY:
1212 if( value.Get( valueInt ) )
1214 popupImpl.SetAutoHideDelay( valueInt );
1218 case Toolkit::Popup::Property::BACKING_ENABLED:
1221 if( value.Get( valueBool ) )
1223 popupImpl.SetBackingEnabled( valueBool );
1227 case Toolkit::Popup::Property::BACKING_COLOR:
1229 Vector4 valueVector4;
1230 if( value.Get( valueVector4 ) )
1232 popupImpl.SetBackingColor( valueVector4 );
1236 case Toolkit::Popup::Property::POPUP_BACKGROUND_IMAGE:
1238 std::string valueString;
1239 if( value.Get( valueString ) )
1241 Image image = ResourceImage::New( valueString );
1244 Toolkit::ImageView actor = Toolkit::ImageView::New( image );
1245 popupImpl.SetPopupBackgroundImage( actor );
1250 case Toolkit::Popup::Property::TAIL_UP_IMAGE:
1252 std::string valueString;
1253 if( value.Get( valueString ) )
1255 popupImpl.SetTailUpImage( valueString );
1259 case Toolkit::Popup::Property::TAIL_DOWN_IMAGE:
1261 std::string valueString;
1262 if( value.Get( valueString ) )
1264 popupImpl.SetTailDownImage( valueString );
1268 case Toolkit::Popup::Property::TAIL_LEFT_IMAGE:
1270 std::string valueString;
1271 if( value.Get( valueString ) )
1273 popupImpl.SetTailLeftImage( valueString );
1277 case Toolkit::Popup::Property::TAIL_RIGHT_IMAGE:
1279 std::string valueString;
1280 if( value.Get( valueString ) )
1282 popupImpl.SetTailRightImage( valueString );
1290 Property::Value Popup::GetProperty( BaseObject* object, Property::Index propertyIndex )
1292 Property::Value value;
1294 Toolkit::Popup popup = Toolkit::Popup::DownCast( Dali::BaseHandle( object ) );
1298 Popup& popupImpl( GetImpl( popup ) );
1300 switch ( propertyIndex )
1302 case Toolkit::Popup::Property::TITLE:
1305 Scripting::CreatePropertyMap( popupImpl.GetTitle(), map );
1309 case Toolkit::Popup::Property::CONTENT:
1312 Scripting::CreatePropertyMap( popupImpl.GetContent(), map );
1316 case Toolkit::Popup::Property::FOOTER:
1319 Scripting::CreatePropertyMap( popupImpl.GetFooter(), map );
1323 case Toolkit::Popup::Property::DISPLAY_STATE:
1325 value = Scripting::GetLinearEnumerationName< Toolkit::Popup::DisplayState >( popupImpl.GetDisplayState(), DisplayStateTable, DisplayStateTableCount );
1328 case Toolkit::Popup::Property::TOUCH_TRANSPARENT:
1330 value = popupImpl.IsTouchTransparent();
1333 case Toolkit::Popup::Property::TAIL_VISIBILITY:
1335 value = popupImpl.IsTailVisible();
1338 case Toolkit::Popup::Property::TAIL_POSITION:
1340 value = popupImpl.GetTailPosition();
1343 case Toolkit::Popup::Property::CONTEXTUAL_MODE:
1345 value = Scripting::GetLinearEnumerationName< Toolkit::Popup::ContextualMode >( popupImpl.GetContextualMode(), ContextualModeTable, ContextualModeTableCount );
1348 case Toolkit::Popup::Property::ANIMATION_DURATION:
1350 value = popupImpl.GetAnimationDuration();
1353 case Toolkit::Popup::Property::ANIMATION_MODE:
1355 value = Scripting::GetLinearEnumerationName< Toolkit::Popup::AnimationMode >( popupImpl.GetAnimationMode(), AnimationModeTable, AnimationModeTableCount );
1358 case Toolkit::Popup::Property::ENTRY_ANIMATION:
1360 // Note: Cannot retrieve property map from animation.
1365 case Toolkit::Popup::Property::EXIT_ANIMATION:
1367 // Note: Cannot retrieve property map from animation.
1372 case Toolkit::Popup::Property::AUTO_HIDE_DELAY:
1374 value = popupImpl.GetAutoHideDelay();
1377 case Toolkit::Popup::Property::BACKING_ENABLED:
1379 value = popupImpl.IsBackingEnabled();
1382 case Toolkit::Popup::Property::BACKING_COLOR:
1384 value = popupImpl.GetBackingColor();
1387 case Toolkit::Popup::Property::POPUP_BACKGROUND_IMAGE:
1389 ResourceImage image = ResourceImage::DownCast( popupImpl.GetPopupBackgroundImage() );
1392 value = image.GetUrl();
1396 case Toolkit::Popup::Property::TAIL_UP_IMAGE:
1398 value = popupImpl.GetTailUpImage();
1401 case Toolkit::Popup::Property::TAIL_DOWN_IMAGE:
1403 value = popupImpl.GetTailDownImage();
1406 case Toolkit::Popup::Property::TAIL_LEFT_IMAGE:
1408 value = popupImpl.GetTailLeftImage();
1411 case Toolkit::Popup::Property::TAIL_RIGHT_IMAGE:
1413 value = popupImpl.GetTailRightImage();
1422 bool Popup::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1424 Dali::BaseHandle handle( object );
1426 bool connected( true );
1427 Toolkit::Popup popup = Toolkit::Popup::DownCast( handle );
1429 if( 0 == strcmp( signalName.c_str(), SIGNAL_TOUCHED_OUTSIDE ) )
1431 popup.OutsideTouchedSignal().Connect( tracker, functor );
1433 else if( 0 == strcmp( signalName.c_str(), SIGNAL_SHOWING ) )
1435 popup.ShowingSignal().Connect( tracker, functor );
1437 else if( 0 == strcmp( signalName.c_str(), SIGNAL_SHOWN ) )
1439 popup.ShownSignal().Connect( tracker, functor );
1441 else if( 0 == strcmp( signalName.c_str(), SIGNAL_HIDING ) )
1443 popup.HidingSignal().Connect( tracker, functor );
1445 else if( 0 == strcmp( signalName.c_str(), SIGNAL_HIDDEN ) )
1447 popup.HiddenSignal().Connect( tracker, functor );
1451 // signalName does not match any signal
1458 bool Popup::OnBackingTouched( Actor actor, const TouchEvent& event )
1460 // Allow events to pass through if touch transparency is enabled.
1461 if( mTouchTransparent )
1466 if( event.GetPointCount() > 0 )
1468 const TouchPoint& point = event.GetPoint( 0 );
1470 if( point.state == TouchPoint::Down )
1472 // Guard against destruction during signal emission.
1473 Toolkit::Popup handle( GetOwner() );
1475 mTouchedOutsideSignal.Emit();
1479 // Block anything behind backing becoming touched.
1480 mLayer.SetTouchConsumed( true );
1484 bool Popup::OnBackingWheelEvent( Actor actor, const WheelEvent& event )
1486 // Allow events to pass through if touch transparency is enabled.
1487 if( mTouchTransparent )
1492 // Consume wheel event in dimmed backing actor.
1493 mLayer.SetTouchConsumed( true );
1497 bool Popup::OnDialogTouched(Actor actor, const TouchEvent& event)
1499 // Allow events to pass through if touch transparency is enabled.
1500 if( mTouchTransparent )
1505 // Consume event (stops backing actor receiving touch events)
1506 mLayer.SetTouchConsumed( true );
1510 void Popup::OnControlStageConnection()
1512 mLayoutDirty = true;
1516 void Popup::OnControlChildAdd( Actor& child )
1518 // Re-parent any children added by user to the body layer.
1519 if( mAlterAddedChild )
1521 SetContent( child );
1525 mLayoutDirty = true;
1530 void Popup::LayoutContext( const Vector2& size )
1532 // Do nothing if not in a contextual mode (or there is no parent context).
1533 Actor self = Self();
1534 Actor parent = self.GetParent();
1535 if( ( mContextualMode == Toolkit::Popup::NON_CONTEXTUAL ) || !parent )
1540 mPopupContainer.SetParentOrigin( ParentOrigin::CENTER );
1541 // We always anchor to the CENTER, rather than a different anchor point for each contextual
1542 // mode to allow code-reuse of the bound checking code (for maintainability).
1543 mPopupContainer.SetAnchorPoint( AnchorPoint::CENTER );
1545 // Setup with some pre-calculations for speed.
1546 Vector3 halfStageSize( Stage().GetCurrent().GetSize() / 2.0f );
1547 Vector3 parentPosition( parent.GetCurrentPosition() );
1548 Vector2 halfSize( size / 2.0f );
1549 Vector2 halfParentSize( parent.GetRelayoutSize( Dimension::WIDTH ) / 2.0f, parent.GetRelayoutSize( Dimension::HEIGHT ) / 2.0f );
1550 Vector3 newPosition( Vector3::ZERO );
1552 // Perform different positioning based on the specified contextual layout mode.
1553 switch( mContextualMode )
1555 case Toolkit::Popup::BELOW:
1557 newPosition.x += halfSize.x - halfParentSize.x;
1558 newPosition.y += halfSize.y + halfParentSize.y + DEFAULT_CONTEXTUAL_ADJACENCY_MARGIN.y;
1561 case Toolkit::Popup::ABOVE:
1563 newPosition.x += halfSize.x - halfParentSize.x;
1564 newPosition.y -= halfSize.y + halfParentSize.y + DEFAULT_CONTEXTUAL_ADJACENCY_MARGIN.y;
1567 case Toolkit::Popup::RIGHT:
1569 newPosition.x += halfSize.x + halfParentSize.x + DEFAULT_CONTEXTUAL_ADJACENCY_MARGIN.x;
1570 newPosition.y += halfSize.y - halfParentSize.y;
1573 case Toolkit::Popup::LEFT:
1575 newPosition.x -= halfSize.x + halfParentSize.x + DEFAULT_CONTEXTUAL_ADJACENCY_MARGIN.x;
1576 newPosition.y += halfSize.y - halfParentSize.y;
1579 case Toolkit::Popup::NON_CONTEXTUAL:
1581 // Code won't reach here (caught earlier).
1586 // On-screen position checking.
1587 // Check new position is not too far right. If so, correct it.
1588 // Note: Check for right rather than left first, so if popup is too wide, the left check overrides
1589 // the right check and we at least see the left portion of the popup (as this is more useful).
1590 if( newPosition.x >= ( halfStageSize.x - parentPosition.x - halfSize.x - DEFAULT_CONTEXTUAL_STAGE_BORDER.x ) )
1592 newPosition.x = halfStageSize.x - parentPosition.x - halfSize.x - DEFAULT_CONTEXTUAL_STAGE_BORDER.x;
1594 // Check new position is not too far left. If so, correct it.
1595 if( newPosition.x < halfSize.x - ( parentPosition.x + halfStageSize.x ) + DEFAULT_CONTEXTUAL_STAGE_BORDER.x )
1597 newPosition.x = halfSize.x - ( parentPosition.x + halfStageSize.x ) + DEFAULT_CONTEXTUAL_STAGE_BORDER.x;// - parentSize.x;
1599 // Check new position is not too far down. If so, correct it.
1600 if( newPosition.y >= ( halfStageSize.y - parentPosition.y - halfSize.y - DEFAULT_CONTEXTUAL_STAGE_BORDER.y ) )
1602 newPosition.y = halfStageSize.y - parentPosition.y - halfSize.y - DEFAULT_CONTEXTUAL_STAGE_BORDER.y;
1604 // Check new position is not too far up. If so, correct it.
1605 if( newPosition.y < halfSize.y - ( parentPosition.y + halfStageSize.y ) + DEFAULT_CONTEXTUAL_STAGE_BORDER.y )
1607 newPosition.y = halfSize.y - ( parentPosition.y + halfStageSize.y ) + DEFAULT_CONTEXTUAL_STAGE_BORDER.y;
1610 // Set the final position.
1611 mPopupContainer.SetPosition( newPosition );
1614 void Popup::OnRelayout( const Vector2& size, RelayoutContainer& container )
1616 Vector2 useSize( size );
1618 // Use the Popup layouts size, unless requested to use a fixed size.
1619 // In which case take the size set for the Popup itself.
1620 ResizePolicy::Type widthPolicy = Self().GetResizePolicy( Dimension::WIDTH );
1621 ResizePolicy::Type heightPolicy = Self().GetResizePolicy( Dimension::HEIGHT );
1623 // Width calculations:
1624 if( widthPolicy == ResizePolicy::USE_NATURAL_SIZE || widthPolicy == ResizePolicy::FIT_TO_CHILDREN )
1626 // If we using a child-based policy, take the size from the popup layout.
1627 mPopupLayout.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::WIDTH );
1628 useSize.width = mPopupLayout.GetRelayoutSize( Dimension::WIDTH );
1630 mPopupLayout.SetFitWidth( 0u );
1634 // If we using a parent-based policy, take the size from the popup object itself (self).
1635 mPopupLayout.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::WIDTH );
1637 mPopupLayout.SetFixedWidth( 0u, useSize.width );
1640 // Height calculations:
1641 // Title: Let the title be as high as it needs to be.
1642 mPopupLayout.SetFitHeight( 0u );
1644 // Footer: Convert the footer's resize policy to a TableView row policy.
1647 ResizePolicy::Type footerHeightPolicy = mFooter.GetResizePolicy( Dimension::HEIGHT );
1648 if( ( footerHeightPolicy == ResizePolicy::USE_NATURAL_SIZE ) ||
1649 ( footerHeightPolicy == ResizePolicy::FIT_TO_CHILDREN ) )
1651 mPopupLayout.SetFitHeight( 2u );
1653 else if( footerHeightPolicy == ResizePolicy::FIXED )
1655 mPopupLayout.SetFixedHeight( 2u, mFooter.GetRelayoutSize( Dimension::HEIGHT) );
1659 mPopupLayout.SetRelativeHeight( 2u, 1.0f );
1664 mPopupLayout.SetFixedHeight( 2u, 0.0f );
1667 // Popup contents: Adjust the tableview's policies based on the popup's policies.
1668 if( heightPolicy == ResizePolicy::USE_NATURAL_SIZE || heightPolicy == ResizePolicy::FIT_TO_CHILDREN )
1670 mPopupLayout.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT );
1672 // Let both the contents expand as necessary.
1673 mPopupLayout.SetFitHeight( 1u );
1674 useSize.height = mPopupLayout.GetRelayoutSize( Dimension::HEIGHT );
1678 mPopupLayout.SetResizePolicy( heightPolicy, Dimension::HEIGHT );
1680 // Let the content expand to fill the remaining space.
1681 mPopupLayout.SetRelativeHeight( 1u, 1.0f );
1682 mPopupLayout.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::HEIGHT );
1685 // Relayout the popup-layout to give it it's new size this frame.
1686 container.Add( mPopupLayout, useSize );
1690 container.Add( mContent, Vector2( mContent.GetRelayoutSize( Dimension::WIDTH ), mContent.GetRelayoutSize( Dimension::HEIGHT ) ) );
1693 // Perform contextual layout setup if required.
1694 // This is done each time in case the parent moves.
1695 // This will have no effect if no contextual mode is selected.
1696 LayoutContext( useSize );
1699 void Popup::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1701 // To get the popup to emulate fit-to-children, we need to actually set use-natural-size.
1702 if( ( dimension & Dimension::HEIGHT ) && ( policy == ResizePolicy::FIT_TO_CHILDREN ) )
1704 Self().SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT );
1707 mLayoutDirty = true;
1711 Vector3 Popup::GetNaturalSize()
1713 return mPopupLayout.GetNaturalSize();
1716 float Popup::GetHeightForWidth( float width )
1718 return mPopupLayout.GetHeightForWidth( width );
1721 float Popup::GetWidthForHeight( float height )
1723 return mPopupLayout.GetWidthForHeight( height );
1726 bool Popup::OnKeyEvent( const KeyEvent& event )
1728 // Allow events to pass through if touch transparency is enabled.
1729 if( mTouchTransparent )
1734 bool consumed = false;
1736 if( event.state == KeyEvent::Down )
1738 if (event.keyCode == Dali::DALI_KEY_ESCAPE || event.keyCode == Dali::DALI_KEY_BACK)
1740 SetDisplayState( Toolkit::Popup::HIDDEN );
1748 void Popup::AddFocusableChildrenRecursive( Actor parent, std::vector< Actor >& focusableActors )
1752 Toolkit::Control control = Toolkit::Control::DownCast( parent );
1753 bool layoutControl = control && GetImplementation( control ).IsKeyboardNavigationSupported();
1755 if( parent.IsKeyboardFocusable() || layoutControl )
1757 focusableActors.push_back( parent );
1759 if( !layoutControl )
1761 for( unsigned int i = 0, numberChildren = parent.GetChildCount(); i < numberChildren; ++i )
1763 Actor child( parent.GetChildAt( i ) );
1764 AddFocusableChildrenRecursive( child, focusableActors );
1771 void Popup::AddFocusableChildren( Actor parent, std::vector< Actor >& focusableActors )
1775 Toolkit::Control control = Toolkit::Control::DownCast( parent );
1776 if( !GetImplementation( control ).IsKeyboardNavigationSupported() )
1778 for( unsigned int i = 0, numberChildren = parent.GetChildCount(); i < numberChildren; ++i )
1780 Actor child( parent.GetChildAt( i ) );
1781 AddFocusableChildrenRecursive( child, focusableActors );
1786 focusableActors.push_back( parent );
1791 Actor Popup::GetNextKeyboardFocusableActor( Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled )
1793 std::string currentStr;
1794 if( currentFocusedActor )
1796 currentStr = currentFocusedActor.GetName();
1799 Actor nextFocusableActor( currentFocusedActor );
1800 Actor currentFocusGroup;
1801 if( currentFocusedActor )
1803 currentFocusGroup = KeyboardFocusManager::Get().GetFocusGroup( currentFocusedActor );
1806 // TODO: Needs to be optimised
1807 // The following statement checks that if we have a current focused actor, then the current focus group is not the popup content or footer.
1808 // This is to detect if the focus is currently outside the popup, and if so, move it inside.
1809 if( !currentFocusedActor ||
1810 ( currentFocusedActor && ( ( !mContent || ( currentFocusGroup != mContent ) ) && ( !mFooter || ( currentFocusGroup != mFooter ) ) ) ) )
1812 // The current focused actor is not within popup.
1813 if( mContent && mContent.IsKeyboardFocusable() )
1815 // If the content is focusable, move the focus to the content.
1816 nextFocusableActor = mContent;
1818 else if( mFooter && mFooter.IsKeyboardFocusable() )
1820 // If the footer is focusable, move the focus to the footer.
1821 nextFocusableActor = mFooter;
1826 // Rebuild the focus chain because controls or content can be added or removed dynamically
1827 std::vector< Actor > focusableActors;
1829 AddFocusableChildren( mContent, focusableActors );
1830 AddFocusableChildren( mFooter, focusableActors );
1832 std::vector< Actor >::iterator endIterator = focusableActors.end();
1833 std::vector< Actor >::iterator currentIterator = focusableActors.begin();
1834 for( std::vector< Actor >::iterator iterator = focusableActors.begin(); iterator != endIterator; ++iterator )
1836 if( currentFocusedActor == *iterator )
1838 currentIterator = iterator;
1842 if( currentIterator != endIterator )
1846 case Toolkit::Control::KeyboardFocus::LEFT:
1848 if( currentIterator == focusableActors.begin() )
1850 nextFocusableActor = *( endIterator - 1 );
1854 nextFocusableActor = *( currentIterator - 1 );
1858 case Toolkit::Control::KeyboardFocus::RIGHT:
1860 if( currentIterator == endIterator - 1 )
1862 nextFocusableActor = *( focusableActors.begin() );
1866 nextFocusableActor = *( currentIterator + 1 );
1871 case Toolkit::Control::KeyboardFocus::UP:
1873 nextFocusableActor = *( focusableActors.begin() );
1877 case Toolkit::Control::KeyboardFocus::DOWN:
1879 nextFocusableActor = *( endIterator - 1 );
1884 if( !nextFocusableActor )
1886 DALI_LOG_WARNING( "Can not decide next focusable actor\n" );
1891 return nextFocusableActor;
1895 } // namespace Internal
1897 } // namespace Toolkit