-//
-// Copyright (c) 2014 Samsung Electronics Co., Ltd.
-//
-// Licensed under the Flora License, Version 1.0 (the License);
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://floralicense.org/license/
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an AS IS BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+// CLASS HEADER
#include <dali-toolkit/internal/controls/popup/popup-impl.h>
+// EXTERNAL INCLUDES
+#include <dali/public-api/adaptor-framework/key.h>
+#include <dali/public-api/adaptor-framework/physical-keyboard.h>
+#include <dali/public-api/animation/constraints.h>
+#include <dali/public-api/common/stage.h>
+#include <dali/public-api/events/key-event.h>
+#include <dali/public-api/events/touch-event.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/images/resource-image.h>
+
+// INTERNAL INCLUDES
#include <dali-toolkit/public-api/controls/buttons/button.h>
#include <dali-toolkit/public-api/controls/default-controls/solid-color-actor.h>
#include <dali-toolkit/public-api/controls/control-impl.h>
-
#include <dali-toolkit/internal/controls/relayout-helper.h>
#include <dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h>
-
#include <dali-toolkit/public-api/focus-manager/focus-manager.h>
-#include <dali/integration-api/debug.h>
using namespace Dali;
-using namespace std;
namespace
{
const Vector3 DEFAULT_DIALOG_SIZE = Vector3(POPUP_TITLE_WIDTH/POPUP_WIDTH, 0.5f, 0.0f);
const Vector3 DEFAULT_BOTTOM_SIZE = Vector3(1.0f, 0.2f, 0.0f);
-// Constraints ///////////////////////////////////////////////////////////////////////////
+// Signals
+
+const char* const SIGNAL_TOUCHED_OUTSIDE = "touched-outside";
+const char* const SIGNAL_HIDDEN = "hidden";
+
+// Properties
+
+const char* const PROPERTY_TITLE = "title";
+const char* const PROPERTY_STATE = "state";
/**
- * BackgroundSizeConstraint
- *
* The background size should be at least as big as the Dialog.
* In some cases a background may have graphics which are visible
* outside of the Dialog, e.g. A Shadow. For this we need to alter
* the size of Background.
+ *
+ * @param[in] outerBorder The border to extend beyond parent's Size.
+ * @param[in] parentSize The parent's size
*/
-struct BackgroundSizeConstraint
+Vector3 BackgroundSize(const Vector4& outerBoarder, const Vector3& parentSize)
{
- /**
- * Constraint that sets size to parent's size plus a border.
- *
- * @param[in] outerBorder The border to extend beyond parent's Size.
- */
- BackgroundSizeConstraint( Vector4 outerBorder )
- : mOuterBorder( outerBorder )
- {
- }
+ Vector3 size( parentSize );
+ size.width += outerBoarder.x + outerBoarder.y;
+ size.height += outerBoarder.z + outerBoarder.w;
- /**
- * (render thread code)
- * @param[in] current The current size.
- * @param[in] parentSizeProperty The parent's size
- */
- Vector3 operator()( const Vector3& current,
- const PropertyInput& parentSizeProperty )
- {
- Vector3 size = parentSizeProperty.GetVector3();
-
- size.width += mOuterBorder.x + mOuterBorder.y;
- size.height += mOuterBorder.z + mOuterBorder.w;
-
- return size;
- }
-
- const Vector4 mOuterBorder; ///< The size of the outer-border (Set to 0.0, 0.0f, 0.0f, 0.0f if doesn't exist).
-};
+ return size;
+}
-struct ButtonAreaSizeConstraint
-{
/**
- * Constraint that sets size to parent's size plus a border.
+ * sets button area size to parent's size plus a border.
*
* @param[in] outerBorder The border to extend beyond parent's Size.
+ * @param[in] parentSize The parent's size
*/
- ButtonAreaSizeConstraint( Vector4 outerBorder )
- : mOuterBorder( outerBorder )
- {
- }
-
- /**
- * (render thread code)
- * @param[in] current The current size.
- * @param[in] parentSizeProperty The parent's size
- */
- Vector3 operator()( const Vector3& current,
- const PropertyInput& parentSizeProperty )
- {
- Vector3 size = parentSizeProperty.GetVector3();
-
- size.width += mOuterBorder.x + mOuterBorder.y;
- size.width -= (POPUP_OUT_MARGIN_WIDTH + POPUP_OUT_MARGIN_WIDTH);
- size.height = POPUP_BUTTON_BG_HEIGHT;
-
- return size;
- }
+Vector3 ButtonAreaSize( const Vector4& outBoarder, const Vector3& parentSize )
+{
+ Vector3 size( parentSize );
+ size.width += outBoarder.x + outBoarder.y;
+ size.width -= (POPUP_OUT_MARGIN_WIDTH + POPUP_OUT_MARGIN_WIDTH);
+ size.height = POPUP_BUTTON_BG_HEIGHT;
- const Vector4 mOuterBorder; ///< The size of the outer-border (Set to 0.0, 0.0f, 0.0f, 0.0f if doesn't exist).
-};
+ return size;
+}
} // unnamed namespace
return Toolkit::Popup::New();
}
-TypeRegistration typeRegistration( typeid(Toolkit::Popup), typeid(Toolkit::Control), Create );
+TypeRegistration typeRegistration( typeid( Toolkit::Popup ), typeid( Toolkit::Control ), Create );
-SignalConnectorType signalConnector1( typeRegistration, Toolkit::Popup::SIGNAL_TOUCHED_OUTSIDE, &Popup::DoConnectSignal );
-SignalConnectorType signalConnector2( typeRegistration, Toolkit::Popup::SIGNAL_HIDDEN, &Popup::DoConnectSignal );
+SignalConnectorType signalConnector1( typeRegistration, SIGNAL_TOUCHED_OUTSIDE, &Popup::DoConnectSignal );
+SignalConnectorType signalConnector2( typeRegistration, SIGNAL_HIDDEN, &Popup::DoConnectSignal );
}
}
Popup::Popup(PopupStyle& style)
-: ControlImpl(true),
+: Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ),
mShowing(false),
mState(Toolkit::Popup::POPUP_NONE), // Initially, the popup state should not be set, it's set in OnInitialize
mAlterAddedChild(false),
- mPopupStyle(PopupStylePtr(&style))
+ mPopupStyle(PopupStylePtr(&style)),
+ mPropertyTitle(Property::INVALID_INDEX),
+ mPropertyState(Property::INVALID_INDEX)
{
SetKeyboardNavigationSupport( true );
}
mLayer.SetParentOrigin(ParentOrigin::CENTER);
mLayer.SetAnchorPoint(AnchorPoint::CENTER);
mLayer.RaiseToTop();
- mLayer.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) );
self.Add(mLayer);
mPopupBg = Actor::New();
mPopupBg.SetParentOrigin(ParentOrigin::CENTER);
mPopupBg.SetAnchorPoint(AnchorPoint::CENTER);
- mPopupBg.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) );
mLayer.Add(mPopupBg);
// Any content after this point which is added to Self() will be reparented to
// Hide content by default.
SetState( Toolkit::Popup::POPUP_HIDE, 0.0f );
- mPropertyTitle = self.RegisterProperty( Dali::Toolkit::Popup::PROPERTY_TITLE, "", Property::READ_WRITE );
- mPropertyState = self.RegisterProperty( Dali::Toolkit::Popup::PROPERTY_STATE, "POPUP_HIDE", Property::READ_WRITE );
+ mPropertyTitle = self.RegisterProperty( PROPERTY_TITLE, "", Property::READ_WRITE );
+ mPropertyState = self.RegisterProperty( PROPERTY_STATE, "POPUP_HIDE", Property::READ_WRITE );
// Make self as keyboard focusable and focus group
self.SetKeyboardFocusable(true);
if(image != "")
{
- Image tail = Image::New( image );
+ Image tail = ResourceImage::New( image );
mTailImage = ImageActor::New(tail);
const Vector3 anchorPoint = AnchorPoint::FRONT_BOTTOM_RIGHT - position;
void Popup::SetDefaultBackgroundImage()
{
- Image bg = Image::New( mPopupStyle->backgroundImage );
+ Image bg = ResourceImage::New( mPopupStyle->backgroundImage );
ImageActor bgImage = ImageActor::New( bg );
bgImage.SetStyle( ImageActor::STYLE_NINE_PATCH );
bgImage.SetNinePatchBorder( mPopupStyle->backgroundScale9Border );
- Image buttonBg = Image::New( mPopupStyle->buttonAreaImage );
+ Image buttonBg = ResourceImage::New( mPopupStyle->buttonAreaImage );
ImageActor buttonBgImage = ImageActor::New( buttonBg );
buttonBgImage.SetStyle( ImageActor::STYLE_NINE_PATCH );
buttonBgImage.SetNinePatchBorder( mPopupStyle->buttonArea9PatchBorder );
// Guard against destruction during signal emission
Toolkit::Popup handle( GetOwner() );
- mHiddenSignalV2.Emit();
+ mHiddenSignal.Emit();
}
}
-Toolkit::Popup::TouchedOutsideSignalV2& Popup::OutsideTouchedSignal()
+Toolkit::Popup::TouchedOutsideSignalType& Popup::OutsideTouchedSignal()
{
- return mTouchedOutsideSignalV2;
+ return mTouchedOutsideSignal;
}
-Toolkit::Popup::HiddenSignalV2& Popup::HiddenSignal()
+Toolkit::Popup::HiddenSignalType& Popup::HiddenSignal()
{
- return mHiddenSignalV2;
+ return mHiddenSignal;
}
bool Popup::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
Dali::BaseHandle handle( object );
bool connected( true );
- Toolkit::Popup popup = Toolkit::Popup::DownCast(handle);
+ Toolkit::Popup popup = Toolkit::Popup::DownCast( handle );
- if( Dali::Toolkit::Popup::SIGNAL_TOUCHED_OUTSIDE == signalName )
+ if( 0 == strcmp( signalName.c_str(), SIGNAL_TOUCHED_OUTSIDE ) )
{
popup.OutsideTouchedSignal().Connect( tracker, functor );
}
- else if( Dali::Toolkit::Popup::SIGNAL_HIDDEN == signalName )
+ else if( 0 == strcmp( signalName.c_str(), SIGNAL_HIDDEN ) )
{
popup.HiddenSignal().Connect( tracker, functor );
}
// Guard against destruction during signal emission
Toolkit::Popup handle( GetOwner() );
- mTouchedOutsideSignalV2.Emit();
+ mTouchedOutsideSignal.Emit();
}
}
}
}
-void Popup::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
+void Popup::OnControlSizeSet( const Vector3& targetSize )
+{
+ mLayer.SetSize( targetSize );
+ mPopupBg.SetSize( targetSize );
+
+ const Vector4 outerBorder = mPopupStyle->backgroundOuterBorder;
+ if( mBackgroundImage )
+ {
+ mBackgroundImage.SetSize( BackgroundSize( outerBorder,targetSize ) );
+ }
+ if( mButtonAreaImage )
+ {
+ mButtonAreaImage.SetSize( ButtonAreaSize( outerBorder, targetSize ) );
+ }
+
+}
+
+void Popup::OnRelayout( const Vector2& size, ActorSizeContainer& container )
{
// Set the popup size
Vector2 popupSize;
if( mBackgroundImage )
{
- Constraint constraint = Constraint::New<Vector3>( Actor::SIZE,
- ParentSource( Actor::SIZE ),
- BackgroundSizeConstraint(outerBorder) );
-
- mBackgroundImage.RemoveConstraints();
- mBackgroundImage.ApplyConstraint( constraint );
-
+ mBackgroundImage.SetSize(BackgroundSize(outerBorder, Vector3(size)));
mBackgroundImage.SetAnchorPoint( AnchorPoint::TOP_LEFT );
mBackgroundImage.SetParentOrigin( ParentOrigin::TOP_LEFT );
mBackgroundImage.SetPosition( -outerBorder.x, -outerBorder.y, 0.0f );
}
else
{
- Constraint constraint = Constraint::New<Vector3>( Actor::SIZE,
- ParentSource( Actor::SIZE ),
- ButtonAreaSizeConstraint(outerBorder) );
-
- mButtonAreaImage.RemoveConstraints();
- mButtonAreaImage.ApplyConstraint( constraint );
-
+ mButtonAreaImage.SetSize( ButtonAreaSize(outerBorder, Vector3(size)) );
mButtonAreaImage.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
mButtonAreaImage.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
mButtonAreaImage.SetY( -outerBorder.z - POPUP_OUT_MARGIN_HEIGHT );
// Relayout content
if( mContent )
{
- Vector2 contentSize;
- contentSize.width = popupSize.width;
-
- Toolkit::Control control = Toolkit::Control::DownCast( mContent );
- if( control )
- {
- contentSize.height = control.GetHeightForWidth( contentSize.width );
- }
- else
+ // If the content width is greater than popup width then scale it down/wrap text as needed
+ Vector2 contentSize( RelayoutHelper::GetNaturalSize( mContent ) );
+ if( contentSize.width > popupSize.width )
{
+ contentSize.width = popupSize.width;
contentSize.height = RelayoutHelper::GetHeightForWidth( mContent, contentSize.width );
}
Vector3 Popup::GetNaturalSize()
{
- Vector3 naturalSize;
+ float margin = 2.0f * ( POPUP_OUT_MARGIN_WIDTH + mPopupStyle->margin );
+ const float maxWidth = Stage::GetCurrent().GetSize().width - margin;
- if ( mTitle )
- {
- naturalSize += mTitle.GetImplementation().GetNaturalSize();
- naturalSize.height += mPopupStyle->margin;
- }
+ Vector3 naturalSize( 0.0f, 0.0f, 0.0f );
- if( mContent )
+ if ( mTitle )
{
- Vector3 contentSize;
-
- Toolkit::Control control = Toolkit::Control::DownCast( mContent );
- if( control )
+ Vector3 titleNaturalSize = mTitle.GetImplementation().GetNaturalSize();
+ // Buffer to avoid errors. The width of the popup could potentially be the width of the title text.
+ // It was observed in this case that text wrapping was then inconsistent when seen on device
+ const float titleBuffer = 0.5f;
+ titleNaturalSize.width += titleBuffer;
+
+ // As TextView GetNaturalSize does not take wrapping into account, limit the width
+ // to that of the stage
+ if( titleNaturalSize.width >= maxWidth)
{
- contentSize = control.GetImplementation().GetNaturalSize();
+ naturalSize.width = maxWidth;
+ naturalSize.height = mTitle.GetImplementation().GetHeightForWidth( naturalSize.width );
}
else
{
- contentSize = RelayoutHelper::GetNaturalSize( mContent );
+ naturalSize += titleNaturalSize;
}
+ naturalSize.height += mPopupStyle->margin;
+ }
+
+ if( mContent )
+ {
+ Vector3 contentSize = RelayoutHelper::GetNaturalSize( mContent );
+ // Choose the biggest width
naturalSize.width = std::max( naturalSize.width, contentSize.width );
+ if( naturalSize.width > maxWidth )
+ {
+ naturalSize.width = maxWidth;
+ contentSize.height = RelayoutHelper::GetHeightForWidth( mContent, maxWidth );
+ }
naturalSize.height += contentSize.height + mPopupStyle->margin;
}
}
// Add the margins
- float margin( 2.0f * ( POPUP_OUT_MARGIN_WIDTH + mPopupStyle->margin ) );
naturalSize.width += margin;
naturalSize.height += margin;
if( mContent )
{
- float contentHeight;
-
- Toolkit::Control control = Toolkit::Control::DownCast( mContent );
- if( control )
- {
- contentHeight = control.GetImplementation().GetHeightForWidth( popupWidth );
- }
- else
- {
- contentHeight = RelayoutHelper::GetHeightForWidth( mContent, popupWidth );
- }
-
- height += contentHeight + mPopupStyle->margin;
+ height += RelayoutHelper::GetHeightForWidth( mContent, popupWidth ) + mPopupStyle->margin;
}
if( !mButtons.empty() )
return GetNaturalSize().width;
}
-Actor Popup::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Control::KeyboardFocusNavigationDirection direction, bool loopEnabled)
+Actor Popup::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocusNavigationDirection direction, bool loopEnabled)
{
Actor nextFocusableActor( currentFocusedActor );
{
switch ( direction )
{
- case Control::Left:
+ case Toolkit::Control::Left:
{
if ( iter == focusableActors.begin() )
{
}
break;
}
- case Control::Right:
+ case Toolkit::Control::Right:
{
if ( iter == focusableActors.end() - 1 )
{
break;
}
- case Control::Up:
+ case Toolkit::Control::Up:
{
if ( *iter == mContent )
{
break;
}
- case Control::Down:
+ case Toolkit::Control::Down:
{
if ( mContent && mContent.IsKeyboardFocusable() )
{