#endif
const float MAX_FLOAT = std::numeric_limits<float>::max();
+const unsigned int POINTS_PER_INCH = 72;
const std::string EMPTY_STRING("");
+const unsigned int ZERO = 0u;
float ConvertToEven( float value )
{
void Controller::SetText( const std::string& text )
{
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::SetText\n" );
+
+ // Reset keyboard as text changed
+ mImpl->ResetImfManager();
+
// Remove the previously set text
ResetText();
mImpl->mEventData->mEventQueue.clear();
}
- // Reset keyboard as text changed
- mImpl->ResetImfManager();
+ // Notify IMF as text changed
+ NotifyImfManager();
// Do this last since it provides callbacks into application code
mImpl->mControlInterface.TextChanged();
return mImpl->mMaximumNumberOfCharacters;
}
-void Controller::SetDefaultFontFamily( const std::string& defaultFontFamily )
+void Controller::SetDefaultFontFamily( const std::string& defaultFontFamily, bool userDefined )
{
if( !mImpl->mFontDefaults )
{
mImpl->mFontDefaults = new FontDefaults();
}
- mImpl->mFontDefaults->mDefaultFontFamily = defaultFontFamily;
+ mImpl->mFontDefaults->mFontDescription.family = defaultFontFamily;
+ DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::SetDefaultFontFamily %s userDefined: %s\n", defaultFontFamily.c_str(), userDefined ? "true":"false" );
+ mImpl->mUserDefinedFontFamily = userDefined;
// Clear the font-specific data
ClearFontData();
{
if( mImpl->mFontDefaults )
{
- return mImpl->mFontDefaults->mDefaultFontFamily;
+ return mImpl->mFontDefaults->mFontDescription.family;
+ }
+
+ return EMPTY_STRING;
+}
+
+void Controller::SetDefaultFontStyle( const std::string& style )
+{
+ if( !mImpl->mFontDefaults )
+ {
+ mImpl->mFontDefaults = new FontDefaults();
+ }
+
+ mImpl->mFontDefaults->mFontStyle = style;
+}
+
+const std::string& Controller::GetDefaultFontStyle() const
+{
+ if( mImpl->mFontDefaults )
+ {
+ return mImpl->mFontDefaults->mFontStyle;
}
return EMPTY_STRING;
}
-void Controller::SetDefaultFontStyle( const std::string& defaultFontStyle )
+void Controller::SetDefaultFontWidth( FontWidth width )
{
if( !mImpl->mFontDefaults )
{
mImpl->mFontDefaults = new FontDefaults();
}
- mImpl->mFontDefaults->mDefaultFontStyle = defaultFontStyle;
+ mImpl->mFontDefaults->mFontDescription.width = width;
// Clear the font-specific data
ClearFontData();
mImpl->RequestRelayout();
}
-const std::string& Controller::GetDefaultFontStyle() const
+FontWidth Controller::GetDefaultFontWidth() const
{
if( mImpl->mFontDefaults )
{
- return mImpl->mFontDefaults->mDefaultFontStyle;
+ return mImpl->mFontDefaults->mFontDescription.width;
}
- return EMPTY_STRING;
+ return TextAbstraction::FontWidth::NORMAL;
+}
+
+void Controller::SetDefaultFontWeight( FontWeight weight )
+{
+ if( !mImpl->mFontDefaults )
+ {
+ mImpl->mFontDefaults = new FontDefaults();
+ }
+
+ mImpl->mFontDefaults->mFontDescription.weight = weight;
+
+ // Clear the font-specific data
+ ClearFontData();
+
+ mImpl->mOperationsPending = ALL_OPERATIONS;
+ mImpl->mRecalculateNaturalSize = true;
+
+ mImpl->RequestRelayout();
+}
+
+FontWeight Controller::GetDefaultFontWeight() const
+{
+ if( mImpl->mFontDefaults )
+ {
+ return mImpl->mFontDefaults->mFontDescription.weight;
+ }
+
+ return TextAbstraction::FontWeight::NORMAL;
+}
+
+void Controller::SetDefaultFontSlant( FontSlant slant )
+{
+ if( !mImpl->mFontDefaults )
+ {
+ mImpl->mFontDefaults = new FontDefaults();
+ }
+
+ mImpl->mFontDefaults->mFontDescription.slant = slant;
+
+ // Clear the font-specific data
+ ClearFontData();
+
+ mImpl->mOperationsPending = ALL_OPERATIONS;
+ mImpl->mRecalculateNaturalSize = true;
+
+ mImpl->RequestRelayout();
+}
+
+FontSlant Controller::GetDefaultFontSlant() const
+{
+ if( mImpl->mFontDefaults )
+ {
+ return mImpl->mFontDefaults->mFontDescription.slant;
+ }
+
+ return TextAbstraction::FontSlant::NORMAL;
}
void Controller::SetDefaultPointSize( float pointSize )
mImpl->mFontDefaults->mDefaultPointSize = pointSize;
+ 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();
return 0.0f;
}
+void Controller::UpdateAfterFontChange( std::string& newDefaultFont )
+{
+ DALI_LOG_INFO( gLogFilter, Debug::Concise, "Controller::UpdateAfterFontChange");
+
+ if ( !mImpl->mUserDefinedFontFamily ) // If user defined font then should not update when system font changes
+ {
+ DALI_LOG_INFO( gLogFilter, Debug::Concise, "Controller::UpdateAfterFontChange newDefaultFont(%s)\n", newDefaultFont.c_str() );
+ ClearFontData();
+ mImpl->mFontDefaults->mFontDescription.family = newDefaultFont;
+ mImpl->UpdateModel( ALL_OPERATIONS );
+ mImpl->QueueModifyEvent( ModifyEvent::TEXT_REPLACED );
+ mImpl->mRecalculateNaturalSize = true;
+ mImpl->RequestRelayout();
+ }
+}
+
void Controller::SetTextColor( const Vector4& textColor )
{
mImpl->mTextColor = textColor;
// Do not re-do any operation until something changes.
mImpl->mOperationsPending = NO_OPERATION;
+ // Keep the current offset and alignment as it will be used to update the decorator's positions.
+ Vector2 offset;
+ if( mImpl->mEventData )
+ {
+ offset = mImpl->mAlignmentOffset + mImpl->mEventData->mScrollPosition;
+ }
+
// After doing the text layout, the alignment offset to place the actor in the desired position can be calculated.
CalculateTextAlignment( size );
if( mImpl->mEventData )
{
+ // If there is a nex size, the scroll position needs to be clamped.
+ mImpl->ClampHorizontalScroll( layoutSize );
+
+ // Update the decorator's positions.
+ mImpl->mEventData->mDecorator->UpdatePositions( mImpl->mAlignmentOffset + mImpl->mEventData->mScrollPosition - offset );
+
// Move the cursor, grab handle etc.
updated = mImpl->ProcessInputEvents() || updated;
}
if( mImpl->mEventData )
{
- mImpl->ChangeState( EventData::EDITING );
+ if( ( EventData::INACTIVE == mImpl->mEventData->mState ) ||
+ ( EventData::INTERRUPTED == mImpl->mEventData->mState ) )
+ {
+ mImpl->ChangeState( EventData::EDITING );
+ mImpl->mEventData->mUpdateCursorPosition = true; //If editing started without tap event, cursor update must be triggered.
+ }
if( mImpl->IsShowingPlaceholderText() )
{
ShowPlaceholderText();
}
- mImpl->mEventData->mUpdateCursorPosition = true; //If editing started without tap event, cursor update must be triggered.
mImpl->RequestRelayout();
}
}
{
mImpl->ChangeState( EventData::INACTIVE );
- if( mImpl->IsShowingPlaceholderText() )
+ if( !mImpl->IsShowingRealText() )
{
// Revert to regular placeholder-text when not editing
ShowPlaceholderText();
textChanged = true;
}
- if ( mImpl->mEventData->mState != EventData::INTERRUPTED && mImpl->mEventData->mState != EventData::INACTIVE )
+ if ( ( mImpl->mEventData->mState != EventData::INTERRUPTED ) &&
+ ( mImpl->mEventData->mState != EventData::INACTIVE ) )
{
mImpl->ChangeState( EventData::EDITING );
}
else if( EventData::EDITING != mImpl->mEventData->mState &&
EventData::EDITING_WITH_GRAB_HANDLE != mImpl->mEventData->mState )
{
+ if( mImpl->IsShowingPlaceholderText() && ! mImpl->IsFocusedPlaceholderAvailable() )
+ {
+ // Hide placeholder text
+ ResetText();
+ }
// Show cursor on first tap
mImpl->ChangeState( EventData::EDITING );
relayoutNeeded = true;
void Controller::LongPressEvent( Gesture::State state, float x, float y )
{
- DALI_ASSERT_DEBUG( mImpl->mEventData && "Unexpected PanEvent" );
+ DALI_ASSERT_DEBUG( mImpl->mEventData && "Unexpected LongPressEvent" );
- if ( mImpl->IsShowingPlaceholderText() || mImpl->mLogicalModel->mText.Count() == 0u )
+ if( state == Gesture::Started &&
+ mImpl->mEventData )
{
- if ( mImpl->mEventData )
+ if( ! mImpl->IsShowingRealText() )
{
Event event( Event::LONG_PRESS_EVENT );
event.p1.mInt = state;
mImpl->mEventData->mEventQueue.push_back( event );
mImpl->RequestRelayout();
}
- }
- else if( mImpl->mEventData )
- {
- SelectEvent( x, y, false );
+ else
+ {
+ // The 1st long-press on inactive text-field is treated as tap
+ if( EventData::INACTIVE == mImpl->mEventData->mState )
+ {
+ mImpl->ChangeState( EventData::EDITING );
+
+ Event event( Event::TAP_EVENT );
+ event.p1.mUint = 1;
+ event.p2.mFloat = x;
+ event.p3.mFloat = y;
+ mImpl->mEventData->mEventQueue.push_back( event );
+
+ mImpl->RequestRelayout();
+ }
+ else
+ {
+ // Reset the imf manger to commit the pre-edit before selecting the text.
+ mImpl->ResetImfManager();
+
+ SelectEvent( x, y, false );
+ }
+ }
}
}
{
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() )
{
if( removed )
{
+ // 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() )
{
return removed;
}
+void Controller::NotifyImfManager()
+{
+ if( mImpl->mEventData )
+ {
+ ImfManager imfManager = ImfManager::Get();
+
+ if( imfManager )
+ {
+ // Notifying IMF of a cursor change triggers a surrounding text request so updating it now.
+ std::string text;
+ GetText( text );
+ imfManager.SetSurroundingText( text );
+
+ imfManager.SetCursorPosition( GetLogicalCursorPosition() );
+ imfManager.NotifyCursorPosition();
+ }
+ }
+}
+
void Controller::ShowPlaceholderText()
{
if( mImpl->IsPlaceholderAvailable() )