const char * const PLACEHOLDER_POINT_SIZE = "pointSize";
const char * const PLACEHOLDER_PIXEL_SIZE = "pixelSize";
const char * const PLACEHOLDER_ELLIPSIS = "ellipsis";
+const unsigned int MAX_TEXT_LENGTH = 1024u * 32u;
float ConvertToEven( float value )
{
return static_cast<float>( intValue + ( intValue & 1 ) );
}
+int ConvertPixelToPint( float pixel )
+{
+ unsigned int horizontalDpi = 0u;
+ unsigned int verticalDpi = 0u;
+ Dali::TextAbstraction::FontClient fontClient = Dali::TextAbstraction::FontClient::Get();
+ fontClient.GetDpi( horizontalDpi, verticalDpi );
+
+ return ( pixel * 72.f ) / static_cast< float >( horizontalDpi );
+}
+
+
} // namespace
namespace Dali
void Controller::SetMaximumNumberOfCharacters( Length maxCharacters )
{
- mImpl->mMaximumNumberOfCharacters = maxCharacters;
+ mImpl->mMaximumNumberOfCharacters = std::min( maxCharacters, MAX_TEXT_LENGTH );
}
int Controller::GetMaximumNumberOfCharacters()
mImpl->mLayoutDirection = layoutDirection;
}
+bool Controller::IsShowingRealText() const
+{
+ return mImpl->IsShowingRealText();
+}
+
void Controller::SetLineWrapMode( Text::LineWrap::Mode lineWrapMode )
{
return mImpl->mModel->mElideEnabled;
}
+void Controller::SetTextFitEnabled(bool enabled)
+{
+ mImpl->mTextFitEnabled = enabled;
+}
+
+bool Controller::IsTextFitEnabled() const
+{
+ return mImpl->mTextFitEnabled;
+}
+
+void Controller::SetTextFitMinSize( float minSize, FontSizeType type )
+{
+ switch( type )
+ {
+ case POINT_SIZE:
+ {
+ mImpl->mTextFitMinSize = minSize;
+ break;
+ }
+ case PIXEL_SIZE:
+ {
+ mImpl->mTextFitMinSize = ConvertPixelToPint( minSize );
+ break;
+ }
+ }
+}
+
+float Controller::GetTextFitMinSize() const
+{
+ return mImpl->mTextFitMinSize;
+}
+
+void Controller::SetTextFitMaxSize( float maxSize, FontSizeType type )
+{
+ switch( type )
+ {
+ case POINT_SIZE:
+ {
+ mImpl->mTextFitMaxSize = maxSize;
+ break;
+ }
+ case PIXEL_SIZE:
+ {
+ mImpl->mTextFitMaxSize = ConvertPixelToPint( maxSize );
+ break;
+ }
+ }
+}
+
+float Controller::GetTextFitMaxSize() const
+{
+ return mImpl->mTextFitMaxSize;
+}
+
+void Controller::SetTextFitStepSize( float step, FontSizeType type )
+{
+ switch( type )
+ {
+ case POINT_SIZE:
+ {
+ mImpl->mTextFitStepSize = step;
+ break;
+ }
+ case PIXEL_SIZE:
+ {
+ mImpl->mTextFitStepSize = ConvertPixelToPint( step );
+ break;
+ }
+ }
+}
+
+float Controller::GetTextFitStepSize() const
+{
+ return mImpl->mTextFitStepSize;
+}
+
+void Controller::SetTextFitContentSize(Vector2 size)
+{
+ mImpl->mTextFitContentSize = size;
+}
+
+Vector2 Controller::GetTextFitContentSize() const
+{
+ return mImpl->mTextFitContentSize;
+}
+
void Controller::SetPlaceholderTextElideEnabled( bool enabled )
{
mImpl->mEventData->mIsPlaceholderElideEnabled = enabled;
return mImpl->mEventData->mGrabHandleEnabled;
}
+void Controller::SetGrabHandlePopupEnabled(bool enabled)
+{
+ mImpl->mEventData->mGrabHandlePopupEnabled = enabled;
+}
+
+bool Controller::IsGrabHandlePopupEnabled() const
+{
+ return mImpl->mEventData->mGrabHandlePopupEnabled;
+}
+
// public : Update
void Controller::SetText( const std::string& text )
utf8 = reinterpret_cast<const uint8_t*>( text.c_str() );
}
+ // Limit the text size. If the text size is too large, crash or deadlock will occur.
+ if( textSize > MAX_TEXT_LENGTH )
+ {
+ DALI_LOG_WARNING( "The text size is too large(%d), limit the length to 32,768u\n", textSize );
+ textSize = MAX_TEXT_LENGTH;
+ }
+
// Convert text into UTF-32
Vector<Character>& utf32Characters = mImpl->mModel->mLogicalModel->mText;
utf32Characters.Resize( textSize );
return naturalSize;
}
+bool Controller::CheckForTextFit( float pointSize, Size& layoutSize )
+{
+ Size textSize;
+ mImpl->mFontDefaults->mFitPointSize = pointSize;
+ mImpl->mFontDefaults->sizeDefined = true;
+ ClearFontData();
+
+ // Operations that can be done only once until the text changes.
+ const OperationsMask onlyOnceOperations = static_cast<OperationsMask>( CONVERT_TO_UTF32 |
+ GET_SCRIPTS |
+ VALIDATE_FONTS |
+ GET_LINE_BREAKS |
+ GET_WORD_BREAKS |
+ BIDI_INFO |
+ SHAPE_TEXT|
+ GET_GLYPH_METRICS );
+
+ mImpl->mTextUpdateInfo.mParagraphCharacterIndex = 0u;
+ mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters = mImpl->mModel->mLogicalModel->mText.Count();
+
+ // Make sure the model is up-to-date before layouting
+ mImpl->UpdateModel( onlyOnceOperations );
+
+ DoRelayout( Size( layoutSize.width, MAX_FLOAT ),
+ static_cast<OperationsMask>( onlyOnceOperations | LAYOUT),
+ textSize);
+
+ // Clear the update info. This info will be set the next time the text is updated.
+ mImpl->mTextUpdateInfo.Clear();
+ mImpl->mTextUpdateInfo.mClearAll = true;
+
+ if( textSize.width > layoutSize.width || textSize.height > layoutSize.height )
+ {
+ return false;
+ }
+ return true;
+}
+
+void Controller::FitPointSizeforLayout( Size layoutSize )
+{
+ bool actualellipsis = mImpl->mModel->mElideEnabled;
+ float minPointSize = mImpl->mTextFitMinSize;
+ float maxPointSize = mImpl->mTextFitMaxSize;
+ float pointInterval = mImpl->mTextFitStepSize;
+
+ mImpl->mModel->mElideEnabled = false;
+ Vector<float> pointSizeArray;
+
+ // check zero value
+ if( pointInterval < 1.f )
+ {
+ mImpl->mTextFitStepSize = pointInterval = 1.0f;
+ }
+
+ pointSizeArray.Reserve( static_cast< unsigned int >( ceil( ( maxPointSize - minPointSize ) / pointInterval ) ) );
+
+ for( float i = minPointSize; i < maxPointSize; i += pointInterval )
+ {
+ pointSizeArray.PushBack( i );
+ }
+
+ pointSizeArray.PushBack( maxPointSize );
+
+ int bestSizeIndex = 0;
+ int min = bestSizeIndex + 1;
+ int max = pointSizeArray.Size() - 1;
+ while( min <= max )
+ {
+ int destI = ( min + max ) / 2;
+
+ if( CheckForTextFit( pointSizeArray[destI], layoutSize ) )
+ {
+ bestSizeIndex = min;
+ min = destI + 1;
+ }
+ else
+ {
+ max = destI - 1;
+ bestSizeIndex = max;
+ }
+ }
+
+ mImpl->mModel->mElideEnabled = actualellipsis;
+ mImpl->mFontDefaults->mFitPointSize = pointSizeArray[bestSizeIndex];
+ mImpl->mFontDefaults->sizeDefined = true;
+ ClearFontData();
+}
+
float Controller::GetHeightForWidth( float width )
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::GetHeightForWidth %p width %f\n", this, width );
// This branch avoids calling the InsertText() method of the 'else' branch which can delete selected text.
}
- else if( Dali::DALI_KEY_SHIFT_LEFT == keyCode )
+ else if( ( Dali::DALI_KEY_SHIFT_LEFT == keyCode ) || ( Dali::DALI_KEY_SHIFT_RIGHT == keyCode ) )
{
- // DALI_KEY_SHIFT_LEFT is the key code for the Left Shift. It's sent (by the InputMethodContext?) when the predictive text is enabled
+ // DALI_KEY_SHIFT_LEFT or DALI_KEY_SHIFT_RIGHT is the key code for Shift. It's sent (by the InputMethodContext?) when the predictive text is enabled
// and a character is typed after the type of a upper case latin character.
// Do nothing.
( mImpl->mEventData->mState != EventData::INACTIVE ) &&
( !isNullKey ) &&
( Dali::DALI_KEY_SHIFT_LEFT != keyCode ) &&
+ ( Dali::DALI_KEY_SHIFT_RIGHT != keyCode ) &&
( Dali::DALI_KEY_VOLUME_UP != keyCode ) &&
( Dali::DALI_KEY_VOLUME_DOWN != keyCode ) )
{
}
}
+void Controller::SelectEvent( float x, float y, bool selectAll )
+{
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::SelectEvent\n" );
+
+ if( NULL != mImpl->mEventData )
+ {
+ if( selectAll )
+ {
+ Event event( Event::SELECT_ALL );
+ mImpl->mEventData->mEventQueue.push_back( event );
+ }
+ else
+ {
+ Event event( Event::SELECT );
+ event.p2.mFloat = x;
+ event.p3.mFloat = y;
+ mImpl->mEventData->mEventQueue.push_back( event );
+ }
+
+ mImpl->mEventData->mCheckScrollAmount = true;
+ mImpl->mEventData->mIsLeftHandleSelected = true;
+ mImpl->mEventData->mIsRightHandleSelected = true;
+ mImpl->RequestRelayout();
+ }
+}
+
InputMethodContext::CallbackData Controller::OnInputMethodContextEvent( InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent )
{
// Whether the text needs to be relaid-out.
mImpl->mOperationsPending = ALL_OPERATIONS;
}
-void Controller::SelectEvent( float x, float y, bool selectAll )
-{
- DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::SelectEvent\n" );
-
- if( NULL != mImpl->mEventData )
- {
- if( selectAll )
- {
- Event event( Event::SELECT_ALL );
- mImpl->mEventData->mEventQueue.push_back( event );
- }
- else
- {
- Event event( Event::SELECT );
- event.p2.mFloat = x;
- event.p3.mFloat = y;
- mImpl->mEventData->mEventQueue.push_back( event );
- }
-
- mImpl->mEventData->mCheckScrollAmount = true;
- mImpl->mEventData->mIsLeftHandleSelected = true;
- mImpl->mEventData->mIsRightHandleSelected = true;
- mImpl->RequestRelayout();
- }
-}
-
bool Controller::DeleteEvent( int keyCode )
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::KeyEvent %p KeyCode : %d \n", this, keyCode );