+Control::Control( ControlBehaviour behaviourFlags )
+: CustomActorImpl( behaviourFlags & REQUIRES_TOUCH_EVENTS ),
+ mImpl(new Impl(*this))
+{
+ mImpl->mFlags = behaviourFlags;
+}
+
+void Control::Initialize()
+{
+
+ // Calling deriving classes
+ OnInitialize();
+
+ if( mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS )
+ {
+ Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
+
+ // Register for style changes
+ styleManager.StyleChangeSignal().Connect( this, &Control::DoStyleChange );
+
+ // SetTheme
+ GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
+ }
+
+ SetRequiresHoverEvents(mImpl->mFlags & REQUIRES_HOVER_EVENTS);
+ SetRequiresMouseWheelEvents(mImpl->mFlags & REQUIRES_MOUSE_WHEEL_EVENTS);
+
+ mImpl->mInitialized = true;
+}
+
+void Control::EnableGestureDetection(Gesture::Type type)
+{
+ if ( (type & Gesture::Pinch) && !mImpl->mPinchGestureDetector )
+ {
+ mImpl->mPinchGestureDetector = PinchGestureDetector::New();
+ mImpl->mPinchGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PinchDetected);
+ mImpl->mPinchGestureDetector.Attach(Self());
+ }
+
+ if ( (type & Gesture::Pan) && !mImpl->mPanGestureDetector )
+ {
+ mImpl->mPanGestureDetector = PanGestureDetector::New();
+ mImpl->mPanGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PanDetected);
+ mImpl->mPanGestureDetector.Attach(Self());
+ }
+
+ if ( (type & Gesture::Tap) && !mImpl->mTapGestureDetector )
+ {
+ mImpl->mTapGestureDetector = TapGestureDetector::New();
+ mImpl->mTapGestureDetector.DetectedSignal().Connect(mImpl, &Impl::TapDetected);
+ mImpl->mTapGestureDetector.Attach(Self());
+ }
+
+ if ( (type & Gesture::LongPress) && !mImpl->mLongPressGestureDetector )
+ {
+ mImpl->mLongPressGestureDetector = LongPressGestureDetector::New();
+ mImpl->mLongPressGestureDetector.DetectedSignal().Connect(mImpl, &Impl::LongPressDetected);
+ mImpl->mLongPressGestureDetector.Attach(Self());
+ }
+}
+
+void Control::DisableGestureDetection(Gesture::Type type)
+{
+ if ( (type & Gesture::Pinch) && mImpl->mPinchGestureDetector )
+ {
+ mImpl->mPinchGestureDetector.Detach(Self());
+ mImpl->mPinchGestureDetector.Reset();
+ }
+
+ if ( (type & Gesture::Pan) && mImpl->mPanGestureDetector )
+ {
+ mImpl->mPanGestureDetector.Detach(Self());
+ mImpl->mPanGestureDetector.Reset();
+ }
+
+ if ( (type & Gesture::Tap) && mImpl->mTapGestureDetector )
+ {
+ mImpl->mTapGestureDetector.Detach(Self());
+ mImpl->mTapGestureDetector.Reset();
+ }
+
+ if ( (type & Gesture::LongPress) && mImpl->mLongPressGestureDetector)
+ {
+ mImpl->mLongPressGestureDetector.Detach(Self());
+ mImpl->mLongPressGestureDetector.Reset();
+ }
+}
+
+void Control::RelayoutRequest()
+{
+ // unfortunate double negative but thats to guarantee new controls get size negotiation
+ // by default and have to "opt-out" if they dont want it
+ if( !(mImpl->mFlags & NO_SIZE_NEGOTIATION) )
+ {
+ Internal::RelayoutController::Request();
+ }
+}
+
+void Control::Relayout( Actor actor, Vector2 size, ActorSizeContainer& container )
+{
+ if ( actor )
+ {
+ Toolkit::Control control( Toolkit::Control::DownCast( actor ) );
+ if( control )
+ {
+ control.GetImplementation().NegotiateSize( size, container );
+ }
+ else
+ {
+ container.push_back( ActorSizePair( actor, size ) );
+ }
+ }
+}
+
+void Control::OnInitialize()
+{
+}
+
+void Control::OnActivated()
+{
+}
+
+void Control::OnThemeChange( Toolkit::StyleManager styleManager )
+{
+ GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
+}
+
+void Control::OnFontChange( bool defaultFontChange, bool defaultFontSizeChange )
+{
+}
+
+void Control::OnPinch(const PinchGesture& pinch)
+{
+ if( !( mImpl->mStartingPinchScale ) )
+ {
+ // lazy allocate
+ mImpl->mStartingPinchScale = new Vector3;
+ }
+
+ if( pinch.state == Gesture::Started )
+ {
+ *( mImpl->mStartingPinchScale ) = Self().GetCurrentScale();
+ }
+
+ Self().SetScale( *( mImpl->mStartingPinchScale ) * pinch.scale );
+}
+
+void Control::OnPan( const PanGesture& pan )
+{
+}
+
+void Control::OnTap(const TapGesture& tap)
+{
+}
+
+void Control::OnLongPress( const LongPressGesture& longPress )
+{
+}
+
+void Control::OnControlStageConnection()
+{
+}
+
+void Control::OnControlStageDisconnection()
+{
+}
+
+void Control::OnControlChildAdd( Actor& child )
+{
+}
+
+void Control::OnControlChildRemove( Actor& child )
+{
+}
+
+void Control::OnControlSizeSet( const Vector3& size )
+{
+}
+
+void Control::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
+{
+ unsigned int numChildren = Self().GetChildCount();
+
+ for( unsigned int i=0; i<numChildren; ++i )
+ {
+ container.push_back( ActorSizePair( Self().GetChildAt(i), size ) );
+ }
+}
+
+void Control::OnKeyInputFocusGained()
+{
+ // Do Nothing
+}
+
+void Control::OnKeyInputFocusLost()
+{
+ // Do Nothing
+}
+
+void Control::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
+{
+ // @todo consider animating negotiated child sizes to target size
+}
+
+bool Control::OnTouchEvent(const TouchEvent& event)
+{
+ return false; // Do not consume
+}
+
+bool Control::OnHoverEvent(const HoverEvent& event)
+{
+ return false; // Do not consume
+}
+
+bool Control::OnKeyEvent(const KeyEvent& event)
+{
+ return false; // Do not consume
+}
+
+bool Control::OnMouseWheelEvent(const MouseWheelEvent& event)
+{
+ return false; // Do not consume
+}
+
+Actor Control::GetChildByAlias(const std::string& actorAlias)
+{
+ return Actor();
+}
+
+void Control::OnStageConnection()
+{
+ RelayoutRequest();
+
+ // Notify derived classes.
+ OnControlStageConnection();
+}
+
+void Control::OnStageDisconnection()
+{
+ // Notify derived classes
+ OnControlStageDisconnection();
+}
+
+void Control::OnChildAdd(Actor& child)
+{
+ // If this is the background actor, then we do not want to relayout or inform deriving classes
+ if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
+ {
+ return;
+ }
+
+ // Request for relayout as we may need to position the new child and old ones
+ RelayoutRequest();
+
+ // Notify derived classes.
+ OnControlChildAdd( child );
+}
+
+void Control::OnChildRemove(Actor& child)
+{
+ // If this is the background actor, then we do not want to relayout or inform deriving classes
+ if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
+ {
+ return;
+ }
+
+ // Request for relayout as we may need to re-position the old child
+ RelayoutRequest();
+
+ // Notify derived classes.
+ OnControlChildRemove( child );
+}
+
+void Control::OnSizeSet(const Vector3& targetSize)
+{
+ if( ( !mImpl->mInsideRelayout ) && ( targetSize != mImpl->mNaturalSize ) )
+ {
+ // Only updates size if set through Actor's API
+ mImpl->mNaturalSize = targetSize;
+ }
+
+ if( targetSize != mImpl->mCurrentSize )
+ {
+ // Update control size.
+ mImpl->mCurrentSize = targetSize;
+
+ // Notify derived classes.
+ OnControlSizeSet( targetSize );
+ }
+}
+