#endif
const float MAX_FLOAT = std::numeric_limits<float>::max();
-const unsigned int POINTS_PER_INCH = 72;
const std::string EMPTY_STRING("");
// Recalculate the selection highlight as the metrics may have changed.
eventData->mUpdateLeftSelectionPosition = true;
eventData->mUpdateRightSelectionPosition = true;
+ eventData->mUpdateHighlightBox = true;
return fontDescriptionRun;
}
return offset;
}
+void Controller::SetHorizontalScrollEnabled( bool enable )
+{
+ if( ( NULL != mImpl->mEventData ) &&
+ mImpl->mEventData->mDecorator )
+ {
+ mImpl->mEventData->mDecorator->SetHorizontalScrollEnabled( enable );
+ }
+}
+
+bool Controller::IsHorizontalScrollEnabled() const
+{
+ if( ( NULL != mImpl->mEventData ) &&
+ mImpl->mEventData->mDecorator )
+ {
+ return mImpl->mEventData->mDecorator->IsHorizontalScrollEnabled();
+ }
+
+ return false;
+}
+
+void Controller::SetVerticalScrollEnabled( bool enable )
+{
+ if( ( NULL != mImpl->mEventData ) &&
+ mImpl->mEventData->mDecorator )
+ {
+ if( mImpl->mEventData->mDecorator )
+ {
+ mImpl->mEventData->mDecorator->SetVerticalScrollEnabled( enable );
+ }
+ }
+}
+
+bool Controller::IsVerticalScrollEnabled() const
+{
+ if( ( NULL != mImpl->mEventData ) &&
+ mImpl->mEventData->mDecorator )
+ {
+ return mImpl->mEventData->mDecorator->IsVerticalScrollEnabled();
+ }
+
+ return false;
+}
+
+void Controller::SetSmoothHandlePanEnabled( bool enable )
+{
+ if( ( NULL != mImpl->mEventData ) &&
+ mImpl->mEventData->mDecorator )
+ {
+ mImpl->mEventData->mDecorator->SetSmoothHandlePanEnabled( enable );
+ }
+}
+
+bool Controller::IsSmoothHandlePanEnabled() const
+{
+ if( ( NULL != mImpl->mEventData ) &&
+ mImpl->mEventData->mDecorator )
+ {
+ return mImpl->mEventData->mDecorator->IsSmoothHandlePanEnabled();
+ }
+
+ return false;
+}
+
void Controller::SetText( const std::string& text )
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::SetText\n" );
mImpl->mEventData->mEventQueue.clear();
}
- // Notify IMF as text changed
- NotifyImfManager();
-
// Do this last since it provides callbacks into application code
mImpl->mControlInterface.TextChanged();
}
{
if( !mImpl->IsShowingPlaceholderText() )
{
- Vector<Character>& utf32Characters = mImpl->mLogicalModel->mText;
-
- if( 0u != utf32Characters.Count() )
- {
- Utf32ToUtf8( &utf32Characters[0], utf32Characters.Count(), text );
- }
+ // Retrieves the text string.
+ mImpl->GetText( 0u, text );
}
else
{
}
}
-unsigned int Controller::GetLogicalCursorPosition() const
-{
- if( NULL != mImpl->mEventData )
- {
- return mImpl->mEventData->mPrimaryCursorPosition;
- }
-
- return 0u;
-}
-
void Controller::SetPlaceholderText( PlaceholderType type, const std::string& text )
{
if( NULL != mImpl->mEventData )
mImpl->mFontDefaults->mDefaultPointSize = pointSize;
mImpl->mFontDefaults->sizeDefined = true;
- unsigned int horizontalDpi( 0u );
- unsigned int verticalDpi( 0u );
- mImpl->mFontClient.GetDpi( horizontalDpi, verticalDpi );
-
- // Adjust the metrics if the fixed-size font should be down-scaled
- int maxEmojiSize( pointSize/POINTS_PER_INCH * verticalDpi );
- DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::SetDefaultPointSize %p setting MaxEmojiSize %d\n", this, maxEmojiSize );
- mImpl->mMetrics->SetMaxEmojiSize( maxEmojiSize );
-
// Clear the font-specific data
ClearFontData();
// As the font changes, recalculate the handle positions is needed.
mImpl->mEventData->mUpdateLeftSelectionPosition = true;
mImpl->mEventData->mUpdateRightSelectionPosition = true;
+ mImpl->mEventData->mUpdateHighlightBox = true;
mImpl->mEventData->mScrollAfterUpdatePosition = true;
}
}
// As the font might change, recalculate the handle positions is needed.
mImpl->mEventData->mUpdateLeftSelectionPosition = true;
mImpl->mEventData->mUpdateRightSelectionPosition = true;
+ mImpl->mEventData->mUpdateHighlightBox = true;
mImpl->mEventData->mScrollAfterUpdatePosition = true;
}
}
// As the font might change, recalculate the handle positions is needed.
mImpl->mEventData->mUpdateLeftSelectionPosition = true;
mImpl->mEventData->mUpdateRightSelectionPosition = true;
+ mImpl->mEventData->mUpdateHighlightBox = true;
mImpl->mEventData->mScrollAfterUpdatePosition = true;
}
}
// As the font might change, recalculate the handle positions is needed.
mImpl->mEventData->mUpdateLeftSelectionPosition = true;
mImpl->mEventData->mUpdateRightSelectionPosition = true;
+ mImpl->mEventData->mUpdateHighlightBox = true;
mImpl->mEventData->mScrollAfterUpdatePosition = true;
}
}
// As the font might change, recalculate the handle positions is needed.
mImpl->mEventData->mUpdateLeftSelectionPosition = true;
mImpl->mEventData->mUpdateRightSelectionPosition = true;
+ mImpl->mEventData->mUpdateHighlightBox = true;
mImpl->mEventData->mScrollAfterUpdatePosition = true;
}
}
return layoutSize.height;
}
-bool Controller::Relayout( const Size& size )
+Controller::UpdateTextType Controller::Relayout( const Size& size )
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::Relayout %p size %f,%f, autoScroll[%s]\n", this, size.width, size.height, (mImpl->mAutoScrollEnabled)?"true":"false" );
+ UpdateTextType updateTextType = NONE_UPDATED;
+
if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) )
{
- bool glyphsRemoved( false );
if( 0u != mImpl->mVisualModel->mGlyphPositions.Count() )
{
mImpl->mVisualModel->mGlyphPositions.Clear();
- glyphsRemoved = true;
+ updateTextType = MODEL_UPDATED;
}
// Clear the update info. This info will be set the next time the text is updated.
// Not worth to relayout if width or height is equal to zero.
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::Relayout (skipped)\n" );
- return glyphsRemoved;
+ return updateTextType;
}
// Whether a new size has been set.
mImpl->mOperationsPending,
layoutSize ) || updated;
+ if( updated )
+ {
+ updateTextType = MODEL_UPDATED;
+ }
+
// Do not re-do any operation until something changes.
mImpl->mOperationsPending = NO_OPERATION;
}
// Move the cursor, grab handle etc.
- updated = mImpl->ProcessInputEvents() || updated;
+ if( mImpl->ProcessInputEvents() )
+ {
+ updateTextType = static_cast<UpdateTextType>( updateTextType | DECORATOR_UPDATED );
+ }
}
// Clear the update info. This info will be set the next time the text is updated.
mImpl->mTextUpdateInfo.Clear();
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::Relayout\n" );
- return updated;
+ return updateTextType;
}
void Controller::ProcessModifyEvents()
textChanged = true;
}
- if( ( mImpl->mEventData->mState != EventData::INTERRUPTED ) &&
- ( mImpl->mEventData->mState != EventData::INACTIVE ) )
+ if ( ( mImpl->mEventData->mState != EventData::INTERRUPTED ) &&
+ ( mImpl->mEventData->mState != EventData::INACTIVE ) &&
+ ( Dali::DALI_KEY_SHIFT_LEFT != keyCode ) )
{
+ // Should not change the state if the key is the shift send by the imf manager.
+ // Otherwise, when the state is SELECTING the text controller can't send the right
+ // surrounding info to the imf.
mImpl->ChangeState( EventData::EDITING );
}
}
else
{
+ // Show cursor and grabhandle on first tap, this matches the behaviour of tapping when already editing
mImpl->ChangeState( EventData::EDITING_WITH_GRAB_HANDLE );
}
relayoutNeeded = true;
}
void Controller::PanEvent( Gesture::State state, const Vector2& displacement )
- // Show cursor and grabhandle on first tap, this matches the behaviour of tapping when already editing
{
DALI_ASSERT_DEBUG( mImpl->mEventData && "Unexpected PanEvent" );
mImpl->SendSelectionToClipboard( true ); // Synchronous call to modify text
mImpl->mOperationsPending = ALL_OPERATIONS;
- // This is to reset the virtual keyboard to Upper-case
- if( 0u == mImpl->mLogicalModel->mText.Count() )
- {
- NotifyImfManager();
- }
-
if( ( 0u != mImpl->mLogicalModel->mText.Count() ) ||
!mImpl->IsPlaceholderAvailable() )
{
case Toolkit::TextSelectionPopup::COPY:
{
mImpl->SendSelectionToClipboard( false ); // Text not modified
- mImpl->RequestRelayout(); // Handles, Selection Highlight, Popup
+
+ mImpl->mEventData->mUpdateCursorPosition = true;
+
+ mImpl->RequestRelayout(); // Cursor, Handles, Selection Highlight, Popup
break;
}
case Toolkit::TextSelectionPopup::PASTE:
ImfManager::ImfCallbackData Controller::OnImfEvent( ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent )
{
- bool update = false;
+ // Whether the text needs to be relaid-out.
bool requestRelayout = false;
- std::string text;
- unsigned int cursorPosition = 0u;
+ // Whether to retrieve the text and cursor position to be sent to the IMF manager.
+ bool retrieveText = false;
+ bool retrieveCursor = false;
switch( imfEvent.eventName )
{
case ImfManager::COMMIT:
{
InsertText( imfEvent.predictiveString, Text::Controller::COMMIT );
- update = true;
requestRelayout = true;
+ retrieveCursor = true;
break;
}
case ImfManager::PREEDIT:
{
InsertText( imfEvent.predictiveString, Text::Controller::PRE_EDIT );
- update = true;
requestRelayout = true;
+ retrieveCursor = true;
break;
}
case ImfManager::DELETESURROUNDING:
{
- update = RemoveText( imfEvent.cursorOffset,
- imfEvent.numberOfChars,
- DONT_UPDATE_INPUT_STYLE );
+ const bool textDeleted = RemoveText( imfEvent.cursorOffset,
+ imfEvent.numberOfChars,
+ DONT_UPDATE_INPUT_STYLE );
- if( update )
+ if( textDeleted )
{
if( ( 0u != mImpl->mLogicalModel->mText.Count() ) ||
!mImpl->IsPlaceholderAvailable() )
}
mImpl->mEventData->mUpdateCursorPosition = true;
mImpl->mEventData->mScrollAfterDelete = true;
+
+ requestRelayout = true;
}
- requestRelayout = true;
break;
}
case ImfManager::GETSURROUNDING:
{
- GetText( text );
- cursorPosition = GetLogicalCursorPosition();
-
- imfManager.SetSurroundingText( text );
- imfManager.SetCursorPosition( cursorPosition );
+ retrieveText = true;
+ retrieveCursor = true;
break;
}
case ImfManager::VOID:
}
} // end switch
- if( ImfManager::GETSURROUNDING != imfEvent.eventName )
- {
- GetText( text );
- cursorPosition = GetLogicalCursorPosition();
- }
-
if( requestRelayout )
{
mImpl->mOperationsPending = ALL_OPERATIONS;
mImpl->mControlInterface.TextChanged();
}
- ImfManager::ImfCallbackData callbackData( update, cursorPosition, text, false );
+ std::string text;
+ CharacterIndex cursorPosition = 0u;
+ Length numberOfWhiteSpaces = 0u;
+
+ if( retrieveCursor )
+ {
+ numberOfWhiteSpaces = mImpl->GetNumberOfWhiteSpaces( 0u );
+
+ cursorPosition = mImpl->GetLogicalCursorPosition();
+
+ if( cursorPosition < numberOfWhiteSpaces )
+ {
+ cursorPosition = 0u;
+ }
+ else
+ {
+ cursorPosition -= numberOfWhiteSpaces;
+ }
+ }
+
+ if( retrieveText )
+ {
+ mImpl->GetText( numberOfWhiteSpaces, text );
+ }
+
+ ImfManager::ImfCallbackData callbackData( ( retrieveText || retrieveCursor ), cursorPosition, text, false );
return callbackData;
}
if( removed )
{
- DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::KeyEvent %p DALI_KEY_BACKSPACE RemovedText\n", this );
- // Notifiy the IMF manager after text changed
- // Automatic Upper-case and restarting prediction on an existing word require this.
- NotifyImfManager();
-
if( ( 0u != mImpl->mLogicalModel->mText.Count() ) ||
!mImpl->IsPlaceholderAvailable() )
{
return removed;
}
-void Controller::NotifyImfManager()
-{
- if( NULL != mImpl->mEventData )
- {
- if( mImpl->mEventData->mImfManager )
- {
- // Notifying IMF of a cursor change triggers a surrounding text request so updating it now.
- std::string text;
- GetText( text );
- mImpl->mEventData->mImfManager.SetSurroundingText( text );
-
- mImpl->mEventData->mImfManager.SetCursorPosition( GetLogicalCursorPosition() );
- mImpl->mEventData->mImfManager.NotifyCursorPosition();
- }
- }
-}
-
void Controller::ShowPlaceholderText()
{
if( mImpl->IsPlaceholderAvailable() )