mSelectionEnabled( true ),
mHorizontalScrollingEnabled( true ),
mVerticalScrollingEnabled( false ),
- mUpdateCursorPosition( false )
+ mUpdateCursorPosition( false ),
+ mScrollAfterUpdateCursorPosition( false )
{}
EventData::~EventData()
// The cursor must also be repositioned after inserts into the model
if( mEventData->mUpdateCursorPosition )
{
+ // Updates the cursor position and scrolls the text to make it visible.
+
UpdateCursorPosition();
+
+ if( mEventData->mScrollAfterUpdateCursorPosition )
+ {
+ ScrollToMakeCursorVisible();
+ mEventData->mScrollAfterUpdateCursorPosition = false;
+ }
+
mEventData->mUpdateCursorPosition = false;
}
// TODO
}
- UpdateCursorPosition();
+ mEventData->mUpdateCursorPosition = true;
+ mEventData->mScrollAfterUpdateCursorPosition = true;
}
void Controller::Impl::HandleCursorKey( int keyCode )
{
ChangeState( EventData::EDITING );
- const float xPosition = event.p2.mFloat - mAlignmentOffset.x;
- const float yPosition = event.p3.mFloat - mAlignmentOffset.y;
+ const float xPosition = event.p2.mFloat - mEventData->mScrollPosition.x - mAlignmentOffset.x;
+ const float yPosition = event.p3.mFloat - mEventData->mScrollPosition.y - mAlignmentOffset.y;
mEventData->mPrimaryCursorPosition = GetClosestCursorIndex( xPosition,
yPosition );
- UpdateCursorPosition();
+ mEventData->mUpdateCursorPosition = true;
+ mEventData->mScrollAfterUpdateCursorPosition = true;
}
else if( mEventData->mSelectionEnabled &&
( 2u == tapCount ) )
Gesture::Continuing == state )
{
const Vector2& actualSize = mVisualModel->GetActualSize();
+ const Vector2 currentScroll = mEventData->mScrollPosition;
if( mEventData->mHorizontalScrollingEnabled )
{
const float displacementX = event.p2.mFloat;
mEventData->mScrollPosition.x += displacementX;
- // Clamp between -space & 0 (and the text alignment).
- if( actualSize.width > mControlSize.width )
- {
- const float space = ( actualSize.width - mControlSize.width ) + mAlignmentOffset.x;
- mEventData->mScrollPosition.x = ( mEventData->mScrollPosition.x < -space ) ? -space : mEventData->mScrollPosition.x;
- mEventData->mScrollPosition.x = ( mEventData->mScrollPosition.x > -mAlignmentOffset.x ) ? -mAlignmentOffset.x : mEventData->mScrollPosition.x;
-
- mEventData->mDecoratorUpdated = true;
- }
- else
- {
- mEventData->mScrollPosition.x = 0.f;
- }
+ ClampHorizontalScroll( actualSize );
}
if( mEventData->mVerticalScrollingEnabled )
const float displacementY = event.p3.mFloat;
mEventData->mScrollPosition.y += displacementY;
- // Clamp between -space & 0 (and the text alignment).
- if( actualSize.height > mControlSize.height )
- {
- const float space = ( actualSize.height - mControlSize.height ) + mAlignmentOffset.y;
- mEventData->mScrollPosition.y = ( mEventData->mScrollPosition.y < -space ) ? -space : mEventData->mScrollPosition.y;
- mEventData->mScrollPosition.y = ( mEventData->mScrollPosition.y > -mAlignmentOffset.y ) ? -mAlignmentOffset.y : mEventData->mScrollPosition.y;
+ ClampVerticalScroll( actualSize );
+ }
- mEventData->mDecoratorUpdated = true;
- }
- else
- {
- mEventData->mScrollPosition.y = 0.f;
- }
+ if( mEventData->mDecorator )
+ {
+ mEventData->mDecorator->UpdatePositions( mEventData->mScrollPosition - currentScroll );
}
}
}
if( GRAB_HANDLE_PRESSED == state )
{
- float xPosition = event.p2.mFloat + mEventData->mScrollPosition.x;
- float yPosition = event.p3.mFloat + mEventData->mScrollPosition.y;
-
- mEventData->mPrimaryCursorPosition = GetClosestCursorIndex( xPosition,
- yPosition );
-
- UpdateCursorPosition();
+ // The event.p2 and event.p3 are in decorator coords. Need to transforms to text coords.
+ const float xPosition = event.p2.mFloat - mEventData->mScrollPosition.x - mAlignmentOffset.x;
+ const float yPosition = event.p3.mFloat - mEventData->mScrollPosition.y - mAlignmentOffset.y;
//mDecorator->HidePopup();
ChangeState ( EventData::EDITING );
+
+ const CharacterIndex newCursorPosition = GetClosestCursorIndex( xPosition, yPosition );
+
+ if( newCursorPosition != mEventData->mPrimaryCursorPosition )
+ {
+ mEventData->mPrimaryCursorPosition = newCursorPosition;
+ mEventData->mUpdateCursorPosition = true;
+ }
}
else if( mEventData->mGrabHandlePopupEnabled &&
( GRAB_HANDLE_RELEASED == state ) )
{
//mDecorator->ShowPopup();
ChangeState ( EventData::EDITING_WITH_POPUP );
+ mEventData->mUpdateCursorPosition = true;
mEventData->mDecoratorUpdated = true;
}
}
if( count )
{
- float primaryX = positions[0].x;
- float secondaryX = positions[count-1].x + glyphs[count-1].width;
+ float primaryX = positions[0].x + mEventData->mScrollPosition.x;
+ float secondaryX = positions[count-1].x + glyphs[count-1].width + mEventData->mScrollPosition.x;
// TODO - multi-line selection
const Vector<LineRun>& lines = mVisualModel->mLines;
float height = lines.Count() ? lines[0].ascender + -lines[0].descender : 0.0f;
- mEventData->mDecorator->SetPosition( PRIMARY_SELECTION_HANDLE, primaryX, 0.0f, height );
- mEventData->mDecorator->SetPosition( SECONDARY_SELECTION_HANDLE, secondaryX, 0.0f, height );
+ mEventData->mDecorator->SetPosition( PRIMARY_SELECTION_HANDLE, primaryX, mEventData->mScrollPosition.y, height );
+ mEventData->mDecorator->SetPosition( SECONDARY_SELECTION_HANDLE, secondaryX, mEventData->mScrollPosition.y, height );
mEventData->mDecorator->ClearHighlights();
- mEventData->mDecorator->AddHighlight( primaryX, 0.0f, secondaryX, height );
+ mEventData->mDecorator->AddHighlight( primaryX, mEventData->mScrollPosition.y, secondaryX, height + mEventData->mScrollPosition.y );
}
}
return logicalIndex;
}
- // Transform to visual model coords
- visualX -= mEventData->mScrollPosition.x;
- visualY -= mEventData->mScrollPosition.y;
-
// Find which line is closest
const LineIndex lineIndex = GetClosestLine( visualY );
const LineRun& line = mVisualModel->mLines[lineIndex];
cursorInfo );
mEventData->mDecorator->SetPosition( PRIMARY_CURSOR,
- cursorInfo.primaryPosition.x,
- cursorInfo.primaryPosition.y,
+ cursorInfo.primaryPosition.x + mEventData->mScrollPosition.x + mAlignmentOffset.x,
+ cursorInfo.primaryPosition.y + mEventData->mScrollPosition.y + mAlignmentOffset.y,
cursorInfo.primaryCursorHeight,
cursorInfo.lineHeight );
{
mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_BOTH );
mEventData->mDecorator->SetPosition( SECONDARY_CURSOR,
- cursorInfo.secondaryPosition.x,
- cursorInfo.secondaryPosition.y,
+ cursorInfo.secondaryPosition.x + mEventData->mScrollPosition.x + mAlignmentOffset.x,
+ cursorInfo.secondaryPosition.y + mEventData->mScrollPosition.y + mAlignmentOffset.y,
cursorInfo.secondaryCursorHeight,
cursorInfo.lineHeight );
}
mEventData->mDecoratorUpdated = true;
}
+void Controller::Impl::ClampHorizontalScroll( const Vector2& actualSize )
+{
+ // Clamp between -space & 0 (and the text alignment).
+ if( actualSize.width > mControlSize.width )
+ {
+ const float space = ( actualSize.width - mControlSize.width ) + mAlignmentOffset.x;
+ mEventData->mScrollPosition.x = ( mEventData->mScrollPosition.x < -space ) ? -space : mEventData->mScrollPosition.x;
+ mEventData->mScrollPosition.x = ( mEventData->mScrollPosition.x > -mAlignmentOffset.x ) ? -mAlignmentOffset.x : mEventData->mScrollPosition.x;
+
+ mEventData->mDecoratorUpdated = true;
+ }
+ else
+ {
+ mEventData->mScrollPosition.x = 0.f;
+ }
+}
+
+void Controller::Impl::ClampVerticalScroll( const Vector2& actualSize )
+{
+ // Clamp between -space & 0 (and the text alignment).
+ if( actualSize.height > mControlSize.height )
+ {
+ const float space = ( actualSize.height - mControlSize.height ) + mAlignmentOffset.y;
+ mEventData->mScrollPosition.y = ( mEventData->mScrollPosition.y < -space ) ? -space : mEventData->mScrollPosition.y;
+ mEventData->mScrollPosition.y = ( mEventData->mScrollPosition.y > -mAlignmentOffset.y ) ? -mAlignmentOffset.y : mEventData->mScrollPosition.y;
+
+ mEventData->mDecoratorUpdated = true;
+ }
+ else
+ {
+ mEventData->mScrollPosition.y = 0.f;
+ }
+}
+
+void Controller::Impl::ScrollToMakeCursorVisible()
+{
+ if( NULL == mEventData )
+ {
+ // Nothing to do if there is no text input.
+ return;
+ }
+
+ const Vector2& primaryCursorPosition = mEventData->mDecorator->GetPosition( PRIMARY_CURSOR );
+
+ Vector2 offset;
+ bool updateDecorator = false;
+ if( primaryCursorPosition.x < 0.f )
+ {
+ offset.x = -primaryCursorPosition.x;
+ mEventData->mScrollPosition.x += offset.x;
+ updateDecorator = true;
+ }
+ else if( primaryCursorPosition.x > mControlSize.width )
+ {
+ offset.x = mControlSize.width - primaryCursorPosition.x;
+ mEventData->mScrollPosition.x += offset.x;
+ updateDecorator = true;
+ }
+
+ if( updateDecorator && mEventData->mDecorator )
+ {
+ mEventData->mDecorator->UpdatePositions( offset );
+ }
+
+ // TODO : calculate the Y scroll.
+}
+
void Controller::Impl::RequestRelayout()
{
mControlInterface.RequestTextRelayout();