/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <dali/public-api/adaptor-framework/key.h>
#include <dali/integration-api/debug.h>
#include <dali/devel-api/adaptor-framework/clipboard-event-notifier.h>
+#include <dali/devel-api/text-abstraction/font-client.h>
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/bidirectional-support.h>
void Controller::EnableTextInput( DecoratorPtr decorator )
{
+ if( !decorator )
+ {
+ delete mImpl->mEventData;
+ mImpl->mEventData = NULL;
+
+ // Nothing else to do.
+ return;
+ }
+
if( NULL == mImpl->mEventData )
{
mImpl->mEventData = new EventData( decorator );
void Controller::SetAutoScrollEnabled( bool enable )
{
- DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled[%s] SingleBox[%s]-> [%p]\n", (enable)?"true":"false", ( mImpl->mLayoutEngine.GetLayout() == LayoutEngine::SINGLE_LINE_BOX)?"true":"false", this );
+ DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled[%s] SingleBox[%s]-> [%p]\n", (enable)?"true":"false", ( mImpl->mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX)?"true":"false", this );
- if ( mImpl->mLayoutEngine.GetLayout() == LayoutEngine::SINGLE_LINE_BOX )
+ if( mImpl->mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX )
{
- if ( enable )
+ if( enable )
{
DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled for SINGLE_LINE_BOX\n" );
mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending |
REORDER );
}
- mImpl->mAutoScrollEnabled = enable;
+ mImpl->mIsAutoScrollEnabled = enable;
mImpl->RequestRelayout();
}
else
{
DALI_LOG_WARNING( "Attempted AutoScrolling on a non SINGLE_LINE_BOX, request ignored\n" );
- mImpl->mAutoScrollEnabled = false;
+ mImpl->mIsAutoScrollEnabled = false;
}
}
bool Controller::IsAutoScrollEnabled() const
{
- DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::IsAutoScrollEnabled[%s]\n", (mImpl->mAutoScrollEnabled)?"true":"false" );
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::IsAutoScrollEnabled[%s]\n", mImpl->mIsAutoScrollEnabled?"true":"false" );
- return mImpl->mAutoScrollEnabled;
+ return mImpl->mIsAutoScrollEnabled;
}
CharacterDirection Controller::GetAutoScrollDirection() const
{
float offset = 0.f;
- if( mImpl->mVisualModel &&
- ( 0u != mImpl->mVisualModel->mLines.Count() ) )
+ if( mImpl->mModel->mVisualModel &&
+ ( 0u != mImpl->mModel->mVisualModel->mLines.Count() ) )
{
- offset = ( *mImpl->mVisualModel->mLines.Begin() ).alignmentOffset;
+ offset = ( *mImpl->mModel->mVisualModel->mLines.Begin() ).alignmentOffset;
}
return offset;
mImpl->mEventData->mDecorator->SetHorizontalScrollEnabled( enable );
}
}
-
bool Controller::IsHorizontalScrollEnabled() const
{
if( ( NULL != mImpl->mEventData ) &&
void Controller::SetMultiLineEnabled( bool enable )
{
- const LayoutEngine::Layout layout = enable ? LayoutEngine::MULTI_LINE_BOX : LayoutEngine::SINGLE_LINE_BOX;
+ const Layout::Engine::Type layout = enable ? Layout::Engine::MULTI_LINE_BOX : Layout::Engine::SINGLE_LINE_BOX;
if( layout != mImpl->mLayoutEngine.GetLayout() )
{
bool Controller::IsMultiLineEnabled() const
{
- return LayoutEngine::MULTI_LINE_BOX == mImpl->mLayoutEngine.GetLayout();
+ return Layout::Engine::MULTI_LINE_BOX == mImpl->mLayoutEngine.GetLayout();
}
-void Controller::SetHorizontalAlignment( LayoutEngine::HorizontalAlignment alignment )
+void Controller::SetHorizontalAlignment( Layout::HorizontalAlignment alignment )
{
- if( alignment != mImpl->mLayoutEngine.GetHorizontalAlignment() )
+ if( alignment != mImpl->mModel->mHorizontalAlignment )
{
// Set the alignment.
- mImpl->mLayoutEngine.SetHorizontalAlignment( alignment );
+ mImpl->mModel->mHorizontalAlignment = alignment;
// Set the flag to redo the alignment operation.
mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | ALIGN );
}
}
-LayoutEngine::HorizontalAlignment Controller::GetHorizontalAlignment() const
+Layout::HorizontalAlignment Controller::GetHorizontalAlignment() const
{
- return mImpl->mLayoutEngine.GetHorizontalAlignment();
+ return mImpl->mModel->mHorizontalAlignment;
}
-void Controller::SetVerticalAlignment( LayoutEngine::VerticalAlignment alignment )
+void Controller::SetVerticalAlignment( Layout::VerticalAlignment alignment )
{
- if( alignment != mImpl->mLayoutEngine.GetVerticalAlignment() )
+ if( alignment != mImpl->mModel->mVerticalAlignment )
{
// Set the alignment.
- mImpl->mLayoutEngine.SetVerticalAlignment( alignment );
+ mImpl->mModel->mVerticalAlignment = alignment;
mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | ALIGN );
}
}
-LayoutEngine::VerticalAlignment Controller::GetVerticalAlignment() const
+Layout::VerticalAlignment Controller::GetVerticalAlignment() const
+{
+ return mImpl->mModel->mVerticalAlignment;
+}
+
+void Controller::SetTextElideEnabled( bool enabled )
{
- return mImpl->mLayoutEngine.GetVerticalAlignment();
+ mImpl->mModel->mElideEnabled = enabled;
+}
+
+bool Controller::IsTextElideEnabled() const
+{
+ return mImpl->mModel->mElideEnabled;
}
// public : Update
if( !text.empty() )
{
- mImpl->mVisualModel->SetTextColor( mImpl->mTextColor );
+ mImpl->mModel->mVisualModel->SetTextColor( mImpl->mTextColor );
- MarkupProcessData markupProcessData( mImpl->mLogicalModel->mColorRuns,
- mImpl->mLogicalModel->mFontDescriptionRuns );
+ MarkupProcessData markupProcessData( mImpl->mModel->mLogicalModel->mColorRuns,
+ mImpl->mModel->mLogicalModel->mFontDescriptionRuns );
Length textSize = 0u;
const uint8_t* utf8 = NULL;
}
// Convert text into UTF-32
- Vector<Character>& utf32Characters = mImpl->mLogicalModel->mText;
+ Vector<Character>& utf32Characters = mImpl->mModel->mLogicalModel->mText;
utf32Characters.Resize( textSize );
// Transform a text array encoded in utf8 into an array encoded in utf32.
utf32Characters.Resize( characterCount );
DALI_ASSERT_DEBUG( textSize >= characterCount && "Invalid UTF32 conversion length" );
- DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::SetText %p UTF8 size %d, UTF32 size %d\n", this, textSize, mImpl->mLogicalModel->mText.Count() );
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::SetText %p UTF8 size %d, UTF32 size %d\n", this, textSize, mImpl->mModel->mLogicalModel->mText.Count() );
// The characters to be added.
- mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mLogicalModel->mText.Count();
+ mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mModel->mLogicalModel->mText.Count();
// To reset the cursor position
lastCursorIndex = characterCount;
}
}
+void Controller::SetPlaceholderText( const std::string& text )
+{
+ if( NULL != mImpl->mEventData )
+ {
+ mImpl->mEventData->mPlaceholderText = text;
+
+ // Update placeholder if there is no text
+ if( mImpl->IsShowingPlaceholderText() ||
+ ( 0u == mImpl->mModel->mLogicalModel->mText.Count() ) )
+ {
+ ShowPlaceholderText();
+ }
+ }
+}
+
+// This is overloading function for PLACEHOLDER_TEXT_FOCUSED in text-field
void Controller::SetPlaceholderText( PlaceholderType type, const std::string& text )
{
if( NULL != mImpl->mEventData )
// Update placeholder if there is no text
if( mImpl->IsShowingPlaceholderText() ||
- ( 0u == mImpl->mLogicalModel->mText.Count() ) )
+ ( 0u == mImpl->mModel->mLogicalModel->mText.Count() ) )
{
ShowPlaceholderText();
}
}
}
+void Controller::GetPlaceholderText( std::string& text ) const
+{
+ if( NULL != mImpl->mEventData )
+ {
+ text = mImpl->mEventData->mPlaceholderText;
+ }
+}
+
+// This is overloading function for PLACEHOLDER_TEXT_FOCUSED in text-field
void Controller::GetPlaceholderText( PlaceholderType type, std::string& text ) const
{
if( NULL != mImpl->mEventData )
return TextAbstraction::FontSlant::NORMAL;
}
-void Controller::SetDefaultPointSize( float pointSize )
+void Controller::SetDefaultFontSize( float fontSize, FontSizeType type )
{
if( NULL == mImpl->mFontDefaults )
{
mImpl->mFontDefaults = new FontDefaults();
}
- mImpl->mFontDefaults->mDefaultPointSize = pointSize;
- mImpl->mFontDefaults->sizeDefined = true;
+ switch( type )
+ {
+ case POINT_SIZE:
+ {
+ mImpl->mFontDefaults->mDefaultPointSize = fontSize;
+ mImpl->mFontDefaults->sizeDefined = true;
+ break;
+ }
+ case PIXEL_SIZE:
+ {
+ // Point size = Pixel size * 72 / DPI
+ unsigned int horizontalDpi = 0u;
+ unsigned int verticalDpi = 0u;
+ TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+ fontClient.GetDpi( horizontalDpi, verticalDpi );
+
+ mImpl->mFontDefaults->mDefaultPointSize = ( fontSize * 72 ) / horizontalDpi;
+ mImpl->mFontDefaults->sizeDefined = true;
+ break;
+ }
+ default:
+ {
+ DALI_ASSERT_ALWAYS( false );
+ }
+ }
// Clear the font-specific data
ClearFontData();
mImpl->RequestRelayout();
}
-float Controller::GetDefaultPointSize() const
+float Controller::GetDefaultFontSize( FontSizeType type ) const
{
+ float value = 0.0f;
if( NULL != mImpl->mFontDefaults )
{
- return mImpl->mFontDefaults->mDefaultPointSize;
+ switch( type )
+ {
+ case POINT_SIZE:
+ {
+ value = mImpl->mFontDefaults->mDefaultPointSize;
+ break;
+ }
+ case PIXEL_SIZE:
+ {
+ // Pixel size = Point size * DPI / 72
+ unsigned int horizontalDpi = 0u;
+ unsigned int verticalDpi = 0u;
+ TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+ fontClient.GetDpi( horizontalDpi, verticalDpi );
+
+ value = mImpl->mFontDefaults->mDefaultPointSize * horizontalDpi / 72;
+ break;
+ }
+ default:
+ {
+ DALI_ASSERT_ALWAYS( false );
+ }
+ }
+ return value;
}
- return 0.0f;
+ return value;
}
-void Controller::SetTextColor( const Vector4& textColor )
+void Controller::SetDefaultColor( const Vector4& color )
{
- mImpl->mTextColor = textColor;
+ mImpl->mTextColor = color;
if( !mImpl->IsShowingPlaceholderText() )
{
- mImpl->mVisualModel->SetTextColor( textColor );
+ mImpl->mModel->mVisualModel->SetTextColor( color );
mImpl->RequestRelayout();
}
}
-const Vector4& Controller::GetTextColor() const
+const Vector4& Controller::GetDefaultColor() const
{
return mImpl->mTextColor;
}
if( mImpl->IsShowingPlaceholderText() )
{
- mImpl->mVisualModel->SetTextColor( textColor );
+ mImpl->mModel->mVisualModel->SetTextColor( textColor );
mImpl->RequestRelayout();
}
}
void Controller::SetShadowOffset( const Vector2& shadowOffset )
{
- mImpl->mVisualModel->SetShadowOffset( shadowOffset );
+ mImpl->mModel->mVisualModel->SetShadowOffset( shadowOffset );
mImpl->RequestRelayout();
}
const Vector2& Controller::GetShadowOffset() const
{
- return mImpl->mVisualModel->GetShadowOffset();
+ return mImpl->mModel->mVisualModel->GetShadowOffset();
}
void Controller::SetShadowColor( const Vector4& shadowColor )
{
- mImpl->mVisualModel->SetShadowColor( shadowColor );
+ mImpl->mModel->mVisualModel->SetShadowColor( shadowColor );
mImpl->RequestRelayout();
}
const Vector4& Controller::GetShadowColor() const
{
- return mImpl->mVisualModel->GetShadowColor();
-}
-
-void Controller::SetDefaultShadowProperties( const std::string& shadowProperties )
-{
- if( NULL == mImpl->mShadowDefaults )
- {
- mImpl->mShadowDefaults = new ShadowDefaults();
- }
-
- mImpl->mShadowDefaults->properties = shadowProperties;
-}
-
-const std::string& Controller::GetDefaultShadowProperties() const
-{
- if( NULL != mImpl->mShadowDefaults )
- {
- return mImpl->mShadowDefaults->properties;
- }
-
- return EMPTY_STRING;
+ return mImpl->mModel->mVisualModel->GetShadowColor();
}
void Controller::SetUnderlineColor( const Vector4& color )
{
- mImpl->mVisualModel->SetUnderlineColor( color );
+ mImpl->mModel->mVisualModel->SetUnderlineColor( color );
mImpl->RequestRelayout();
}
const Vector4& Controller::GetUnderlineColor() const
{
- return mImpl->mVisualModel->GetUnderlineColor();
+ return mImpl->mModel->mVisualModel->GetUnderlineColor();
}
void Controller::SetUnderlineEnabled( bool enabled )
{
- mImpl->mVisualModel->SetUnderlineEnabled( enabled );
+ mImpl->mModel->mVisualModel->SetUnderlineEnabled( enabled );
mImpl->RequestRelayout();
}
bool Controller::IsUnderlineEnabled() const
{
- return mImpl->mVisualModel->IsUnderlineEnabled();
+ return mImpl->mModel->mVisualModel->IsUnderlineEnabled();
}
void Controller::SetUnderlineHeight( float height )
{
- mImpl->mVisualModel->SetUnderlineHeight( height );
+ mImpl->mModel->mVisualModel->SetUnderlineHeight( height );
mImpl->RequestRelayout();
}
float Controller::GetUnderlineHeight() const
{
- return mImpl->mVisualModel->GetUnderlineHeight();
-}
-
-void Controller::SetDefaultUnderlineProperties( const std::string& underlineProperties )
-{
- if( NULL == mImpl->mUnderlineDefaults )
- {
- mImpl->mUnderlineDefaults = new UnderlineDefaults();
- }
-
- mImpl->mUnderlineDefaults->properties = underlineProperties;
-}
-
-const std::string& Controller::GetDefaultUnderlineProperties() const
-{
- if( NULL != mImpl->mUnderlineDefaults )
- {
- return mImpl->mUnderlineDefaults->properties;
- }
-
- return EMPTY_STRING;
+ return mImpl->mModel->mVisualModel->GetUnderlineHeight();
}
void Controller::SetDefaultEmbossProperties( const std::string& embossProperties )
const Length lengthOfSelectedText = ( handlesCrossed ? mImpl->mEventData->mLeftSelectionPosition : mImpl->mEventData->mRightSelectionPosition ) - startOfSelectedText;
// Add the color run.
- const VectorBase::SizeType numberOfRuns = mImpl->mLogicalModel->mColorRuns.Count();
- mImpl->mLogicalModel->mColorRuns.Resize( numberOfRuns + 1u );
+ const VectorBase::SizeType numberOfRuns = mImpl->mModel->mLogicalModel->mColorRuns.Count();
+ mImpl->mModel->mLogicalModel->mColorRuns.Resize( numberOfRuns + 1u );
- ColorRun& colorRun = *( mImpl->mLogicalModel->mColorRuns.Begin() + numberOfRuns );
+ ColorRun& colorRun = *( mImpl->mModel->mLogicalModel->mColorRuns.Begin() + numberOfRuns );
colorRun.color = color;
colorRun.characterRun.characterIndex = startOfSelectedText;
colorRun.characterRun.numberOfCharacters = lengthOfSelectedText;
CharacterIndex startOfSelectedText = 0u;
Length lengthOfSelectedText = 0u;
FontDescriptionRun& fontDescriptionRun = UpdateSelectionFontStyleRun( mImpl->mEventData,
- mImpl->mLogicalModel,
+ mImpl->mModel->mLogicalModel,
startOfSelectedText,
lengthOfSelectedText );
CharacterIndex startOfSelectedText = 0u;
Length lengthOfSelectedText = 0u;
FontDescriptionRun& fontDescriptionRun = UpdateSelectionFontStyleRun( mImpl->mEventData,
- mImpl->mLogicalModel,
+ mImpl->mModel->mLogicalModel,
startOfSelectedText,
lengthOfSelectedText );
CharacterIndex startOfSelectedText = 0u;
Length lengthOfSelectedText = 0u;
FontDescriptionRun& fontDescriptionRun = UpdateSelectionFontStyleRun( mImpl->mEventData,
- mImpl->mLogicalModel,
+ mImpl->mModel->mLogicalModel,
startOfSelectedText,
lengthOfSelectedText );
CharacterIndex startOfSelectedText = 0u;
Length lengthOfSelectedText = 0u;
FontDescriptionRun& fontDescriptionRun = UpdateSelectionFontStyleRun( mImpl->mEventData,
- mImpl->mLogicalModel,
+ mImpl->mModel->mLogicalModel,
startOfSelectedText,
lengthOfSelectedText );
CharacterIndex startOfSelectedText = 0u;
Length lengthOfSelectedText = 0u;
FontDescriptionRun& fontDescriptionRun = UpdateSelectionFontStyleRun( mImpl->mEventData,
- mImpl->mLogicalModel,
+ mImpl->mModel->mLogicalModel,
startOfSelectedText,
lengthOfSelectedText );
}
// Return the default font's point size if there is no EventData.
- return GetDefaultPointSize();
+ return GetDefaultFontSize( Text::Controller::POINT_SIZE );
}
void Controller::SetInputLineSpacing( float lineSpacing )
return mImpl->mEventData->mInputStyle.shadowProperties;
}
- return GetDefaultShadowProperties();
+ return EMPTY_STRING;
}
void Controller::SetInputUnderlineProperties( const std::string& underlineProperties )
return mImpl->mEventData->mInputStyle.underlineProperties;
}
- return GetDefaultUnderlineProperties();
+ return EMPTY_STRING;
}
void Controller::SetInputEmbossProperties( const std::string& embossProperties )
return GetDefaultOutlineProperties();
}
+void Controller::SetInputModePassword( bool passwordInput )
+{
+ if( NULL != mImpl->mEventData )
+ {
+ mImpl->mEventData->mPasswordInput = passwordInput;
+ }
+}
+
+bool Controller::IsInputModePassword()
+{
+ if( NULL != mImpl->mEventData )
+ {
+ return mImpl->mEventData->mPasswordInput;
+ }
+ return false;
+}
+
+void Controller::SetNoTextDoubleTapAction( NoTextTap::Action action )
+{
+ if( NULL != mImpl->mEventData )
+ {
+ mImpl->mEventData->mDoubleTapAction = action;
+ }
+}
+
+Controller::NoTextTap::Action Controller::GetNoTextDoubleTapAction() const
+{
+ NoTextTap::Action action = NoTextTap::NO_ACTION;
+
+ if( NULL != mImpl->mEventData )
+ {
+ action = mImpl->mEventData->mDoubleTapAction;
+ }
+
+ return action;
+}
+
+void Controller::SetNoTextLongPressAction( NoTextTap::Action action )
+{
+ if( NULL != mImpl->mEventData )
+ {
+ mImpl->mEventData->mLongPressAction = action;
+ }
+}
+
+Controller::NoTextTap::Action Controller::GetNoTextLongPressAction() const
+{
+ NoTextTap::Action action = NoTextTap::NO_ACTION;
+
+ if( NULL != mImpl->mEventData )
+ {
+ action = mImpl->mEventData->mLongPressAction;
+ }
+
+ return action;
+}
+
+bool Controller::IsUnderlineSetByString()
+{
+ return mImpl->mUnderlineSetByString;
+}
+
+void Controller::UnderlineSetByString( bool setByString )
+{
+ mImpl->mUnderlineSetByString = setByString;
+}
+
+bool Controller::IsShadowSetByString()
+{
+ return mImpl->mShadowSetByString;
+}
+
+void Controller::ShadowSetByString( bool setByString )
+{
+ mImpl->mShadowSetByString = setByString;
+}
+
+bool Controller::IsFontStyleSetByString()
+{
+ return mImpl->mFontStyleSetByString;
+}
+
+void Controller::FontStyleSetByString( bool setByString )
+{
+ mImpl->mFontStyleSetByString = setByString;
+}
+
// public : Queries & retrieves.
-LayoutEngine& Controller::GetLayoutEngine()
+Layout::Engine& Controller::GetLayoutEngine()
{
return mImpl->mLayoutEngine;
}
return mImpl->mView;
}
-const Vector2& Controller::GetScrollPosition() const
-{
- return mImpl->mScrollPosition;
-}
-
Vector3 Controller::GetNaturalSize()
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::GetNaturalSize\n" );
BIDI_INFO |
SHAPE_TEXT |
GET_GLYPH_METRICS );
+
+ // Set the update info to relayout the whole text.
+ 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 );
// Layout the text for the new width.
mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | LAYOUT );
- // Set the update info to relayout the whole text.
- mImpl->mTextUpdateInfo.mParagraphCharacterIndex = 0u;
- mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters = mImpl->mLogicalModel->mText.Count();
-
// Store the actual control's size to restore later.
- const Size actualControlSize = mImpl->mVisualModel->mControlSize;
+ const Size actualControlSize = mImpl->mModel->mVisualModel->mControlSize;
DoRelayout( Size( MAX_FLOAT, MAX_FLOAT ),
static_cast<OperationsMask>( onlyOnceOperations |
// Stores the natural size to avoid recalculate it again
// unless the text/style changes.
- mImpl->mVisualModel->SetNaturalSize( naturalSize.GetVectorXY() );
+ mImpl->mModel->mVisualModel->SetNaturalSize( naturalSize.GetVectorXY() );
mImpl->mRecalculateNaturalSize = false;
mImpl->mTextUpdateInfo.Clear();
// Restore the actual control's size.
- mImpl->mVisualModel->mControlSize = actualControlSize;
+ mImpl->mModel->mVisualModel->mControlSize = actualControlSize;
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize calculated %f,%f,%f\n", naturalSize.x, naturalSize.y, naturalSize.z );
}
else
{
- naturalSize = mImpl->mVisualModel->GetNaturalSize();
+ naturalSize = mImpl->mModel->mVisualModel->GetNaturalSize();
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize cached %f,%f,%f\n", naturalSize.x, naturalSize.y, naturalSize.z );
}
ProcessModifyEvents();
Size layoutSize;
- if( fabsf( width - mImpl->mVisualModel->mControlSize.width ) > Math::MACHINE_EPSILON_1000 )
+ if( fabsf( width - mImpl->mModel->mVisualModel->mControlSize.width ) > Math::MACHINE_EPSILON_1000 )
{
// Operations that can be done only once until the text changes.
const OperationsMask onlyOnceOperations = static_cast<OperationsMask>( CONVERT_TO_UTF32 |
BIDI_INFO |
SHAPE_TEXT |
GET_GLYPH_METRICS );
+
+ // Set the update info to relayout the whole text.
+ 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 );
// Layout the text for the new width.
mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | LAYOUT );
- // Set the update info to relayout the whole text.
- mImpl->mTextUpdateInfo.mParagraphCharacterIndex = 0u;
- mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters = mImpl->mLogicalModel->mText.Count();
-
// Store the actual control's width.
- const float actualControlWidth = mImpl->mVisualModel->mControlSize.width;
+ const float actualControlWidth = mImpl->mModel->mVisualModel->mControlSize.width;
DoRelayout( Size( width, MAX_FLOAT ),
static_cast<OperationsMask>( onlyOnceOperations |
mImpl->mTextUpdateInfo.Clear();
// Restore the actual control's width.
- mImpl->mVisualModel->mControlSize.width = actualControlWidth;
+ mImpl->mModel->mVisualModel->mControlSize.width = actualControlWidth;
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth calculated %f\n", layoutSize.height );
}
else
{
- layoutSize = mImpl->mVisualModel->GetLayoutSize();
+ layoutSize = mImpl->mModel->mVisualModel->GetLayoutSize();
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth cached %f\n", layoutSize.height );
}
return layoutSize.height;
}
+int Controller::GetLineCount( float width )
+{
+ GetHeightForWidth( width );
+ int numberofLines = mImpl->mModel->GetNumberOfLines();
+ return numberofLines;
+}
+
+const ModelInterface* const Controller::GetTextModel() const
+{
+ return mImpl->mModel.Get();
+}
+
+float Controller::GetScrollAmountByUserInput()
+{
+ float scrollAmount = 0.0f;
+
+ if (NULL != mImpl->mEventData && mImpl->mEventData->mCheckScrollAmount)
+ {
+ scrollAmount = mImpl->mModel->mScrollPosition.y - mImpl->mModel->mScrollPositionLast.y;
+ mImpl->mEventData->mCheckScrollAmount = false;
+ }
+ return scrollAmount;
+}
+
+bool Controller::GetTextScrollInfo( float& scrollPosition, float& controlHeight, float& layoutHeight )
+{
+ const Vector2& layout = mImpl->mModel->mVisualModel->GetLayoutSize();
+ bool isScrolled;
+
+ controlHeight = mImpl->mModel->mVisualModel->mControlSize.height;
+ layoutHeight = layout.height;
+ scrollPosition = mImpl->mModel->mScrollPosition.y;
+ isScrolled = !Equals( mImpl->mModel->mScrollPosition.y, mImpl->mModel->mScrollPositionLast.y, Math::MACHINE_EPSILON_1 );
+ return isScrolled;
+}
+
+void Controller::SetHiddenInputOption(const Property::Map& options )
+{
+ if( NULL == mImpl->mHiddenInput )
+ {
+ mImpl->mHiddenInput = new HiddenText( this );
+ }
+ mImpl->mHiddenInput->SetProperties(options);
+}
+
+void Controller::GetHiddenInputOption(Property::Map& options )
+{
+ if( NULL != mImpl->mHiddenInput )
+ {
+ mImpl->mHiddenInput->GetProperties(options);
+ }
+}
+
// public : Relayout.
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" );
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::Relayout %p size %f,%f, autoScroll[%s]\n", this, size.width, size.height, mImpl->mIsAutoScrollEnabled ?"true":"false" );
UpdateTextType updateTextType = NONE_UPDATED;
if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) )
{
- if( 0u != mImpl->mVisualModel->mGlyphPositions.Count() )
+ if( 0u != mImpl->mModel->mVisualModel->mGlyphPositions.Count() )
{
- mImpl->mVisualModel->mGlyphPositions.Clear();
+ mImpl->mModel->mVisualModel->mGlyphPositions.Clear();
updateTextType = MODEL_UPDATED;
}
}
// Whether a new size has been set.
- const bool newSize = ( size != mImpl->mVisualModel->mControlSize );
+ const bool newSize = ( size != mImpl->mModel->mVisualModel->mControlSize );
if( newSize )
{
- DALI_LOG_INFO( gLogFilter, Debug::Verbose, "new size (previous size %f,%f)\n", mImpl->mVisualModel->mControlSize.width, mImpl->mVisualModel->mControlSize.height );
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "new size (previous size %f,%f)\n", mImpl->mModel->mVisualModel->mControlSize.width, mImpl->mModel->mVisualModel->mControlSize.height );
// Layout operations that need to be done if the size changes.
mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending |
// Set the update info to relayout the whole text.
mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
+
+ // Store the size used to layout the text.
+ mImpl->mModel->mVisualModel->mControlSize = size;
}
// Whether there are modify events.
// Do not re-do any operation until something changes.
mImpl->mOperationsPending = NO_OPERATION;
+ mImpl->mModel->mScrollPositionLast = mImpl->mModel->mScrollPosition;
// Whether the text control is editable
const bool isEditable = NULL != mImpl->mEventData;
Vector2 offset;
if( newSize && isEditable )
{
- offset = mImpl->mScrollPosition;
+ offset = mImpl->mModel->mScrollPosition;
}
if( !isEditable || !IsMultiLineEnabled() )
mImpl->ClampHorizontalScroll( layoutSize );
// Update the decorator's positions is needed if there is a new size.
- mImpl->mEventData->mDecorator->UpdatePositions( mImpl->mScrollPosition - offset );
+ mImpl->mEventData->mDecorator->UpdatePositions( mImpl->mModel->mScrollPosition - offset );
}
// Move the cursor, grab handle etc.
return updateTextType;
}
+void Controller::RequestRelayout()
+{
+ mImpl->RequestRelayout();
+}
+
// public : Input style change signals.
bool Controller::IsInputStyleChangedSignalsQueueEmpty()
{
mImpl->ChangeState( EventData::EDITING );
mImpl->mEventData->mUpdateCursorPosition = true; //If editing started without tap event, cursor update must be triggered.
+ mImpl->mEventData->mUpdateInputStyle = true;
}
mImpl->NotifyImfMultiLineStatus();
if( mImpl->IsShowingPlaceholderText() )
{
DALI_ASSERT_DEBUG( mImpl->mEventData && "Unexpected KeyEvent" );
- bool textChanged( false );
+ bool textChanged = false;
+ bool relayoutNeeded = false;
if( ( NULL != mImpl->mEventData ) &&
( keyEvent.state == KeyEvent::Down ) )
int keyCode = keyEvent.keyCode;
const std::string& keyString = keyEvent.keyPressed;
+ const bool isNullKey = ( 0 == keyCode ) && ( keyString.empty() );
+
// Pre-process to separate modifying events from non-modifying input events.
- if( Dali::DALI_KEY_ESCAPE == keyCode )
+ if( isNullKey )
+ {
+ // In some platforms arrive key events with no key code.
+ // Do nothing.
+ }
+ else if( Dali::DALI_KEY_ESCAPE == keyCode )
{
// Escape key is a special case which causes focus loss
KeyboardFocusLostEvent();
+
+ // Will request for relayout.
+ relayoutNeeded = true;
}
else if( ( Dali::DALI_KEY_CURSOR_LEFT == keyCode ) ||
( Dali::DALI_KEY_CURSOR_RIGHT == keyCode ) ||
( Dali::DALI_KEY_CURSOR_UP == keyCode ) ||
( Dali::DALI_KEY_CURSOR_DOWN == keyCode ) )
{
+ // If don't have any text, do nothing.
+ if( !mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters )
+ {
+ return false;
+ }
+
+ uint32_t cursorPosition = mImpl->mEventData->mPrimaryCursorPosition;
+ uint32_t numberOfCharacters = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
+ uint32_t cursorLine = mImpl->mModel->mVisualModel->GetLineOfCharacter( cursorPosition );
+ uint32_t numberOfLines = mImpl->mModel->GetNumberOfLines();
+
+ // Logic to determine whether this text control will lose focus or not.
+ if( ( Dali::DALI_KEY_CURSOR_LEFT == keyCode && 0 == cursorPosition ) ||
+ ( Dali::DALI_KEY_CURSOR_RIGHT == keyCode && numberOfCharacters == cursorPosition) ||
+ ( Dali::DALI_KEY_CURSOR_DOWN == keyCode && cursorLine == numberOfLines -1 ) ||
+ ( Dali::DALI_KEY_CURSOR_DOWN == keyCode && numberOfCharacters == cursorPosition && cursorLine -1 == numberOfLines -1 ) ||
+ ( Dali::DALI_KEY_CURSOR_UP == keyCode && cursorLine == 0 ) ||
+ ( Dali::DALI_KEY_CURSOR_UP == keyCode && numberOfCharacters == cursorPosition && cursorLine == 1 ) )
+ {
+ return false;
+ }
+
+ mImpl->mEventData->mCheckScrollAmount = true;
Event event( Event::CURSOR_KEY_EVENT );
event.p1.mInt = keyCode;
mImpl->mEventData->mEventQueue.push_back( event );
+
+ // Will request for relayout.
+ relayoutNeeded = true;
}
else if( Dali::DALI_KEY_BACKSPACE == keyCode )
{
textChanged = BackspaceKeyEvent();
+
+ // Will request for relayout.
+ relayoutNeeded = true;
}
- else if( IsKey( keyEvent, Dali::DALI_KEY_POWER ) )
- {
- mImpl->ChangeState( EventData::INTERRUPTED ); // State is not INACTIVE as expect to return to edit mode.
- // Avoids calling the InsertText() method which can delete selected text
- }
- else if( IsKey( keyEvent, Dali::DALI_KEY_MENU ) ||
+ else if( IsKey( keyEvent, Dali::DALI_KEY_POWER ) ||
+ IsKey( keyEvent, Dali::DALI_KEY_MENU ) ||
IsKey( keyEvent, Dali::DALI_KEY_HOME ) )
{
+ // Power key/Menu/Home key behaviour does not allow edit mode to resume.
mImpl->ChangeState( EventData::INACTIVE );
- // Menu/Home key behaviour does not allow edit mode to resume like Power key
- // Avoids calling the InsertText() method which can delete selected text
+
+ // Will request for relayout.
+ relayoutNeeded = true;
+
+ // This branch avoids calling the InsertText() method of the 'else' branch which can delete selected text.
}
else if( Dali::DALI_KEY_SHIFT_LEFT == keyCode )
{
// Do nothing.
}
+ else if( ( Dali::DALI_KEY_VOLUME_UP == keyCode ) || ( Dali::DALI_KEY_VOLUME_DOWN == keyCode ) )
+ {
+ // This branch avoids calling the InsertText() method of the 'else' branch which can delete selected text.
+ // Do nothing.
+ }
else
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::KeyEvent %p keyString %s\n", this, keyString.c_str() );
InsertText( keyString, COMMIT );
textChanged = true;
+
+ // Will request for relayout.
+ relayoutNeeded = true;
}
if ( ( mImpl->mEventData->mState != EventData::INTERRUPTED ) &&
( mImpl->mEventData->mState != EventData::INACTIVE ) &&
- ( Dali::DALI_KEY_SHIFT_LEFT != keyCode ) )
+ ( !isNullKey ) &&
+ ( Dali::DALI_KEY_SHIFT_LEFT != keyCode ) &&
+ ( Dali::DALI_KEY_VOLUME_UP != keyCode ) &&
+ ( Dali::DALI_KEY_VOLUME_DOWN != 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 );
+
+ // Will request for relayout.
+ relayoutNeeded = true;
}
- mImpl->RequestRelayout();
+ if( relayoutNeeded )
+ {
+ mImpl->RequestRelayout();
+ }
}
if( textChanged &&
if( mImpl->mEventData->mSelectionEnabled &&
mImpl->IsShowingRealText() )
{
- SelectEvent( x, y, false );
+ relayoutNeeded = true;
+ mImpl->mEventData->mIsLeftHandleSelected = true;
+ mImpl->mEventData->mIsRightHandleSelected = true;
}
}
+
// Handles & cursors must be repositioned after Relayout() i.e. after the Model has been updated
if( relayoutNeeded )
{
if( ( state == Gesture::Started ) &&
( NULL != mImpl->mEventData ) )
{
- if( !mImpl->IsShowingRealText() )
+ // 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 if( !mImpl->IsShowingRealText() )
{
Event event( Event::LONG_PRESS_EVENT );
event.p1.mInt = state;
+ event.p2.mFloat = x;
+ event.p3.mFloat = y;
mImpl->mEventData->mEventQueue.push_back( event );
mImpl->RequestRelayout();
}
- else
+ else if( !mImpl->IsClipboardVisible() )
{
- // 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 );
+ // Reset the imf manager to commit the pre-edit before selecting the text.
+ mImpl->ResetImfManager();
- mImpl->RequestRelayout();
- }
- else if( !mImpl->IsClipboardVisible() )
- {
- // Reset the imf manger to commit the pre-edit before selecting the text.
- mImpl->ResetImfManager();
+ Event event( Event::LONG_PRESS_EVENT );
+ event.p1.mInt = state;
+ event.p2.mFloat = x;
+ event.p3.mFloat = y;
+ mImpl->mEventData->mEventQueue.push_back( event );
+ mImpl->RequestRelayout();
- SelectEvent( x, y, false );
- }
+ mImpl->mEventData->mIsLeftHandleSelected = true;
+ mImpl->mEventData->mIsRightHandleSelected = true;
}
}
}
if( textDeleted )
{
- if( ( 0u != mImpl->mLogicalModel->mText.Count() ) ||
+ if( ( 0u != mImpl->mModel->mLogicalModel->mText.Count() ) ||
!mImpl->IsPlaceholderAvailable() )
{
mImpl->QueueModifyEvent( ModifyEvent::TEXT_DELETED );
retrieveCursor = true;
break;
}
+ case ImfManager::PRIVATECOMMAND:
+ {
+ // PRIVATECOMMAND event is just for getting the private command message
+ retrieveText = true;
+ retrieveCursor = true;
+ break;
+ }
case ImfManager::VOID:
{
// do nothing
void Controller::GetTargetSize( Vector2& targetSize )
{
- targetSize = mImpl->mVisualModel->mControlSize;
+ targetSize = mImpl->mModel->mVisualModel->mControlSize;
}
void Controller::AddDecoration( Actor& actor, bool needsClipping )
mImpl->SendSelectionToClipboard( true ); // Synchronous call to modify text
mImpl->mOperationsPending = ALL_OPERATIONS;
- if( ( 0u != mImpl->mLogicalModel->mText.Count() ) ||
+ if( ( 0u != mImpl->mModel->mLogicalModel->mText.Count() ) ||
!mImpl->IsPlaceholderAvailable() )
{
mImpl->QueueModifyEvent( ModifyEvent::TEXT_DELETED );
}
}
+void Controller::DisplayTimeExpired()
+{
+ mImpl->mEventData->mUpdateCursorPosition = true;
+ // Apply modifications to the model
+ mImpl->mOperationsPending = ALL_OPERATIONS;
+
+ mImpl->RequestRelayout();
+}
+
// private : Update.
void Controller::InsertText( const std::string& text, Controller::InsertType type )
{
- bool removedPrevious( false );
- bool maxLengthReached( false );
+ bool removedPrevious = false;
+ bool removedSelected = false;
+ bool maxLengthReached = false;
DALI_ASSERT_DEBUG( NULL != mImpl->mEventData && "Unexpected InsertText" )
mImpl->mEventData->mPrimaryCursorPosition, mImpl->mEventData->mPreEditFlag, mImpl->mEventData->mPreEditStartPosition, mImpl->mEventData->mPreEditLength );
// TODO: At the moment the underline runs are only for pre-edit.
- mImpl->mVisualModel->mUnderlineRuns.Clear();
-
- // Keep the current number of characters.
- const Length currentNumberOfCharacters = mImpl->IsShowingRealText() ? mImpl->mLogicalModel->mText.Count() : 0u;
+ mImpl->mModel->mVisualModel->mUnderlineRuns.Clear();
// Remove the previous IMF pre-edit.
if( mImpl->mEventData->mPreEditFlag && ( 0u != mImpl->mEventData->mPreEditLength ) )
else
{
// Remove the previous Selection.
- removedPrevious = RemoveSelectedText();
+ removedSelected = RemoveSelectedText();
+
}
Vector<Character> utf32Characters;
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "mPreEditStartPosition %d mPreEditLength %d\n", mImpl->mEventData->mPreEditStartPosition, mImpl->mEventData->mPreEditLength );
}
- const Length numberOfCharactersInModel = mImpl->mLogicalModel->mText.Count();
+ const Length numberOfCharactersInModel = mImpl->mModel->mLogicalModel->mText.Count();
// Restrict new text to fit within Maximum characters setting.
Length maxSizeOfNewText = std::min( ( mImpl->mMaximumNumberOfCharacters - numberOfCharactersInModel ), characterCount );
// Update the text's style.
// Updates the text style runs by adding characters.
- mImpl->mLogicalModel->UpdateTextStyleRuns( cursorIndex, maxSizeOfNewText );
+ mImpl->mModel->mLogicalModel->UpdateTextStyleRuns( cursorIndex, maxSizeOfNewText );
// Get the character index from the cursor index.
const CharacterIndex styleIndex = ( cursorIndex > 0u ) ? cursorIndex - 1u : 0u;
// Retrieve the text's style for the given index.
InputStyle style;
mImpl->RetrieveDefaultInputStyle( style );
- mImpl->mLogicalModel->RetrieveStyle( styleIndex, style );
+ mImpl->mModel->mLogicalModel->RetrieveStyle( styleIndex, style );
// Whether to add a new text color run.
const bool addColorRun = ( style.textColor != mImpl->mEventData->mInputStyle.textColor );
// Add style runs.
if( addColorRun )
{
- const VectorBase::SizeType numberOfRuns = mImpl->mLogicalModel->mColorRuns.Count();
- mImpl->mLogicalModel->mColorRuns.Resize( numberOfRuns + 1u );
+ const VectorBase::SizeType numberOfRuns = mImpl->mModel->mLogicalModel->mColorRuns.Count();
+ mImpl->mModel->mLogicalModel->mColorRuns.Resize( numberOfRuns + 1u );
- ColorRun& colorRun = *( mImpl->mLogicalModel->mColorRuns.Begin() + numberOfRuns );
+ ColorRun& colorRun = *( mImpl->mModel->mLogicalModel->mColorRuns.Begin() + numberOfRuns );
colorRun.color = mImpl->mEventData->mInputStyle.textColor;
colorRun.characterRun.characterIndex = cursorIndex;
colorRun.characterRun.numberOfCharacters = maxSizeOfNewText;
addFontSlantRun ||
addFontSizeRun )
{
- const VectorBase::SizeType numberOfRuns = mImpl->mLogicalModel->mFontDescriptionRuns.Count();
- mImpl->mLogicalModel->mFontDescriptionRuns.Resize( numberOfRuns + 1u );
+ const VectorBase::SizeType numberOfRuns = mImpl->mModel->mLogicalModel->mFontDescriptionRuns.Count();
+ mImpl->mModel->mLogicalModel->mFontDescriptionRuns.Resize( numberOfRuns + 1u );
- FontDescriptionRun& fontDescriptionRun = *( mImpl->mLogicalModel->mFontDescriptionRuns.Begin() + numberOfRuns );
+ FontDescriptionRun& fontDescriptionRun = *( mImpl->mModel->mLogicalModel->mFontDescriptionRuns.Begin() + numberOfRuns );
if( addFontNameRun )
{
}
// Insert at current cursor position.
- Vector<Character>& modifyText = mImpl->mLogicalModel->mText;
+ Vector<Character>& modifyText = mImpl->mModel->mLogicalModel->mText;
if( cursorIndex < numberOfCharactersInModel )
{
// Update the cursor index.
cursorIndex += maxSizeOfNewText;
- DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Inserted %d characters, new size %d new cursor %d\n", maxSizeOfNewText, mImpl->mLogicalModel->mText.Count(), mImpl->mEventData->mPrimaryCursorPosition );
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Inserted %d characters, new size %d new cursor %d\n", maxSizeOfNewText, mImpl->mModel->mLogicalModel->mText.Count(), mImpl->mEventData->mPrimaryCursorPosition );
}
- const Length numberOfCharacters = mImpl->IsShowingRealText() ? mImpl->mLogicalModel->mText.Count() : 0u;
-
- if( ( 0u == mImpl->mLogicalModel->mText.Count() ) &&
+ if( ( 0u == mImpl->mModel->mLogicalModel->mText.Count() ) &&
mImpl->IsPlaceholderAvailable() )
{
// Show place-holder if empty after removing the pre-edit text
mImpl->ClearPreEditFlag();
}
else if( removedPrevious ||
+ removedSelected ||
( 0 != utf32Characters.Count() ) )
{
// Queue an inserted event
mImpl->QueueModifyEvent( ModifyEvent::TEXT_INSERTED );
mImpl->mEventData->mUpdateCursorPosition = true;
- if( numberOfCharacters < currentNumberOfCharacters )
+ if( removedSelected )
{
mImpl->mEventData->mScrollAfterDelete = true;
}
if( maxLengthReached )
{
- DALI_LOG_INFO( gLogFilter, Debug::Verbose, "MaxLengthReached (%d)\n", mImpl->mLogicalModel->mText.Count() );
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "MaxLengthReached (%d)\n", mImpl->mModel->mLogicalModel->mText.Count() );
mImpl->ResetImfManager();
}
DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::RemoveText %p mText.Count() %d cursor %d cursorOffset %d numberOfCharacters %d\n",
- this, mImpl->mLogicalModel->mText.Count(), mImpl->mEventData->mPrimaryCursorPosition, cursorOffset, numberOfCharacters );
+ this, mImpl->mModel->mLogicalModel->mText.Count(), mImpl->mEventData->mPrimaryCursorPosition, cursorOffset, numberOfCharacters );
if( !mImpl->IsShowingPlaceholderText() )
{
// Delete at current cursor position
- Vector<Character>& currentText = mImpl->mLogicalModel->mText;
+ Vector<Character>& currentText = mImpl->mModel->mLogicalModel->mText;
CharacterIndex& oldCursorIndex = mImpl->mEventData->mPrimaryCursorPosition;
- CharacterIndex cursorIndex = oldCursorIndex;
+ CharacterIndex cursorIndex = 0;
// Validate the cursor position & number of characters
- if( static_cast< CharacterIndex >( std::abs( cursorOffset ) ) <= cursorIndex )
+ if( ( static_cast< int >( mImpl->mEventData->mPrimaryCursorPosition ) + cursorOffset ) >= 0 )
{
- cursorIndex = oldCursorIndex + cursorOffset;
+ cursorIndex = mImpl->mEventData->mPrimaryCursorPosition + cursorOffset;
}
if( ( cursorIndex + numberOfCharacters ) > currentText.Count() )
numberOfCharacters = currentText.Count() - cursorIndex;
}
- if( ( cursorIndex + numberOfCharacters ) <= mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters )
+ if( mImpl->mEventData->mPreEditFlag || // If the preedit flag is enabled, it means two (or more) of them came together i.e. when two keys have been pressed at the same time.
+ ( ( cursorIndex + numberOfCharacters ) <= mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters ) )
{
// Mark the paragraphs to be updated.
mImpl->mTextUpdateInfo.mCharacterIndex = std::min( cursorIndex, mImpl->mTextUpdateInfo.mCharacterIndex );
mImpl->RetrieveDefaultInputStyle( mImpl->mEventData->mInputStyle );
// Update the input style.
- mImpl->mLogicalModel->RetrieveStyle( cursorIndex, mImpl->mEventData->mInputStyle );
+ mImpl->mModel->mLogicalModel->RetrieveStyle( cursorIndex, mImpl->mEventData->mInputStyle );
// Compare if the input style has changed.
const bool hasInputStyleChanged = !currentInputStyle.Equal( mImpl->mEventData->mInputStyle );
}
// Updates the text style runs by removing characters. Runs with no characters are removed.
- mImpl->mLogicalModel->UpdateTextStyleRuns( cursorIndex, -numberOfCharacters );
+ mImpl->mModel->mLogicalModel->UpdateTextStyleRuns( cursorIndex, -numberOfCharacters );
// Remove the characters.
Vector<Character>::Iterator first = currentText.Begin() + cursorIndex;
const Length requestedNumberOfCharacters = mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters;
// Get the current layout size.
- layoutSize = mImpl->mVisualModel->GetLayoutSize();
+ layoutSize = mImpl->mModel->mVisualModel->GetLayoutSize();
if( NO_OPERATION != ( LAYOUT & operations ) )
{
// Fill the vectors again.
// Calculate the number of glyphs to layout.
- const Vector<GlyphIndex>& charactersToGlyph = mImpl->mVisualModel->mCharactersToGlyph;
- const Vector<Length>& glyphsPerCharacter = mImpl->mVisualModel->mGlyphsPerCharacter;
+ const Vector<GlyphIndex>& charactersToGlyph = mImpl->mModel->mVisualModel->mCharactersToGlyph;
+ const Vector<Length>& glyphsPerCharacter = mImpl->mModel->mVisualModel->mGlyphsPerCharacter;
const GlyphIndex* const charactersToGlyphBuffer = charactersToGlyph.Begin();
const Length* const glyphsPerCharacterBuffer = glyphsPerCharacter.Begin();
const CharacterIndex lastIndex = startIndex + ( ( requestedNumberOfCharacters > 0u ) ? requestedNumberOfCharacters - 1u : 0u );
const GlyphIndex startGlyphIndex = mImpl->mTextUpdateInfo.mStartGlyphIndex;
const Length numberOfGlyphs = ( requestedNumberOfCharacters > 0u ) ? *( charactersToGlyphBuffer + lastIndex ) + *( glyphsPerCharacterBuffer + lastIndex ) - startGlyphIndex : 0u;
- const Length totalNumberOfGlyphs = mImpl->mVisualModel->mGlyphs.Count();
+ const Length totalNumberOfGlyphs = mImpl->mModel->mVisualModel->mGlyphs.Count();
if( 0u == totalNumberOfGlyphs )
{
if( NO_OPERATION != ( UPDATE_LAYOUT_SIZE & operations ) )
{
- mImpl->mVisualModel->SetLayoutSize( Size::ZERO );
+ mImpl->mModel->mVisualModel->SetLayoutSize( Size::ZERO );
}
// Nothing else to do if there is no glyphs.
return true;
}
- const Vector<LineBreakInfo>& lineBreakInfo = mImpl->mLogicalModel->mLineBreakInfo;
- const Vector<WordBreakInfo>& wordBreakInfo = mImpl->mLogicalModel->mWordBreakInfo;
- const Vector<CharacterDirection>& characterDirection = mImpl->mLogicalModel->mCharacterDirections;
- const Vector<GlyphInfo>& glyphs = mImpl->mVisualModel->mGlyphs;
- const Vector<CharacterIndex>& glyphsToCharactersMap = mImpl->mVisualModel->mGlyphsToCharacters;
- const Vector<Length>& charactersPerGlyph = mImpl->mVisualModel->mCharactersPerGlyph;
- const Character* const textBuffer = mImpl->mLogicalModel->mText.Begin();
+ const Vector<LineBreakInfo>& lineBreakInfo = mImpl->mModel->mLogicalModel->mLineBreakInfo;
+ const Vector<WordBreakInfo>& wordBreakInfo = mImpl->mModel->mLogicalModel->mWordBreakInfo;
+ const Vector<CharacterDirection>& characterDirection = mImpl->mModel->mLogicalModel->mCharacterDirections;
+ const Vector<GlyphInfo>& glyphs = mImpl->mModel->mVisualModel->mGlyphs;
+ const Vector<CharacterIndex>& glyphsToCharactersMap = mImpl->mModel->mVisualModel->mGlyphsToCharacters;
+ const Vector<Length>& charactersPerGlyph = mImpl->mModel->mVisualModel->mCharactersPerGlyph;
+ const Character* const textBuffer = mImpl->mModel->mLogicalModel->mText.Begin();
// Set the layout parameters.
- LayoutParameters layoutParameters( size,
- textBuffer,
- lineBreakInfo.Begin(),
- wordBreakInfo.Begin(),
- ( 0u != characterDirection.Count() ) ? characterDirection.Begin() : NULL,
- glyphs.Begin(),
- glyphsToCharactersMap.Begin(),
- charactersPerGlyph.Begin(),
- charactersToGlyphBuffer,
- glyphsPerCharacterBuffer,
- totalNumberOfGlyphs );
+ Layout::Parameters layoutParameters( size,
+ textBuffer,
+ lineBreakInfo.Begin(),
+ wordBreakInfo.Begin(),
+ ( 0u != characterDirection.Count() ) ? characterDirection.Begin() : NULL,
+ glyphs.Begin(),
+ glyphsToCharactersMap.Begin(),
+ charactersPerGlyph.Begin(),
+ charactersToGlyphBuffer,
+ glyphsPerCharacterBuffer,
+ totalNumberOfGlyphs,
+ mImpl->mModel->mHorizontalAlignment );
// Resize the vector of positions to have the same size than the vector of glyphs.
- Vector<Vector2>& glyphPositions = mImpl->mVisualModel->mGlyphPositions;
+ Vector<Vector2>& glyphPositions = mImpl->mModel->mVisualModel->mGlyphPositions;
glyphPositions.Resize( totalNumberOfGlyphs );
// Whether the last character is a new paragraph character.
- mImpl->mTextUpdateInfo.mIsLastCharacterNewParagraph = TextAbstraction::IsNewParagraph( *( textBuffer + ( mImpl->mLogicalModel->mText.Count() - 1u ) ) );
+ mImpl->mTextUpdateInfo.mIsLastCharacterNewParagraph = TextAbstraction::IsNewParagraph( *( textBuffer + ( mImpl->mModel->mLogicalModel->mText.Count() - 1u ) ) );
layoutParameters.isLastNewParagraph = mImpl->mTextUpdateInfo.mIsLastCharacterNewParagraph;
// The initial glyph and the number of glyphs to layout.
Size newLayoutSize;
viewUpdated = mImpl->mLayoutEngine.LayoutText( layoutParameters,
glyphPositions,
- mImpl->mVisualModel->mLines,
- newLayoutSize );
+ mImpl->mModel->mVisualModel->mLines,
+ newLayoutSize,
+ mImpl->mModel->mElideEnabled );
viewUpdated = viewUpdated || ( newLayoutSize != layoutSize );
{
layoutSize = newLayoutSize;
- if ( NO_OPERATION != ( UPDATE_DIRECTION & operations ) )
+ if( NO_OPERATION != ( UPDATE_DIRECTION & operations ) )
{
mImpl->mAutoScrollDirectionRTL = false;
}
// Reorder the lines
if( NO_OPERATION != ( REORDER & operations ) )
{
- Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = mImpl->mLogicalModel->mBidirectionalParagraphInfo;
- Vector<BidirectionalLineInfoRun>& bidirectionalLineInfo = mImpl->mLogicalModel->mBidirectionalLineInfo;
+ Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = mImpl->mModel->mLogicalModel->mBidirectionalParagraphInfo;
+ Vector<BidirectionalLineInfoRun>& bidirectionalLineInfo = mImpl->mModel->mLogicalModel->mBidirectionalLineInfo;
// Check first if there are paragraphs with bidirectional info.
if( 0u != bidirectionalInfo.Count() )
{
// Get the lines
- const Length numberOfLines = mImpl->mVisualModel->mLines.Count();
+ const Length numberOfLines = mImpl->mModel->mVisualModel->mLines.Count();
// Reorder the lines.
bidirectionalLineInfo.Reserve( numberOfLines ); // Reserve because is not known yet how many lines have right to left characters.
ReorderLines( bidirectionalInfo,
startIndex,
requestedNumberOfCharacters,
- mImpl->mVisualModel->mLines,
+ mImpl->mModel->mVisualModel->mLines,
bidirectionalLineInfo );
// Set the bidirectional info per line into the layout parameters.
if ( ( NO_OPERATION != ( UPDATE_DIRECTION & operations ) ) && ( numberOfLines > 0 ) )
{
- const LineRun* const firstline = mImpl->mVisualModel->mLines.Begin();
+ const LineRun* const firstline = mImpl->mModel->mVisualModel->mLines.Begin();
if ( firstline )
{
mImpl->mAutoScrollDirectionRTL = firstline->direction;
// Sets the layout size.
if( NO_OPERATION != ( UPDATE_LAYOUT_SIZE & operations ) )
{
- mImpl->mVisualModel->SetLayoutSize( layoutSize );
+ mImpl->mModel->mVisualModel->SetLayoutSize( layoutSize );
}
} // view updated
-
- // Store the size used to layout the text.
- mImpl->mVisualModel->mControlSize = size;
}
if( NO_OPERATION != ( ALIGN & operations ) )
{
// The laid-out lines.
- Vector<LineRun>& lines = mImpl->mVisualModel->mLines;
+ Vector<LineRun>& lines = mImpl->mModel->mVisualModel->mLines;
+ // Need to align with the control's size as the text may contain lines
+ // starting either with left to right text or right to left.
mImpl->mLayoutEngine.Align( size,
startIndex,
requestedNumberOfCharacters,
- lines );
+ mImpl->mModel->mHorizontalAlignment,
+ lines,
+ mImpl->mModel->mAlignmentOffset );
viewUpdated = true;
}
void Controller::CalculateVerticalOffset( const Size& controlSize )
{
- Size layoutSize = mImpl->mVisualModel->GetLayoutSize();
+ Size layoutSize = mImpl->mModel->mVisualModel->GetLayoutSize();
if( fabsf( layoutSize.height ) < Math::MACHINE_EPSILON_1000 )
{
layoutSize.height = mImpl->GetDefaultFontLineHeight();
}
- switch( mImpl->mLayoutEngine.GetVerticalAlignment() )
+ switch( mImpl->mModel->mVerticalAlignment )
{
- case LayoutEngine::VERTICAL_ALIGN_TOP:
+ case Layout::VERTICAL_ALIGN_TOP:
{
- mImpl->mScrollPosition.y = 0.f;
+ mImpl->mModel->mScrollPosition.y = 0.f;
break;
}
- case LayoutEngine::VERTICAL_ALIGN_CENTER:
+ case Layout::VERTICAL_ALIGN_CENTER:
{
- mImpl->mScrollPosition.y = floorf( 0.5f * ( controlSize.height - layoutSize.height ) ); // try to avoid pixel alignment.
+ mImpl->mModel->mScrollPosition.y = floorf( 0.5f * ( controlSize.height - layoutSize.height ) ); // try to avoid pixel alignment.
break;
}
- case LayoutEngine::VERTICAL_ALIGN_BOTTOM:
+ case Layout::VERTICAL_ALIGN_BOTTOM:
{
- mImpl->mScrollPosition.y = controlSize.height - layoutSize.height;
+ mImpl->mModel->mScrollPosition.y = controlSize.height - layoutSize.height;
break;
}
}
return;
}
+ mImpl->mEventData->mCheckScrollAmount = true;
+
// The natural size needs to be re-calculated.
mImpl->mRecalculateNaturalSize = true;
return;
}
+ mImpl->mEventData->mCheckScrollAmount = true;
+
// The natural size needs to be re-calculated.
mImpl->mRecalculateNaturalSize = true;
mImpl->mEventData->mEventQueue.push_back( event );
}
+ mImpl->mEventData->mCheckScrollAmount = true;
+ mImpl->mEventData->mIsLeftHandleSelected = true;
+ mImpl->mEventData->mIsRightHandleSelected = true;
mImpl->RequestRelayout();
}
}
if( removed )
{
- if( ( 0u != mImpl->mLogicalModel->mText.Count() ) ||
+ if( ( 0u != mImpl->mModel->mLogicalModel->mText.Count() ) ||
!mImpl->IsPlaceholderAvailable() )
{
mImpl->QueueModifyEvent( ModifyEvent::TEXT_DELETED );
void Controller::ResetText()
{
// Reset buffers.
- mImpl->mLogicalModel->mText.Clear();
+ mImpl->mModel->mLogicalModel->mText.Clear();
// We have cleared everything including the placeholder-text
mImpl->PlaceholderCleared();
const char* text( NULL );
size_t size( 0 );
- // TODO - Switch placeholder text styles when changing state
- if( ( EventData::INACTIVE != mImpl->mEventData->mState ) &&
- ( 0u != mImpl->mEventData->mPlaceholderTextActive.c_str() ) )
+ if( !mImpl->mEventData->mPlaceholderTextActive.empty() || !mImpl->mEventData->mPlaceholderTextInactive.empty() )
{
- text = mImpl->mEventData->mPlaceholderTextActive.c_str();
- size = mImpl->mEventData->mPlaceholderTextActive.size();
+ if( ( EventData::INACTIVE != mImpl->mEventData->mState ) &&
+ ( 0u != mImpl->mEventData->mPlaceholderTextActive.c_str() ) )
+ {
+ text = mImpl->mEventData->mPlaceholderTextActive.c_str();
+ size = mImpl->mEventData->mPlaceholderTextActive.size();
+ }
+ else
+ {
+ text = mImpl->mEventData->mPlaceholderTextInactive.c_str();
+ size = mImpl->mEventData->mPlaceholderTextInactive.size();
+ }
}
else
{
- text = mImpl->mEventData->mPlaceholderTextInactive.c_str();
- size = mImpl->mEventData->mPlaceholderTextInactive.size();
+ if( 0u != mImpl->mEventData->mPlaceholderText.c_str() )
+ {
+ text = mImpl->mEventData->mPlaceholderText.c_str();
+ size = mImpl->mEventData->mPlaceholderText.size();
+ }
}
mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
// Reset model for showing placeholder.
- mImpl->mLogicalModel->mText.Clear();
- mImpl->mVisualModel->SetTextColor( mImpl->mEventData->mPlaceholderTextColor );
+ mImpl->mModel->mLogicalModel->mText.Clear();
+ mImpl->mModel->mVisualModel->SetTextColor( mImpl->mEventData->mPlaceholderTextColor );
// Convert text into UTF-32
- Vector<Character>& utf32Characters = mImpl->mLogicalModel->mText;
+ Vector<Character>& utf32Characters = mImpl->mModel->mLogicalModel->mText;
utf32Characters.Resize( size );
// This is a bit horrible but std::string returns a (signed) char*
// Set flags to update the model.
mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
- mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mLogicalModel->mText.Count();
+ mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mModel->mLogicalModel->mText.Count();
mImpl->mTextUpdateInfo.mClearAll = true;
mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
void Controller::ClearStyleData()
{
- mImpl->mLogicalModel->mColorRuns.Clear();
- mImpl->mLogicalModel->ClearFontDescriptionRuns();
+ mImpl->mModel->mLogicalModel->mColorRuns.Clear();
+ mImpl->mModel->mLogicalModel->ClearFontDescriptionRuns();
}
void Controller::ResetCursorPosition( CharacterIndex cursorIndex )
if( NULL != mImpl->mEventData )
{
// Reset the scroll position.
- mImpl->mScrollPosition = Vector2::ZERO;
+ mImpl->mModel->mScrollPosition = Vector2::ZERO;
mImpl->mEventData->mScrollAfterUpdatePosition = true;
}
}