// INTERNAL INCLUDES
#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
+#include <dali-toolkit/internal/text/text-controller-background-actor.h>
#include <dali-toolkit/internal/text/text-controller-event-handler.h>
#include <dali-toolkit/internal/text/text-controller-impl.h>
#include <dali-toolkit/internal/text/text-controller-input-font-handler.h>
Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
#endif
-constexpr float MAX_FLOAT = std::numeric_limits<float>::max();
-
const std::string EMPTY_STRING("");
template<typename Type>
mImpl->mMetrics->SetGlyphType(glyphType);
// Clear the font-specific data
- ClearFontData();
+ mImpl->ClearFontData();
mImpl->RequestRelayout();
}
void Controller::SetAutoScrollEnabled(bool enable)
{
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() == Layout::Engine::SINGLE_LINE_BOX)
- {
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
- LAYOUT |
- ALIGN |
- UPDATE_LAYOUT_SIZE |
- REORDER);
-
- if(enable)
- {
- DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled for SINGLE_LINE_BOX\n");
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | UPDATE_DIRECTION);
- }
- else
- {
- DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled Disabling autoscroll\n");
- }
-
- mImpl->mIsAutoScrollEnabled = enable;
- mImpl->RequestRelayout();
- }
- else
- {
- DALI_LOG_WARNING("Attempted AutoScrolling on a non SINGLE_LINE_BOX, request ignored\n");
- mImpl->mIsAutoScrollEnabled = false;
- }
+ mImpl->SetAutoScrollEnabled(enable);
}
bool Controller::IsAutoScrollEnabled() const
{
DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::IsAutoScrollEnabled[%s]\n", mImpl->mIsAutoScrollEnabled ? "true" : "false");
-
return mImpl->mIsAutoScrollEnabled;
}
void Controller::SetEnableCursorBlink(bool enable)
{
- DALI_ASSERT_DEBUG(NULL != mImpl->mEventData && "TextInput disabled");
-
- if(mImpl->mEventData)
- {
- mImpl->mEventData->mCursorBlinkEnabled = enable;
-
- if(!enable && mImpl->mEventData->mDecorator)
- {
- mImpl->mEventData->mDecorator->StopCursorBlink();
- }
- }
+ mImpl->SetEnableCursorBlink(enable);
}
bool Controller::GetEnableCursorBlink() const
void Controller::SetMultiLineEnabled(bool enable)
{
- const Layout::Engine::Type layout = enable ? Layout::Engine::MULTI_LINE_BOX : Layout::Engine::SINGLE_LINE_BOX;
-
- if(layout != mImpl->mLayoutEngine.GetLayout())
- {
- // Set the layout type.
- mImpl->mLayoutEngine.SetLayout(layout);
-
- // Set the flags to redo the layout operations
- const OperationsMask layoutOperations = static_cast<OperationsMask>(LAYOUT |
- UPDATE_LAYOUT_SIZE |
- ALIGN |
- REORDER);
-
- mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | layoutOperations);
-
- // Need to recalculate natural size
- mImpl->mRecalculateNaturalSize = true;
-
- mImpl->RequestRelayout();
- }
+ mImpl->SetMultiLineEnabled(enable);
}
bool Controller::IsMultiLineEnabled() const
void Controller::SetHorizontalAlignment(Text::HorizontalAlignment::Type alignment)
{
- if(alignment != mImpl->mModel->mHorizontalAlignment)
- {
- // Set the alignment.
- mImpl->mModel->mHorizontalAlignment = alignment;
-
- // Set the flag to redo the alignment operation.
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | ALIGN);
-
- if(mImpl->mEventData)
- {
- mImpl->mEventData->mUpdateAlignment = true;
-
- // Update the cursor if it's in editing mode
- if(EventData::IsEditingState(mImpl->mEventData->mState))
- {
- mImpl->ChangeState(EventData::EDITING);
- mImpl->mEventData->mUpdateCursorPosition = true;
- }
- }
-
- mImpl->RequestRelayout();
- }
+ mImpl->SetHorizontalAlignment(alignment);
}
Text::HorizontalAlignment::Type Controller::GetHorizontalAlignment() const
void Controller::SetVerticalAlignment(VerticalAlignment::Type alignment)
{
- if(alignment != mImpl->mModel->mVerticalAlignment)
- {
- // Set the alignment.
- mImpl->mModel->mVerticalAlignment = alignment;
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | ALIGN);
- mImpl->RequestRelayout();
- }
+ mImpl->SetVerticalAlignment(alignment);
}
VerticalAlignment::Type Controller::GetVerticalAlignment() const
Dali::LayoutDirection::Type Controller::GetLayoutDirection(Dali::Actor& actor) const
{
- if(mImpl->mModel->mMatchLayoutDirection == DevelText::MatchLayoutDirection::LOCALE ||
- (mImpl->mModel->mMatchLayoutDirection == DevelText::MatchLayoutDirection::INHERIT && !mImpl->mIsLayoutDirectionChanged))
- {
- return static_cast<Dali::LayoutDirection::Type>(DevelWindow::Get(actor).GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
- }
- else
- {
- return static_cast<Dali::LayoutDirection::Type>(actor.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
- }
+ return mImpl->GetLayoutDirection(actor);
}
bool Controller::IsShowingRealText() const
void Controller::SetLineWrapMode(Text::LineWrap::Mode lineWrapMode)
{
- if(lineWrapMode != mImpl->mModel->mLineWrapMode)
- {
- // Update Text layout for applying wrap mode
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
- ALIGN |
- LAYOUT |
- UPDATE_LAYOUT_SIZE |
- REORDER);
-
- if((mImpl->mModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) || (lineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) ||
- (mImpl->mModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::MIXED) || (lineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::MIXED)) // hyphen is treated as line break
- {
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | GET_LINE_BREAKS);
- }
-
- // Set the text wrap mode.
- mImpl->mModel->mLineWrapMode = lineWrapMode;
-
- mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
- mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
- mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mModel->mLogicalModel->mText.Count();
-
- // Request relayout
- mImpl->RequestRelayout();
- }
+ mImpl->SetLineWrapMode(lineWrapMode);
}
Text::LineWrap::Mode Controller::GetLineWrapMode() const
return mImpl->mTextFitEnabled;
}
+void Controller::SetTextFitChanged(bool changed)
+{
+ mImpl->mTextFitChanged = changed;
+}
+
+bool Controller::IsTextFitChanged() const
+{
+ return mImpl->mTextFitChanged;
+}
+
void Controller::SetTextFitMinSize(float minSize, FontSizeType type)
{
mImpl->mTextFitMinSize = (type == POINT_SIZE) ? minSize : ConvertPixelToPoint(minSize);
return mImpl->mTextFitContentSize;
}
+float Controller::GetTextFitPointSize() const
+{
+ return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFitPointSize : 0.0f;
+}
+
void Controller::SetPlaceholderTextElideEnabled(bool enabled)
{
PlaceholderHandler::SetPlaceholderTextElideEnabled(*this, enabled);
void Controller::GetText(std::string& text) const
{
- if(!mImpl->IsShowingPlaceholderText())
- {
- // Retrieves the text string.
- mImpl->GetText(0u, text);
- }
- else
- {
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::GetText %p empty (but showing placeholder)\n", this);
- }
+ mImpl->GetText(text);
}
void Controller::SetPlaceholderText(PlaceholderType type, const std::string& text)
void Controller::UpdateAfterFontChange(const std::string& newDefaultFont)
{
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::UpdateAfterFontChange\n");
-
- if(!mImpl->mFontDefaults->familyDefined) // 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());
- mImpl->mFontDefaults->mFontDescription.family = newDefaultFont;
-
- ClearFontData();
-
- mImpl->RequestRelayout();
- }
+ mImpl->UpdateAfterFontChange(newDefaultFont);
}
void Controller::RetrieveSelection(std::string& selectedText) const
UpdateCursorPosition(mImpl->mEventData);
// Clear the font-specific data
- ClearFontData();
+ mImpl->ClearFontData();
mImpl->RequestRelayout();
}
UpdateCursorPosition(mImpl->mEventData);
// Clear the font-specific data
- ClearFontData();
+ mImpl->ClearFontData();
mImpl->RequestRelayout();
}
UpdateCursorPosition(mImpl->mEventData);
// Clear the font-specific data
- ClearFontData();
+ mImpl->ClearFontData();
mImpl->RequestRelayout();
}
UpdateCursorPosition(mImpl->mEventData);
// Clear the font-specific data
- ClearFontData();
+ mImpl->ClearFontData();
mImpl->RequestRelayout();
}
UpdateCursorPosition(mImpl->mEventData);
// Clear the font-specific data
- ClearFontData();
+ mImpl->ClearFontData();
mImpl->RequestRelayout();
}
UpdateCursorPosition(mImpl->mEventData);
// Clear the font-specific data
- ClearFontData();
+ mImpl->ClearFontData();
mImpl->RequestRelayout();
}
void Controller::SetDefaultColor(const Vector4& color)
{
- mImpl->mTextColor = color;
-
- if(!mImpl->IsShowingPlaceholderText())
- {
- mImpl->mModel->mVisualModel->SetTextColor(color);
- mImpl->mModel->mLogicalModel->mColorRuns.Clear();
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | COLOR);
- mImpl->RequestRelayout();
- }
+ mImpl->SetDefaultColor(color);
}
const Vector4& Controller::GetDefaultColor() const
bool Controller::SetDefaultLineSpacing(float lineSpacing)
{
- if(std::fabs(lineSpacing - mImpl->mLayoutEngine.GetDefaultLineSpacing()) > Math::MACHINE_EPSILON_1000)
- {
- mImpl->mLayoutEngine.SetDefaultLineSpacing(lineSpacing);
- mImpl->mRecalculateNaturalSize = true;
-
- mImpl->RelayoutForNewLineSize();
- return true;
- }
- return false;
+ return mImpl->SetDefaultLineSpacing(lineSpacing);
}
float Controller::GetDefaultLineSpacing() const
bool Controller::SetDefaultLineSize(float lineSize)
{
- if(std::fabs(lineSize - mImpl->mLayoutEngine.GetDefaultLineSize()) > Math::MACHINE_EPSILON_1000)
- {
- mImpl->mLayoutEngine.SetDefaultLineSize(lineSize);
- mImpl->mRecalculateNaturalSize = true;
-
- mImpl->RelayoutForNewLineSize();
- return true;
- }
- return false;
+ return mImpl->SetDefaultLineSize(lineSize);
}
float Controller::GetDefaultLineSize() const
Toolkit::DevelText::TextDirection::Type Controller::GetTextDirection()
{
// Make sure the model is up-to-date before layouting
- ProcessModifyEvents();
-
- if(mImpl->mUpdateTextDirection)
- {
- // 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 |
- 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);
-
- Vector3 naturalSize;
- DoRelayout(Size(MAX_FLOAT, MAX_FLOAT),
- static_cast<OperationsMask>(onlyOnceOperations |
- LAYOUT | REORDER | UPDATE_DIRECTION),
- naturalSize.GetVectorXY());
-
- // Do not do again the only once operations.
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending & ~onlyOnceOperations);
-
- // Clear the update info. This info will be set the next time the text is updated.
- mImpl->mTextUpdateInfo.Clear();
-
- // FullRelayoutNeeded should be true because DoRelayout is MAX_FLOAT, MAX_FLOAT.
- mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
-
- mImpl->mUpdateTextDirection = false;
- }
+ EventHandler::ProcessModifyEvents(*this);
- return mImpl->mIsTextDirectionRTL ? Toolkit::DevelText::TextDirection::RIGHT_TO_LEFT : Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT;
+ return mImpl->GetTextDirection();
}
Toolkit::DevelText::VerticalLineAlignment::Type Controller::GetVerticalLineAlignment() const
EventHandler::SelectEvent(*this, x, y, selectType);
}
-void Controller::SelectEvent(const uint32_t start, const uint32_t end, SelectionType selectType)
-{
- EventHandler::SelectEvent(*this, start, end, selectType);
-}
-
void Controller::SetTextSelectionRange(const uint32_t* start, const uint32_t* end)
{
if(mImpl->mEventData)
mImpl->mEventData->mIsRightHandleSelected = true;
mImpl->SetTextSelectionRange(start, end);
mImpl->RequestRelayout();
- KeyboardFocusGainEvent();
+ EventHandler::KeyboardFocusGainEvent(*this);
}
}
mImpl->mEventData->mCheckScrollAmount = true;
if(mImpl->SetPrimaryCursorPosition(index, focused) && focused)
{
- KeyboardFocusGainEvent();
+ EventHandler::KeyboardFocusGainEvent(*this);
return true;
}
}
void Controller::SelectWholeText()
{
- SelectEvent(0.f, 0.f, SelectionType::ALL);
+ EventHandler::SelectEvent(*this, 0.f, 0.f, SelectionType::ALL);
}
void Controller::SelectNone()
{
- SelectEvent(0.f, 0.f, SelectionType::NONE);
+ EventHandler::SelectEvent(*this, 0.f, 0.f, SelectionType::NONE);
}
void Controller::SelectText(const uint32_t start, const uint32_t end)
{
- SelectEvent(start, end, SelectionType::RANGE);
+ EventHandler::SelectEvent(*this, start, end, SelectionType::RANGE);
}
string Controller::GetSelectedText() const
{
- string text;
- if(EventData::SELECTING == mImpl->mEventData->mState)
- {
- mImpl->RetrieveSelection(text, false);
- }
- return text;
+ return mImpl->GetSelectedText();
}
string Controller::CopyText()
{
- string text;
- mImpl->RetrieveSelection(text, false);
- mImpl->SendSelectionToClipboard(false); // Text not modified
-
- mImpl->mEventData->mUpdateCursorPosition = true;
-
- mImpl->RequestRelayout(); // Cursor, Handles, Selection Highlight, Popup
-
- return text;
+ return mImpl->CopyText();
}
string Controller::CutText()
{
- string text;
- mImpl->RetrieveSelection(text, false);
-
- if(!IsEditable())
- {
- return EMPTY_STRING;
- }
-
- mImpl->SendSelectionToClipboard(true); // Synchronous call to modify text
- mImpl->mOperationsPending = ALL_OPERATIONS;
-
- if((0u != mImpl->mModel->mLogicalModel->mText.Count()) ||
- !mImpl->IsPlaceholderAvailable())
- {
- mImpl->QueueModifyEvent(ModifyEvent::TEXT_DELETED);
- }
- else
- {
- ShowPlaceholderText();
- }
-
- mImpl->mEventData->mUpdateCursorPosition = true;
- mImpl->mEventData->mScrollAfterDelete = true;
-
- mImpl->RequestRelayout();
-
- if(nullptr != mImpl->mEditableControlInterface)
- {
- mImpl->mEditableControlInterface->TextChanged(true);
- }
- return text;
+ return mImpl->CutText();
}
void Controller::PasteText()
mImpl->RequestRelayout();
}
-void Controller::InsertText(const std::string& text, Controller::InsertType type)
-{
- TextUpdater::InsertText(*this, text, type);
-}
-
-void Controller::PasteText(const std::string& stringToPaste)
-{
- TextUpdater::PasteText(*this, stringToPaste);
-}
-
-bool Controller::RemoveText(int cursorOffset, int numberOfCharacters, UpdateInputStyleType type)
-{
- return TextUpdater::RemoveText(*this, cursorOffset, numberOfCharacters, type);
-}
-
-bool Controller::RemoveSelectedText()
-{
- return TextUpdater::RemoveSelectedText(*this);
-}
-
-void Controller::InsertTextAnchor(int numberOfCharacters, CharacterIndex previousCursorIndex)
-{
- TextUpdater::InsertTextAnchor(*this, numberOfCharacters, previousCursorIndex);
-}
-
-void Controller::RemoveTextAnchor(int cursorOffset, int numberOfCharacters, CharacterIndex previousCursorIndex)
-{
- TextUpdater::RemoveTextAnchor(*this, cursorOffset, numberOfCharacters, previousCursorIndex);
-}
-
-bool Controller::DoRelayout(const Size& size, OperationsMask operationsRequired, Size& layoutSize)
-{
- return Relayouter::DoRelayout(*this, size, operationsRequired, layoutSize);
-}
-
-void Controller::CalculateVerticalOffset(const Size& controlSize)
-{
- Relayouter::CalculateVerticalOffset(*this, controlSize);
-}
-
-void Controller::ProcessModifyEvents()
-{
- EventHandler::ProcessModifyEvents(*this);
-}
-
-void Controller::TextReplacedEvent()
-{
- EventHandler::TextReplacedEvent(*this);
-}
-
-void Controller::TextInsertedEvent()
-{
- EventHandler::TextInsertedEvent(*this);
-}
-
-void Controller::TextDeletedEvent()
-{
- EventHandler::TextDeletedEvent(*this);
-}
-
-bool Controller::DeleteEvent(int keyCode)
-{
- return EventHandler::DeleteEvent(*this, keyCode);
-}
-
-// private : Helpers.
-
-void Controller::ResetText()
-{
- TextUpdater::ResetText(*this);
-}
-
-void Controller::ShowPlaceholderText()
-{
- PlaceholderHandler::ShowPlaceholderText(*this);
-}
-
-void Controller::ClearFontData()
-{
- if(mImpl->mFontDefaults)
- {
- mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
- }
-
- // Set flags to update the model.
- mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
- mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
- mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mModel->mLogicalModel->mText.Count();
-
- mImpl->mTextUpdateInfo.mClearAll = true;
- mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
- mImpl->mRecalculateNaturalSize = true;
-
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
- VALIDATE_FONTS |
- SHAPE_TEXT |
- BIDI_INFO |
- GET_GLYPH_METRICS |
- LAYOUT |
- UPDATE_LAYOUT_SIZE |
- REORDER |
- ALIGN);
-}
-
-void Controller::ClearStyleData()
-{
- mImpl->mModel->mLogicalModel->mColorRuns.Clear();
- mImpl->mModel->mLogicalModel->ClearFontDescriptionRuns();
-}
-
void Controller::ResetCursorPosition(CharacterIndex cursorIndex)
{
// Reset the cursor position
CharacterIndex Controller::GetCursorPosition()
{
- if(!mImpl->mEventData)
- return 0;
-
- return mImpl->mEventData->mPrimaryCursorPosition;
-}
-
-void Controller::ResetScrollPosition()
-{
- if(mImpl->mEventData)
- {
- // Reset the scroll position.
- mImpl->mModel->mScrollPosition = Vector2::ZERO;
- mImpl->mEventData->mScrollAfterUpdatePosition = true;
- }
+ return mImpl->mEventData ? mImpl->mEventData->mPrimaryCursorPosition : 0;
}
void Controller::SetControlInterface(ControlInterface* controlInterface)
Actor Controller::CreateBackgroundActor()
{
- return mImpl->CreateBackgroundActor();
+ return CreateControllerBackgroundActor(mImpl->mView, mImpl->mModel->mVisualModel, mImpl->mShaderBackground);
+}
+
+void Controller::GetAnchorActors(std::vector<Toolkit::TextAnchor>& anchorActors)
+{
+ mImpl->GetAnchorActors(anchorActors);
+}
+
+int Controller::GetAnchorIndex(size_t characterOffset)
+{
+ return mImpl->GetAnchorIndex(characterOffset);
}
Controller::Controller(ControlInterface* controlInterface,