mActiveSelection( false ),
mCursorBlinkInterval( CURSOR_BLINK_INTERVAL ),
mCursorBlinkDuration(0.0f),
- mCursorBlinkStatus( true )
+ mCursorBlinkStatus( true ),
+ mGrabDisplacementX(0.0f),
+ mGrabDisplacementY(0.0f)
{
}
#endif
parent.Add( mPrimaryCursor);
}
+
+ mPrimaryCursor.SetPosition( mCursor[PRIMARY_CURSOR].x, mCursor[PRIMARY_CURSOR].y );
}
else if ( mActiveCursor == ACTIVE_CURSOR_BOTH )
{
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 );
+ }
}
}
ImageActor mGrabHandle;
Actor mGrabArea;
+ float mGrabDisplacementX;
+ float mGrabDisplacementY;
SelectionHandleImpl mSelectionHandle[SELECTION_HANDLE_COUNT];
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;
EDITING
};
- TextInput( DecoratorPtr decorator )
- : mDecorator( decorator ),
+ TextInput( LogicalModelPtr logicalModel,
+ VisualModelPtr visualModel,
+ DecoratorPtr decorator )
+ : mLogicalModel( logicalModel ),
+ mVisualModel( visualModel ),
+ mDecorator( decorator ),
mState( INACTIVE )
{
}
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 )
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;
* 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
{
if( !mImpl->mTextInput )
{
- mImpl->mTextInput = new TextInput( decorator );
+ mImpl->mTextInput = new TextInput( mImpl->mLogicalModel, mImpl->mVisualModel, decorator );
}
}
if( GET_GLYPH_METRICS & operations )
{
- TextAbstraction::FontClient::Get().GetGlyphMetrics( glyphs.Begin(), glyphs.Count() );
+ mImpl->mFontClient.GetGlyphMetrics( glyphs.Begin(), glyphs.Count() );
}
if( LAYOUT & operations )
}
}
-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();