Pass Grab handle events to Controller 35/36135/7
authorPaul Wisbey <p.wisbey@samsung.com>
Mon, 2 Mar 2015 15:41:54 +0000 (15:41 +0000)
committerPaul Wisbey <p.wisbey@samsung.com>
Mon, 2 Mar 2015 18:08:46 +0000 (18:08 +0000)
Change-Id: I24c369ef7eefa7397e88e897c683536501c62076

dali-toolkit/public-api/text/decorator/text-decorator.cpp
dali-toolkit/public-api/text/decorator/text-decorator.h
dali-toolkit/public-api/text/text-controller.cpp
dali-toolkit/public-api/text/text-controller.h

index ce93854..148fbc8 100644 (file)
@@ -117,7 +117,9 @@ struct Decorator::Impl : public ConnectionTracker
     mActiveSelection( false ),
     mCursorBlinkInterval( CURSOR_BLINK_INTERVAL ),
     mCursorBlinkDuration(0.0f),
-    mCursorBlinkStatus( true )
+    mCursorBlinkStatus( true ),
+    mGrabDisplacementX(0.0f),
+    mGrabDisplacementY(0.0f)
   {
   }
 
@@ -197,6 +199,8 @@ struct Decorator::Impl : public ConnectionTracker
 #endif
         parent.Add( mPrimaryCursor);
       }
+
+      mPrimaryCursor.SetPosition( mCursor[PRIMARY_CURSOR].x, mCursor[PRIMARY_CURSOR].y );
     }
     else if ( mActiveCursor == ACTIVE_CURSOR_BOTH )
     {
@@ -393,9 +397,29 @@ struct Decorator::Impl : public ConnectionTracker
 
   void OnPan( Actor actor, const PanGesture& gesture )
   {
-    if( actor == mGrabHandle )
+    if( actor == mGrabArea )
     {
-      // TODO
+      if( Gesture::Started == gesture.state )
+      {
+        mGrabDisplacementX = mGrabDisplacementY = 0;
+      }
+
+      mGrabDisplacementX += gesture.displacement.x;
+      mGrabDisplacementY += gesture.displacement.y;
+
+      float x = mCursor[PRIMARY_CURSOR].x + mGrabDisplacementX;
+      float y = mCursor[PRIMARY_CURSOR].y + mCursor[PRIMARY_CURSOR].height*0.5f + mGrabDisplacementY;
+
+      if( Gesture::Started    == gesture.state ||
+          Gesture::Continuing == gesture.state )
+      {
+        mObserver.GrabHandleEvent( GRAB_HANDLE_PRESSED, x, y );
+      }
+      else if( Gesture::Finished  == gesture.state ||
+               Gesture::Cancelled == gesture.state )
+      {
+        mObserver.GrabHandleEvent( GRAB_HANDLE_RELEASED, x, y );
+      }
     }
   }
 
@@ -432,6 +456,8 @@ struct Decorator::Impl : public ConnectionTracker
 
   ImageActor mGrabHandle;
   Actor mGrabArea;
+  float mGrabDisplacementX;
+  float mGrabDisplacementY;
 
   SelectionHandleImpl mSelectionHandle[SELECTION_HANDLE_COUNT];
 
@@ -468,6 +494,10 @@ unsigned int Decorator::GetActiveCursor() const
 
 void Decorator::SetPosition( Cursor cursor, float x, float y, float height )
 {
+  // Adjust grab handle displacement
+  mImpl->mGrabDisplacementX -= x - mImpl->mCursor[cursor].x;
+  mImpl->mGrabDisplacementY -= y - mImpl->mCursor[cursor].y;
+
   mImpl->mCursor[cursor].x = x;
   mImpl->mCursor[cursor].y = y;
   mImpl->mCursor[cursor].height = height;
index 809be0d..144f0ef 100644 (file)
@@ -113,8 +113,9 @@ public:
      *
      * @param[in] state The grab handle state.
      * @param[in] x The x position relative to the top-left of the parent control.
+     * @param[in] y The y position relative to the top-left of the parent control.
      */
-    virtual void GrabHandleEvent( GrabHandleState state, float x ) = 0;
+    virtual void GrabHandleEvent( GrabHandleState state, float x, float y ) = 0;
   };
 
   /**
index 878272c..58fd536 100644 (file)
@@ -85,8 +85,12 @@ struct Controller::TextInput
     EDITING
   };
 
-  TextInput( DecoratorPtr decorator )
-  : mDecorator( decorator ),
+  TextInput( LogicalModelPtr logicalModel,
+             VisualModelPtr visualModel,
+             DecoratorPtr decorator )
+  : mLogicalModel( logicalModel ),
+    mVisualModel( visualModel ),
+    mDecorator( decorator ),
     mState( INACTIVE )
   {
   }
@@ -146,7 +150,13 @@ struct Controller::TextInput
       mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY );
       mDecorator->StartCursorBlink();
       mDecorator->SetGrabHandleActive( true );
-      mDecorator->SetPosition( PRIMARY_CURSOR, 10, 0, 18 );
+
+      float xPosition = event.p2.mFloat;
+      float yPosition = event.p3.mFloat;
+      float height(0.0f);
+      GetClosestCursorPosition( xPosition, yPosition, height );
+      mDecorator->SetPosition( PRIMARY_CURSOR, xPosition, yPosition, height );
+
       mDecoratorUpdated = true;
     }
     else if( 2u == event.p1.mUint )
@@ -160,11 +170,68 @@ struct Controller::TextInput
 
   void OnGrabHandleEvent( const Event& event )
   {
-    // TODO
+    unsigned int state = event.p1.mUint;
+
+    if( GRAB_HANDLE_PRESSED == state )
+    {
+      float xPosition = event.p2.mFloat;
+      float yPosition = event.p3.mFloat;
+      float height(0.0f);
+
+      GetClosestCursorPosition( xPosition, yPosition, height );
+
+      mDecorator->SetPosition( PRIMARY_CURSOR, xPosition, yPosition, height );
+      mDecoratorUpdated = true;
+    }
   }
 
-  DecoratorPtr mDecorator;
-  bool mDecoratorUpdated;
+  void GetClosestCursorPosition( float& x, float& y, float& height )
+  {
+    // TODO - Look at LineRuns first
+
+    Text::Length numberOfGlyphs = mVisualModel->GetNumberOfGlyphs();
+    if( 0 == numberOfGlyphs )
+    {
+      return;
+    }
+
+    Vector<GlyphInfo> glyphs;
+    glyphs.Resize( numberOfGlyphs );
+    mVisualModel->GetGlyphs( &glyphs[0], 0, numberOfGlyphs );
+
+    std::vector<Vector2> positions;
+    positions.resize( numberOfGlyphs );
+    mVisualModel->GetGlyphPositions( &positions[0], 0, numberOfGlyphs );
+
+    unsigned int closestGlyph = 0;
+    float closestDistance = std::numeric_limits<float>::max();
+
+    for( unsigned int i=0; i<glyphs.Count(); ++i )
+    {
+      float glyphX = positions[i].x + glyphs[i].width*0.5f;
+      float glyphY = positions[i].y + glyphs[i].height*0.5f;
+
+      float distanceToGlyph = fabsf( glyphX - x ) + fabsf( glyphY - y );
+
+      if( distanceToGlyph < closestDistance )
+      {
+        closestDistance = distanceToGlyph;
+        closestGlyph = i;
+      }
+    }
+
+    // TODO - Consider RTL languages
+    x = positions[closestGlyph].x + glyphs[closestGlyph].width;
+    y = 0.0f;
+
+    FontMetrics metrics;
+    TextAbstraction::FontClient::Get().GetFontMetrics( glyphs[closestGlyph].fontId, metrics );
+    height = metrics.height; // TODO - Fix for multi-line
+  }
+
+  LogicalModelPtr mLogicalModel;
+  VisualModelPtr  mVisualModel;
+  DecoratorPtr    mDecorator;
 
   State mState;
 
@@ -173,6 +240,8 @@ struct Controller::TextInput
    * The number of updates to the model is minimized to improve performance.
    */
   vector<Event> mEventQueue; ///< The queue of touch events etc.
+
+  bool mDecoratorUpdated;
 };
 
 struct Controller::Impl
