2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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.
17 #include <dali-toolkit/internal/controls/popup/popup-impl.h>
19 #include <dali-toolkit/public-api/controls/buttons/button.h>
20 #include <dali-toolkit/public-api/controls/default-controls/solid-color-actor.h>
21 #include <dali-toolkit/public-api/controls/control-impl.h>
23 #include <dali-toolkit/internal/controls/relayout-helper.h>
24 #include <dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h>
26 #include <dali-toolkit/public-api/focus-manager/focus-manager.h>
27 #include <dali/integration-api/debug.h>
34 const float CONTENT_DEPTH = 1.0f; ///< 3D Effect of buttons/title etc. appearing off the popup.
35 const float POPUP_ANIMATION_DURATION = 0.5f; ///< Duration of hide/show animations
36 const float BACKING_DEPTH = -1.0f; ///< Depth of backing (positioned just behind dialog, so dialog catches hit events first)
38 const float POPUP_WIDTH = 720.0f; ///< Width of Popup
39 const float POPUP_OUT_MARGIN_WIDTH = 16.f; ///< Space between the screen edge and the popup edge in the horizontal dimension.
40 const float POPUP_OUT_MARGIN_HEIGHT = 36.f; ///< Space between the screen edge and the popup edge in the vertical dimension.
41 const float POPUP_TITLE_WIDTH = 648.0f; ///<Width of Popup Title
42 const float POPUP_BUTTON_BG_HEIGHT = 96.f; ///< Height of Button Background.
43 const Vector3 DEFAULT_DIALOG_SIZE = Vector3(POPUP_TITLE_WIDTH/POPUP_WIDTH, 0.5f, 0.0f);
44 const Vector3 DEFAULT_BOTTOM_SIZE = Vector3(1.0f, 0.2f, 0.0f);
46 // Constraints ///////////////////////////////////////////////////////////////////////////
49 * BackgroundSizeConstraint
51 * The background size should be at least as big as the Dialog.
52 * In some cases a background may have graphics which are visible
53 * outside of the Dialog, e.g. A Shadow. For this we need to alter
54 * the size of Background.
56 struct BackgroundSizeConstraint
59 * Constraint that sets size to parent's size plus a border.
61 * @param[in] outerBorder The border to extend beyond parent's Size.
63 BackgroundSizeConstraint( Vector4 outerBorder )
64 : mOuterBorder( outerBorder )
69 * (render thread code)
70 * @param[in] current The current size.
71 * @param[in] parentSizeProperty The parent's size
73 Vector3 operator()( const Vector3& current,
74 const PropertyInput& parentSizeProperty )
76 Vector3 size = parentSizeProperty.GetVector3();
78 size.width += mOuterBorder.x + mOuterBorder.y;
79 size.height += mOuterBorder.z + mOuterBorder.w;
84 const Vector4 mOuterBorder; ///< The size of the outer-border (Set to 0.0, 0.0f, 0.0f, 0.0f if doesn't exist).
87 struct ButtonAreaSizeConstraint
90 * Constraint that sets size to parent's size plus a border.
92 * @param[in] outerBorder The border to extend beyond parent's Size.
94 ButtonAreaSizeConstraint( Vector4 outerBorder )
95 : mOuterBorder( outerBorder )
100 * (render thread code)
101 * @param[in] current The current size.
102 * @param[in] parentSizeProperty The parent's size
104 Vector3 operator()( const Vector3& current,
105 const PropertyInput& parentSizeProperty )
107 Vector3 size = parentSizeProperty.GetVector3();
109 size.width += mOuterBorder.x + mOuterBorder.y;
110 size.width -= (POPUP_OUT_MARGIN_WIDTH + POPUP_OUT_MARGIN_WIDTH);
111 size.height = POPUP_BUTTON_BG_HEIGHT;
116 const Vector4 mOuterBorder; ///< The size of the outer-border (Set to 0.0, 0.0f, 0.0f, 0.0f if doesn't exist).
119 } // unnamed namespace
135 return Toolkit::Popup::New();
138 TypeRegistration typeRegistration( typeid(Toolkit::Popup), typeid(Toolkit::Control), Create );
140 SignalConnectorType signalConnector1( typeRegistration, Toolkit::Popup::SIGNAL_TOUCHED_OUTSIDE, &Popup::DoConnectSignal );
141 SignalConnectorType signalConnector2( typeRegistration, Toolkit::Popup::SIGNAL_HIDDEN, &Popup::DoConnectSignal );
147 ///////////////////////////////////////////////////////////////////////////////////////////////////
149 ///////////////////////////////////////////////////////////////////////////////////////////////////
151 Dali::Toolkit::Popup Popup::New()
153 PopupStylePtr style = PopupStyleDefault::New();
155 // Create the implementation
156 PopupPtr popup(new Popup(*style));
158 // Pass ownership to CustomActor via derived handle
159 Dali::Toolkit::Popup handle(*popup);
161 // Second-phase init of the implementation
162 // This can only be done after the CustomActor connection has been made...
168 Popup::Popup(PopupStyle& style)
171 mState(Toolkit::Popup::POPUP_NONE), // Initially, the popup state should not be set, it's set in OnInitialize
172 mAlterAddedChild(false),
173 mPopupStyle(PopupStylePtr(&style))
175 SetKeyboardNavigationSupport( true );
178 void Popup::OnInitialize()
181 self.SetSensitive(false);
184 mLayer = Layer::New();
185 mLayer.SetParentOrigin(ParentOrigin::CENTER);
186 mLayer.SetAnchorPoint(AnchorPoint::CENTER);
188 mLayer.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) );
191 mPopupBg = Actor::New();
192 mPopupBg.SetParentOrigin(ParentOrigin::CENTER);
193 mPopupBg.SetAnchorPoint(AnchorPoint::CENTER);
194 mPopupBg.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) );
195 mLayer.Add(mPopupBg);
197 // Any content after this point which is added to Self() will be reparented to
199 mAlterAddedChild = true;
201 // Add Backing (Dim effect)
204 // Add Dialog ( background image, title, content container, button container and tail )
208 ShowTail(ParentOrigin::BOTTOM_CENTER);
210 // Hide content by default.
211 SetState( Toolkit::Popup::POPUP_HIDE, 0.0f );
213 mPropertyTitle = self.RegisterProperty( Dali::Toolkit::Popup::PROPERTY_TITLE, "", Property::READ_WRITE );
214 mPropertyState = self.RegisterProperty( Dali::Toolkit::Popup::PROPERTY_STATE, "POPUP_HIDE", Property::READ_WRITE );
216 // Make self as keyboard focusable and focus group
217 self.SetKeyboardFocusable(true);
218 SetAsKeyboardFocusGroup(true);
221 void Popup::OnPropertySet( Property::Index index, Property::Value propertyValue )
223 if( index == mPropertyTitle )
225 SetTitle(propertyValue.Get<std::string>());
227 else if ( index == mPropertyState )
229 std::string value( propertyValue.Get<std::string>() );
230 if(value == "POPUP_SHOW")
232 SetState( Toolkit::Popup::POPUP_SHOW, 0.0f );
234 else if( value == "POPUP_HIDE")
236 SetState( Toolkit::Popup::POPUP_HIDE, 0.0f );
245 size_t Popup::GetButtonCount() const
247 return mButtons.size();
250 void Popup::SetBackgroundImage( Actor image )
252 // Removes any previous background.
253 if( mBackgroundImage && mPopupBg )
255 mPopupBg.Remove( mBackgroundImage );
258 // Adds new background to the dialog.
259 mBackgroundImage = image;
261 // OnDialogTouched only consume the event. It prevents the touch event to be caught by the backing.
262 mBackgroundImage.TouchedSignal().Connect( this, &Popup::OnDialogTouched );
264 mPopupBg.Add( mBackgroundImage );
267 void Popup::SetButtonAreaImage( Actor image )
269 // Removes any previous area image.
270 if( mButtonAreaImage && mPopupBg )
272 mPopupBg.Remove( mButtonAreaImage );
275 // Adds new area image to the dialog.
276 mButtonAreaImage = image;
278 // OnDialogTouched only consume the event. It prevents the touch event to be caught by the backing.
279 mButtonAreaImage.TouchedSignal().Connect( this, &Popup::OnDialogTouched );
281 mPopupBg.Add( mButtonAreaImage );
284 void Popup::SetTitle( const std::string& text )
286 Toolkit::TextView titleActor = Toolkit::TextView::New();
287 titleActor.SetText( text );
288 titleActor.SetColor( Color::BLACK );
289 titleActor.SetMultilinePolicy( Toolkit::TextView::SplitByWord );
290 titleActor.SetWidthExceedPolicy( Toolkit::TextView::Split );
291 titleActor.SetLineJustification( Toolkit::TextView::Center );
293 SetTitle( titleActor );
296 void Popup::SetTitle( Toolkit::TextView titleActor )
298 // Replaces the current title actor.
299 if( mTitle && mPopupBg )
301 mPopupBg.Remove( mTitle );
305 mPopupBg.Add( mTitle );
310 Toolkit::TextView Popup::GetTitle() const
315 void Popup::AddButton( Toolkit::Button button )
317 mButtons.push_back( button );
318 mBottomBg.Add( button );
323 void Popup::SetState( Toolkit::Popup::PopupState state )
325 SetState( state, POPUP_ANIMATION_DURATION );
328 void Popup::SetState( Toolkit::Popup::PopupState state, float duration )
330 // default animation behaviour.
331 HandleStateChange(state, duration);
334 Toolkit::Popup::PopupState Popup::GetState() const
339 void Popup::ShowTail(const Vector3& position)
341 // Replaces the tail actor.
342 if(mTailImage && mTailImage.GetParent())
344 mTailImage.GetParent().Remove( mTailImage );
348 std::string image = "";
350 // depending on position of tail around ParentOrigin, a different tail image is used...
351 if(position.y < Math::MACHINE_EPSILON_1)
353 image = mPopupStyle->tailUpImage;
355 else if(position.y > 1.0f - Math::MACHINE_EPSILON_1)
357 image = mPopupStyle->tailDownImage;
359 else if(position.x < Math::MACHINE_EPSILON_1)
361 image = mPopupStyle->tailLeftImage;
363 else if(position.x > 1.0f - Math::MACHINE_EPSILON_1)
365 image = mPopupStyle->tailRightImage;
370 Image tail = Image::New( image );
371 mTailImage = ImageActor::New(tail);
372 const Vector3 anchorPoint = AnchorPoint::FRONT_BOTTOM_RIGHT - position;
374 mTailImage.SetParentOrigin(position);
375 mTailImage.SetAnchorPoint(anchorPoint);
377 mBottomBg.Add(mTailImage);
381 void Popup::HideTail()
383 ShowTail(ParentOrigin::CENTER);
386 void Popup::SetStyle(PopupStyle& style)
388 mPopupStyle = PopupStylePtr(&style);
392 PopupStylePtr Popup::GetStyle() const
397 void Popup::SetDefaultBackgroundImage()
399 Image bg = Image::New( mPopupStyle->backgroundImage );
400 ImageActor bgImage = ImageActor::New( bg );
401 bgImage.SetStyle( ImageActor::STYLE_NINE_PATCH );
402 bgImage.SetNinePatchBorder( mPopupStyle->backgroundScale9Border );
404 Image buttonBg = Image::New( mPopupStyle->buttonAreaImage );
405 ImageActor buttonBgImage = ImageActor::New( buttonBg );
406 buttonBgImage.SetStyle( ImageActor::STYLE_NINE_PATCH );
407 buttonBgImage.SetNinePatchBorder( mPopupStyle->buttonArea9PatchBorder );
409 SetBackgroundImage( bgImage );
410 SetButtonAreaImage( buttonBgImage );
413 void Popup::CreateBacking()
415 mBacking = Dali::Toolkit::CreateSolidColorActor( mPopupStyle->backingColor );
417 mBacking.SetPositionInheritanceMode(DONT_INHERIT_POSITION);
418 mBacking.SetSensitive(true);
420 mLayer.Add(mBacking);
421 mBacking.SetOpacity(0.0f);
422 mBacking.SetPosition(0.0f, 0.0f, BACKING_DEPTH);
423 mBacking.TouchedSignal().Connect( this, &Popup::OnBackingTouched );
424 mBacking.MouseWheelEventSignal().Connect(this, &Popup::OnBackingMouseWheelEvent);
427 void Popup::CreateDialog()
429 // Adds default background image.
430 SetDefaultBackgroundImage();
432 // Adds bottom background
433 mBottomBg = Actor::New();
434 mPopupBg.Add( mBottomBg );
437 void Popup::HandleStateChange( Toolkit::Popup::PopupState state, float duration )
439 const Vector2& stageSize( Stage::GetCurrent().GetSize() );
442 float targetBackingAlpha;
443 Vector3 targetBackingSize;
452 case Toolkit::Popup::POPUP_HIDE:
454 targetSize = Vector3(0.0f, 0.0f, 1.0f);
455 targetBackingAlpha = 0.0f;
456 targetBackingSize = Vector3(0.0f, 0.0f, 1.0f);
458 ClearKeyInputFocus();
460 // Retore the keyboard focus when popup is hidden
461 if(mPreviousFocusedActor && mPreviousFocusedActor.IsKeyboardFocusable() )
463 Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get();
464 if( keyboardFocusManager )
466 keyboardFocusManager.SetCurrentFocusActor(mPreviousFocusedActor);
473 case Toolkit::Popup::POPUP_SHOW:
476 targetSize = Vector3(1.0f, 1.0f, 1.0f);
477 targetBackingAlpha = 1.0f;
478 float length = (stageSize.width > stageSize.height) ? stageSize.width : stageSize.height;
479 targetBackingSize = Vector3( length, length, 1.0f );
482 // Add contents to stage for showing.
483 if( !mLayer.GetParent() )
485 mAlterAddedChild = false;
487 mAlterAddedChild = true;
489 Self().SetSensitive(true);
492 // Handle the keyboard focus when popup is shown
493 Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get();
494 if( keyboardFocusManager )
496 mPreviousFocusedActor = keyboardFocusManager.GetCurrentFocusActor();
498 if( mContent && mContent.IsKeyboardFocusable() )
500 // If content is focusable, move the focus to content
501 keyboardFocusManager.SetCurrentFocusActor(mContent);
503 else if( !mButtons.empty() )
505 // Otherwise, movethe focus to the first button
506 keyboardFocusManager.SetCurrentFocusActor(mButtons[0]);
510 DALI_LOG_WARNING("There is no focusable in popup\n");
517 mBacking.SetSize( targetBackingSize );
519 if(duration > Math::MACHINE_EPSILON_1)
527 mAnimation = Animation::New(duration);
531 mAnimation.AnimateTo( Property(mBacking, Actor::COLOR_ALPHA), targetBackingAlpha, AlphaFunctions::EaseInOut, TimePeriod(0.0f, duration * 0.5f) );
532 mAnimation.AnimateTo( Property(mPopupBg, Actor::SCALE), targetSize, AlphaFunctions::EaseInOut, TimePeriod(duration * 0.5f, duration * 0.5f) );
536 mAnimation.AnimateTo( Property(mBacking, Actor::COLOR_ALPHA), targetBackingAlpha, AlphaFunctions::EaseInOut, TimePeriod(0.0f, duration * 0.5f) );
537 mAnimation.AnimateTo( Property(mPopupBg, Actor::SCALE), targetSize, AlphaFunctions::EaseInOut, TimePeriod(0.0f, duration * 0.5f) );
540 mAnimation.FinishedSignal().Connect(this, &Popup::OnStateAnimationFinished);
544 mBacking.SetOpacity( targetBackingAlpha );
545 mPopupBg.SetScale( targetSize );
547 HandleStateChangeComplete();
551 void Popup::HandleStateChangeComplete()
553 // Remove contents from stage if completely hidden.
554 if( (mState == Toolkit::Popup::POPUP_HIDE) && (mLayer.GetParent()) )
556 Self().Remove(mLayer);
557 Self().SetSensitive( false );
559 // Guard against destruction during signal emission
560 Toolkit::Popup handle( GetOwner() );
561 mHiddenSignalV2.Emit();
565 Toolkit::Popup::TouchedOutsideSignalV2& Popup::OutsideTouchedSignal()
567 return mTouchedOutsideSignalV2;
570 Toolkit::Popup::HiddenSignalV2& Popup::HiddenSignal()
572 return mHiddenSignalV2;
575 bool Popup::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
577 Dali::BaseHandle handle( object );
579 bool connected( true );
580 Toolkit::Popup popup = Toolkit::Popup::DownCast(handle);
582 if( Dali::Toolkit::Popup::SIGNAL_TOUCHED_OUTSIDE == signalName )
584 popup.OutsideTouchedSignal().Connect( tracker, functor );
586 else if( Dali::Toolkit::Popup::SIGNAL_HIDDEN == signalName )
588 popup.HiddenSignal().Connect( tracker, functor );
592 // signalName does not match any signal
599 void Popup::OnStateAnimationFinished( Animation& source )
601 HandleStateChangeComplete();
604 bool Popup::OnBackingTouched(Actor actor, const TouchEvent& event)
606 if(event.GetPointCount()>0)
608 const TouchPoint& point = event.GetPoint(0);
610 if(point.state == TouchPoint::Down)
612 // Guard against destruction during signal emission
613 Toolkit::Popup handle( GetOwner() );
615 mTouchedOutsideSignalV2.Emit();
622 bool Popup::OnBackingMouseWheelEvent(Actor actor, const MouseWheelEvent& event)
624 // consume mouse wheel event in dimmed backing actor
628 bool Popup::OnDialogTouched(Actor actor, const TouchEvent& event)
630 // consume event (stops backing actor receiving touch events)
634 void Popup::OnControlChildAdd( Actor& child )
636 // reparent any children added by user to the body layer.
637 if( mAlterAddedChild )
639 // Removes previously added content.
642 mPopupBg.Remove( mContent );
645 // Reparent new content.
646 Self().Remove( child );
648 // keep a handle to the new content.
651 mPopupBg.Add( mContent );
655 void Popup::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
657 // Set the popup size
659 popupSize.width = size.width - 2.f * ( POPUP_OUT_MARGIN_WIDTH + mPopupStyle->margin );
660 popupSize.height = size.height - 2.f * ( POPUP_OUT_MARGIN_WIDTH + mPopupStyle->margin );
662 // Update sizes of all popup's components.
664 // Relayout background image.
665 // Adjust background position and size relative to parent to cater to outer Border.
666 // Some backgrounds are intended to over-spill. That is some content
667 // should appear outside the Dialog on all sides i.e. Shadows, glow effects.
668 const Vector4 outerBorder = mPopupStyle->backgroundOuterBorder;
670 if( mBackgroundImage )
672 Constraint constraint = Constraint::New<Vector3>( Actor::SIZE,
673 ParentSource( Actor::SIZE ),
674 BackgroundSizeConstraint(outerBorder) );
676 mBackgroundImage.RemoveConstraints();
677 mBackgroundImage.ApplyConstraint( constraint );
679 mBackgroundImage.SetAnchorPoint( AnchorPoint::TOP_LEFT );
680 mBackgroundImage.SetParentOrigin( ParentOrigin::TOP_LEFT );
681 mBackgroundImage.SetPosition( -outerBorder.x, -outerBorder.y, 0.0f );
684 if( mPopupBg && mButtonAreaImage )
686 // If there are no buttons, button background is also removed.
687 if ( mButtons.size() == 0 )
689 mPopupBg.Remove( mButtonAreaImage );
693 Constraint constraint = Constraint::New<Vector3>( Actor::SIZE,
694 ParentSource( Actor::SIZE ),
695 ButtonAreaSizeConstraint(outerBorder) );
697 mButtonAreaImage.RemoveConstraints();
698 mButtonAreaImage.ApplyConstraint( constraint );
700 mButtonAreaImage.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
701 mButtonAreaImage.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
702 mButtonAreaImage.SetY( -outerBorder.z - POPUP_OUT_MARGIN_HEIGHT );
704 mPopupBg.Add( mButtonAreaImage );
709 Vector3 positionOffset( 0.0f, mPopupStyle->margin + POPUP_OUT_MARGIN_WIDTH, CONTENT_DEPTH );
713 titleSize.width = popupSize.width;
714 titleSize.height = mTitle.GetHeightForWidth( titleSize.width );
716 // As the default size policy for text-view is Fixed & Fixed, a size needs to be set.
717 // Otherwise size-negotiation algorithm uses the GetNaturalSize() with doesn't take
718 // into account the multiline and exceed policies, giving as result a wrong size.
719 mTitle.SetSize( titleSize );
720 Relayout( mTitle, titleSize, container );
722 mTitle.SetAnchorPoint( AnchorPoint::TOP_CENTER );
723 mTitle.SetParentOrigin( ParentOrigin::TOP_CENTER );
724 mTitle.SetPosition( positionOffset );
726 positionOffset.y += titleSize.height + mPopupStyle->margin;
733 contentSize.width = popupSize.width;
735 Toolkit::Control control = Toolkit::Control::DownCast( mContent );
738 contentSize.height = control.GetHeightForWidth( contentSize.width );
742 contentSize.height = RelayoutHelper::GetHeightForWidth( mContent, contentSize.width );
745 mContent.SetSize( contentSize );
746 Relayout( mContent, contentSize, container );
748 mContent.SetParentOrigin(ParentOrigin::TOP_CENTER);
749 mContent.SetAnchorPoint(AnchorPoint::TOP_CENTER);
751 mContent.SetPosition( positionOffset );
753 positionOffset.y += contentSize.height + mPopupStyle->margin;
756 // Relayout Button Area
759 mBottomBg.SetSize( popupSize.width, mPopupStyle->bottomSize.height );
761 mBottomBg.SetParentOrigin(ParentOrigin::TOP_CENTER);
762 mBottomBg.SetAnchorPoint(AnchorPoint::TOP_CENTER);
764 mBottomBg.SetPosition( positionOffset );
767 // Relayout All buttons
768 if ( !mButtons.empty() )
770 // All buttons should be the same size and fill the button area. The button spacing needs to be accounted for as well.
771 Vector2 buttonSize( ( ( popupSize.width - mPopupStyle->buttonSpacing * ( mButtons.size() - 1 ) ) / mButtons.size() ),
772 mPopupStyle->bottomSize.height - mPopupStyle->margin );
774 Vector3 buttonPosition;
776 for ( ActorIter iter = mButtons.begin(), endIter = mButtons.end();
778 ++iter, buttonPosition.x += mPopupStyle->buttonSpacing + buttonSize.width )
780 iter->SetPosition( buttonPosition );
782 // If there is only one button, it needs to be laid out on center.
783 if ( mButtons.size() == 1 )
785 iter->SetAnchorPoint( AnchorPoint::CENTER );
786 iter->SetParentOrigin( ParentOrigin::CENTER );
790 iter->SetAnchorPoint( AnchorPoint::CENTER_LEFT );
791 iter->SetParentOrigin( ParentOrigin::CENTER_LEFT );
794 Relayout( *iter, buttonSize, container );
798 if( mShowing && mBacking )
800 Vector2 stageSize = Stage::GetCurrent().GetSize();
801 float length = (stageSize.width > stageSize.height) ? stageSize.width : stageSize.height;
802 Vector3 targetBackingSize = Vector3( length, length, 1.0f );
804 mBacking.SetSize( targetBackingSize );
808 bool Popup::OnKeyEvent(const KeyEvent& event)
810 bool consumed = false;
812 if(event.state == KeyEvent::Down)
814 if (event.keyCode == Dali::DALI_KEY_ESCAPE || event.keyCode == Dali::DALI_KEY_BACK)
816 SetState(Toolkit::Popup::POPUP_HIDE);
824 Vector3 Popup::GetNaturalSize()
830 naturalSize += mTitle.GetImplementation().GetNaturalSize();
831 naturalSize.height += mPopupStyle->margin;
838 Toolkit::Control control = Toolkit::Control::DownCast( mContent );
841 contentSize = control.GetImplementation().GetNaturalSize();
845 contentSize = RelayoutHelper::GetNaturalSize( mContent );
848 naturalSize.width = std::max( naturalSize.width, contentSize.width );
849 naturalSize.height += contentSize.height + mPopupStyle->margin;
852 if( !mButtons.empty() )
854 naturalSize.height += mPopupStyle->bottomSize.height;
858 float margin( 2.0f * ( POPUP_OUT_MARGIN_WIDTH + mPopupStyle->margin ) );
859 naturalSize.width += margin;
860 naturalSize.height += margin;
865 float Popup::GetHeightForWidth( float width )
867 float height( 0.0f );
868 float popupWidth( width - 2.f * ( POPUP_OUT_MARGIN_WIDTH + mPopupStyle->margin ) );
872 height += mTitle.GetImplementation().GetHeightForWidth( popupWidth );
873 height += mPopupStyle->margin;
880 Toolkit::Control control = Toolkit::Control::DownCast( mContent );
883 contentHeight = control.GetImplementation().GetHeightForWidth( popupWidth );
887 contentHeight = RelayoutHelper::GetHeightForWidth( mContent, popupWidth );
890 height += contentHeight + mPopupStyle->margin;
893 if( !mButtons.empty() )
895 height += mPopupStyle->bottomSize.height;
899 float margin( 2.0f * ( POPUP_OUT_MARGIN_WIDTH + mPopupStyle->margin ) );
905 float Popup::GetWidthForHeight( float height )
907 return GetNaturalSize().width;
910 Actor Popup::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Control::KeyboardFocusNavigationDirection direction, bool loopEnabled)
912 Actor nextFocusableActor( currentFocusedActor );
914 // TODO: Needs to be optimised
916 if ( !currentFocusedActor || ( currentFocusedActor && KeyboardFocusManager::Get().GetFocusGroup(currentFocusedActor) != Self() ) )
918 // The current focused actor is not within popup
919 if( mContent && mContent.IsKeyboardFocusable() )
921 // If content is focusable, move the focus to content
922 nextFocusableActor = mContent;
924 else if( !mButtons.empty() )
926 // Otherwise, movethe focus to the first button
927 nextFocusableActor = mButtons[0];
932 // Rebuild the focus chain because button or content can be added or removed dynamically
933 ActorContainer focusableActors;
934 if( mContent && mContent.IsKeyboardFocusable() )
936 focusableActors.push_back(mContent);
939 for(unsigned int i = 0; i < mButtons.size(); i++)
941 if( mButtons[i] && mButtons[i].IsKeyboardFocusable() )
943 focusableActors.push_back(mButtons[i]);
947 for ( ActorContainer::iterator iter = focusableActors.begin(), end = focusableActors.end(); iter != end; ++iter )
949 if ( currentFocusedActor == *iter )
955 if ( iter == focusableActors.begin() )
957 nextFocusableActor = *( focusableActors.end() - 1 );
961 nextFocusableActor = *( iter - 1 );
967 if ( iter == focusableActors.end() - 1 )
969 nextFocusableActor = *( focusableActors.begin() );
973 nextFocusableActor = *( iter + 1 );
980 if ( *iter == mContent )
982 nextFocusableActor = *( focusableActors.end() - 1 );
986 if ( mContent && mContent.IsKeyboardFocusable() )
988 nextFocusableActor = mContent;
992 if ( iter == focusableActors.begin() )
994 nextFocusableActor = *( focusableActors.end() - 1 );
998 nextFocusableActor = *( iter - 1 );
1007 if ( mContent && mContent.IsKeyboardFocusable() )
1009 nextFocusableActor = mContent;
1013 if ( iter == focusableActors.end() - 1 )
1015 nextFocusableActor = *( focusableActors.begin() );
1019 nextFocusableActor = *( iter + 1 );
1023 if ( *iter == mContent && !mButtons.empty() )
1025 nextFocusableActor = mButtons[0];
1031 if(!nextFocusableActor)
1033 DALI_LOG_WARNING("Can not decide next focusable actor\n");
1041 return nextFocusableActor;
1044 } // namespace Internal
1046 } // namespace Toolkit