From f384d637fc0bfd41b4b93221f246719904501c57 Mon Sep 17 00:00:00 2001 From: Paul Wisbey Date: Sun, 8 Mar 2015 11:40:26 +0000 Subject: [PATCH] KeyEvent passing mechanism Change-Id: Ieba701f10bcb3b1e44bcdaf593b8684b8eaa8d03 --- .../controls/text-controls/text-field-impl.cpp | 35 ++++- .../controls/text-controls/text-field-impl.h | 9 +- .../controls/text-controls/text-label-impl.cpp | 2 - dali-toolkit/internal/text/text-controller.cpp | 156 +++++++++++++++++++-- dali-toolkit/internal/text/text-controller.h | 22 +++ 5 files changed, 199 insertions(+), 25 deletions(-) diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp index 2c87bbc..d687d51 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp @@ -19,6 +19,7 @@ #include // EXTERNAL INCLUDES +#include #include #include #include @@ -222,12 +223,22 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde } case Toolkit::TextField::Property::PLACEHOLDER_TEXT: { - DALI_LOG_WARNING( "UTF-8 text representation was discarded\n" ); + if( impl.mController ) + { + std::string text; + impl.mController->GetPlaceholderText( text ); + value = text; + } break; } case Toolkit::TextField::Property::TEXT: { - DALI_LOG_WARNING( "UTF-8 text representation was discarded\n" ); + if( impl.mController ) + { + std::string text; + impl.mController->GetText( text ); + value = text; + } break; } case Toolkit::TextField::Property::CURSOR_IMAGE: @@ -316,10 +327,8 @@ void TextField::OnInitialize() mController->EnableTextInput( mDecorator ); // Forward input events to controller - mDoubleTapDetector = TapGestureDetector::New(); - mDoubleTapDetector.SetMaximumTapsRequired( 2 ); - mDoubleTapDetector.DetectedSignal().Connect( this, &TextField::OnTap ); - mDoubleTapDetector.Attach(Self()); + EnableGestureDetection(Gesture::Tap); + GetTapGestureDetector().SetMaximumTapsRequired( 2 ); // Set BoundingBox to stage size if not already set. if ( mDecorator->GetBoundingBox().IsEmpty() ) @@ -365,11 +374,23 @@ void TextField::OnRelayout( const Vector2& size, ActorSizeContainer& container ) } } -void TextField::OnTap( Actor actor, const TapGesture& gesture ) +void TextField::OnTap( const TapGesture& gesture ) { + SetKeyInputFocus(); + mController->TapEvent( gesture.numberOfTaps, gesture.localPoint.x, gesture.localPoint.y ); } +bool TextField::OnKeyEvent( const KeyEvent& event ) +{ + if( Dali::DALI_KEY_ESCAPE == event.keyCode ) + { + ClearKeyInputFocus(); + } + + return mController->KeyEvent( event ); +} + void TextField::RequestTextRelayout() { RelayoutRequest(); diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.h b/dali-toolkit/internal/controls/text-controls/text-field-impl.h index 32a7db2..23fa0e9 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.h @@ -90,7 +90,12 @@ private: // From Control /** * Received for single & double taps */ - void OnTap( Actor actor, const TapGesture& tap ); + virtual void OnTap( const TapGesture& tap ); + + /** + * @copydoc Dali::CustomActorImpl::OnKeyEvent(const KeyEvent&) + */ + virtual bool OnKeyEvent(const KeyEvent& event); /** * @copydoc Text::ControlInterface::RequestTextRelayout() @@ -121,8 +126,6 @@ private: // Data Text::RendererPtr mRenderer; Text::DecoratorPtr mDecorator; - TapGestureDetector mDoubleTapDetector; - unsigned int mRenderingBackend; }; diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp index bb0607d..2de2c57 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp @@ -199,8 +199,6 @@ Property::Value TextLabel::GetProperty( BaseObject* object, Property::Index inde impl.mController->GetText( text ); value = text; } - - DALI_LOG_WARNING( "UTF-8 text representation was discarded\n" ); break; } case Toolkit::TextLabel::Property::MULTI_LINE: diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index dba8386..60016d2 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -33,6 +33,7 @@ // EXTERNAL INCLUDES #include #include +#include #include using std::vector; @@ -53,6 +54,7 @@ struct Controller::TextInput { KEYBOARD_FOCUS_GAIN_EVENT, KEYBOARD_FOCUS_LOST_EVENT, + KEY_EVENT, TAP_EVENT, GRAB_HANDLE_EVENT }; @@ -62,6 +64,7 @@ struct Controller::TextInput int mInt; unsigned int mUint; float mFloat; + char* mString; }; struct Event @@ -99,7 +102,7 @@ struct Controller::TextInput /** * @brief Helper to move the cursor, grab handle etc. */ - bool ProcessTouchEvents() + bool ProcessInputEvents() { mDecoratorUpdated = false; @@ -119,6 +122,11 @@ struct Controller::TextInput OnKeyboardFocus( false ); break; } + case KEY_EVENT: + { + OnKeyEvent( *iter ); + break; + } case TAP_EVENT: { OnTapEvent( *iter ); @@ -140,17 +148,65 @@ struct Controller::TextInput void OnKeyboardFocus( bool hasFocus ) { + } + + void OnKeyEvent( const Event& event ) + { + int keyCode = event.p1.mInt; + + // Handle state changes + if( Dali::DALI_KEY_ESCAPE == keyCode ) + { + ChangeState( INACTIVE ); // Escape key ends edit mode + } + else if ( event.p2.mString ) + { + // Some text may be selected, hiding keyboard causes an empty keystring to be sent, we don't want to delete highlight in this case + ChangeState( EDITING ); + } + + // Handle the actual key event + if( Dali::DALI_KEY_BACKSPACE == keyCode ) + { + HandleBackspaceKey(); + } + else if( Dali::DALI_KEY_CURSOR_LEFT == keyCode || + Dali::DALI_KEY_CURSOR_RIGHT == keyCode || + Dali::DALI_KEY_CURSOR_UP == keyCode || + Dali::DALI_KEY_CURSOR_DOWN == keyCode ) + { + HandleCursorKey( keyCode ); + } + else if ( event.p2.mString ) + { + HandleKeyString( event.p2.mString ); + + delete [] event.p2.mString; + } + } + + void HandleBackspaceKey() + { + // TODO + } + + void HandleCursorKey( int keyCode ) + { + // TODO + } + + void HandleKeyString( const char* keyString ) + { // TODO } void OnTapEvent( const Event& event ) { - if( 1u == event.p1.mUint ) + unsigned int tapCount = event.p1.mUint; + + if( 1u == tapCount ) { - mState = TextInput::EDITING; - mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY ); - mDecorator->StartCursorBlink(); - mDecorator->SetGrabHandleActive( true ); + ChangeState( EDITING ); float xPosition = event.p2.mFloat; float yPosition = event.p3.mFloat; @@ -160,12 +216,9 @@ struct Controller::TextInput mDecoratorUpdated = true; } - else if( 2u == event.p1.mUint ) + else if( 2u == tapCount ) { - mState = TextInput::SELECTING; - mDecorator->SetGrabHandleActive( false ); - mDecorator->SetSelectionActive( true ); - mDecoratorUpdated = true; + ChangeState( SELECTING ); } } @@ -186,6 +239,39 @@ struct Controller::TextInput } } + void ChangeState( State newState ) + { + if( mState != newState ) + { + mState = newState; + + if( INACTIVE == mState ) + { + mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE ); + mDecorator->StopCursorBlink(); + mDecorator->SetGrabHandleActive( false ); + mDecorator->SetSelectionActive( false ); + mDecoratorUpdated = true; + } + else if ( SELECTING == mState ) + { + mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE ); + mDecorator->StopCursorBlink(); + mDecorator->SetGrabHandleActive( false ); + mDecorator->SetSelectionActive( true ); + mDecoratorUpdated = true; + } + else if( EDITING == mState ) + { + mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY ); + mDecorator->StartCursorBlink(); + mDecorator->SetGrabHandleActive( true ); + mDecorator->SetSelectionActive( false ); + mDecoratorUpdated = true; + } + } + } + void GetClosestCursorPosition( float& x, float& y, float& height ) { // TODO - Look at LineRuns first @@ -234,7 +320,7 @@ struct Controller::TextInput VisualModelPtr mVisualModel; DecoratorPtr mDecorator; - State mState; + std::string mPlaceholderText; /** * This is used to delay handling events until after the model has been updated. @@ -242,6 +328,8 @@ struct Controller::TextInput */ vector mEventQueue; ///< The queue of touch events etc. + State mState; + bool mDecoratorUpdated; }; @@ -349,6 +437,22 @@ void Controller::GetText( std::string& text ) const } } +void Controller::SetPlaceholderText( const std::string& text ) +{ + if( !mImpl->mTextInput ) + { + mImpl->mTextInput->mPlaceholderText = text; + } +} + +void Controller::GetPlaceholderText( std::string& text ) const +{ + if( !mImpl->mTextInput ) + { + text = mImpl->mTextInput->mPlaceholderText; + } +} + void Controller::SetDefaultFontFamily( const std::string& defaultFontFamily ) { if( !mImpl->mFontDefaults ) @@ -446,7 +550,7 @@ bool Controller::Relayout( const Vector2& size ) if( mImpl->mTextInput ) { // Move the cursor, grab handle etc. - updated = mImpl->mTextInput->ProcessTouchEvents() || updated; + updated = mImpl->mTextInput->ProcessInputEvents() || updated; } return updated; @@ -744,6 +848,32 @@ void Controller::KeyboardFocusLostEvent() } } +bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent ) +{ + DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected KeyEvent" ); + + if( mImpl->mTextInput ) + { + TextInput::Event event( TextInput::KEY_EVENT ); + event.p1.mInt = keyEvent.keyCode; + event.p2.mString = NULL; + + const std::string& keyString = keyEvent.keyPressed; + if ( !keyString.empty() ) + { + event.p2.mString = new char[keyString.size() + 1]; + std::copy(keyString.begin(), keyString.end(), event.p2.mString); + event.p2.mString[keyString.size()] = '\0'; + } + + mImpl->mTextInput->mEventQueue.push_back( event ); + + RequestRelayout(); + } + + return false; +} + void Controller::TapEvent( unsigned int tapCount, float x, float y ) { DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected TapEvent" ); diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h index 3fa7c60..11d212b 100644 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -25,6 +25,7 @@ // EXTERNAL INCLUDES #include +#include #include #include #include @@ -106,6 +107,20 @@ public: void GetText( std::string& text ) const; /** + * @brief Replaces any placeholder text previously set. + * + * @param[in] text A string of UTF-8 characters. + */ + void SetPlaceholderText( const std::string& text ); + + /** + * @brief Retrieve any placeholder text previously set. + * + * @return A string of UTF-8 characters. + */ + void GetPlaceholderText( std::string& text ) const; + + /** * @brief Set the default font family. * * @param[in] defaultFontFamily The default font family. @@ -209,6 +224,13 @@ public: void KeyboardFocusLostEvent(); /** + * @brief Caller by editable UI controls when key events are received. + * + * @param[in] event The key event. + */ + bool KeyEvent( const Dali::KeyEvent& event ); + + /** * @brief Caller by editable UI controls when a tap gesture occurs. * @param[in] tapCount The number of taps. * @param[in] x The x position relative to the top-left of the parent control. -- 2.7.4