@@ -242,7 +311,7 @@ void Controller::EnableTextInput( DecoratorPtr decorator )
 {
   if( !mImpl->mTextInput )
   {
-    mImpl->mTextInput = new TextInput( decorator );
+    mImpl->mTextInput = new TextInput( mImpl->mLogicalModel, mImpl->mVisualModel, decorator );
   }
 }
 
@@ -370,7 +439,7 @@ bool Controller::DoRelayout( const Vector2& size, OperationsMask operations )
 
   if( GET_GLYPH_METRICS & operations )
   {
-    TextAbstraction::FontClient::Get().GetGlyphMetrics( glyphs.Begin(), glyphs.Count() );
+    mImpl->mFontClient.GetGlyphMetrics( glyphs.Begin(), glyphs.Count() );
   }
 
   if( LAYOUT & operations )
@@ -523,15 +592,16 @@ void Controller::TapEvent( unsigned int tapCount, float x, float y )
   }
 }
 
-void Controller::GrabHandleEvent( GrabHandleState state, float x )
+void Controller::GrabHandleEvent( GrabHandleState state, float x, float y )
 {
   DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected GrabHandleEvent" );
 
   if( mImpl->mTextInput )
   {
     TextInput::Event event( TextInput::GRAB_HANDLE_EVENT );
-    event.p1.mInt   = state;
+    event.p1.mUint  = state;
     event.p2.mFloat = x;
+    event.p3.mFloat = y;
     mImpl->mTextInput->mEventQueue.push_back( event );
 
     RequestRelayout();
index 8f67531..8133451 100644 (file)
@@ -163,7 +163,7 @@ public:
   /**
    * @copydoc Dali::Toolkit::Text::Decorator::Observer::GrabHandleEvent()
    */
-  virtual void GrabHandleEvent( GrabHandleState state, float x );
+  virtual void GrabHandleEvent( GrabHandleState state, float x, float y );
 
 protected: