${toolkit_src_dir}/text/hyphenator.cpp
${toolkit_src_dir}/text/text-enumerations-impl.cpp
${toolkit_src_dir}/text/text-controller.cpp
+ ${toolkit_src_dir}/text/text-controller-background-actor.cpp
${toolkit_src_dir}/text/text-controller-event-handler.cpp
${toolkit_src_dir}/text/text-controller-impl.cpp
${toolkit_src_dir}/text/text-controller-impl-data-clearer.cpp
--- /dev/null
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// HEADER
+#include <dali-toolkit/internal/text/text-controller-background-actor.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/rendering/renderer.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
+#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
+#include <dali-toolkit/internal/text/text-view.h>
+
+namespace Dali::Toolkit::Text
+{
+
+namespace
+{
+struct BackgroundVertex
+{
+ Vector2 mPosition; ///< Vertex posiiton
+ Vector4 mColor; ///< Vertex color
+};
+
+struct BackgroundMesh
+{
+ Vector<BackgroundVertex> mVertices; ///< container of vertices
+ Vector<unsigned short> mIndices; ///< container of indices
+};
+} // unnamed namespace
+
+Actor CreateControllerBackgroundActor(const View& textView, const VisualModelPtr& textVisualModel, Shader& textShaderBackground)
+{
+ // NOTE: Currently we only support background color for left-to-right text.
+
+ Actor actor;
+
+ Length numberOfGlyphs = textView.GetNumberOfGlyphs();
+ if(numberOfGlyphs > 0u)
+ {
+ Vector<GlyphInfo> glyphs;
+ glyphs.Resize(numberOfGlyphs);
+
+ Vector<Vector2> positions;
+ positions.Resize(numberOfGlyphs);
+
+ // Get the line where the glyphs are laid-out.
+ const LineRun* lineRun = textVisualModel->mLines.Begin();
+ float alignmentOffset = lineRun->alignmentOffset;
+ numberOfGlyphs = textView.GetGlyphs(glyphs.Begin(),
+ positions.Begin(),
+ alignmentOffset,
+ 0u,
+ numberOfGlyphs);
+
+ glyphs.Resize(numberOfGlyphs);
+ positions.Resize(numberOfGlyphs);
+
+ const GlyphInfo* const glyphsBuffer = glyphs.Begin();
+ const Vector2* const positionsBuffer = positions.Begin();
+
+ BackgroundMesh mesh;
+ mesh.mVertices.Reserve(4u * glyphs.Size());
+ mesh.mIndices.Reserve(6u * glyphs.Size());
+
+ const Vector2 textSize = textView.GetLayoutSize();
+
+ const float offsetX = alignmentOffset + textSize.width * 0.5f;
+ const float offsetY = textSize.height * 0.5f;
+
+ const Vector4* const backgroundColorsBuffer = textView.GetBackgroundColors();
+ const ColorIndex* const backgroundColorIndicesBuffer = textView.GetBackgroundColorIndices();
+ const Vector4& defaultBackgroundColor = textVisualModel->IsBackgroundEnabled() ? textVisualModel->GetBackgroundColor() : Color::TRANSPARENT;
+
+ Vector4 quad;
+ uint32_t numberOfQuads = 0u;
+ Length yLineOffset = 0;
+ Length prevLineIndex = 0;
+ LineIndex lineIndex;
+ Length numberOfLines;
+
+ for(uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i)
+ {
+ const GlyphInfo& glyph = *(glyphsBuffer + i);
+
+ // Get the background color of the character.
+ // The color index zero is reserved for the default background color (i.e. Color::TRANSPARENT)
+ const bool isMarkupBackground = textView.IsMarkupBackgroundColorSet();
+ const ColorIndex backgroundColorIndex = isMarkupBackground ? *(backgroundColorIndicesBuffer + i) : 0u;
+ const bool isDefaultBackgroundColor = (0u == backgroundColorIndex);
+ const Vector4& backgroundColor = isDefaultBackgroundColor ? defaultBackgroundColor : *(backgroundColorsBuffer + backgroundColorIndex - 1u);
+
+ textVisualModel->GetNumberOfLines(i, 1, lineIndex, numberOfLines);
+ Length lineHeight = lineRun[lineIndex].ascender + -(lineRun[lineIndex].descender) + lineRun[lineIndex].lineSpacing;
+
+ if(lineIndex != prevLineIndex)
+ {
+ yLineOffset += lineHeight;
+ }
+
+ // Only create quads for glyphs with a background color
+ if(backgroundColor != Color::TRANSPARENT)
+ {
+ const Vector2 position = *(positionsBuffer + i);
+
+ if(i == 0u && glyphSize == 1u) // Only one glyph in the whole text
+ {
+ quad.x = position.x;
+ quad.y = yLineOffset;
+ quad.z = quad.x + std::max(glyph.advance, glyph.xBearing + glyph.width);
+ quad.w = lineHeight;
+ }
+ else if((lineIndex != prevLineIndex) || (i == 0u)) // The first glyph in the line
+ {
+ quad.x = position.x;
+ quad.y = yLineOffset;
+ quad.z = quad.x - glyph.xBearing + glyph.advance;
+ quad.w = quad.y + lineHeight;
+ }
+ else if(i == glyphSize - 1u) // The last glyph in the whole text
+ {
+ quad.x = position.x - glyph.xBearing;
+ quad.y = yLineOffset;
+ quad.z = quad.x + std::max(glyph.advance, glyph.xBearing + glyph.width);
+ quad.w = quad.y + lineHeight;
+ }
+ else // The glyph in the middle of the text
+ {
+ quad.x = position.x - glyph.xBearing;
+ quad.y = yLineOffset;
+ quad.z = quad.x + glyph.advance;
+ quad.w = quad.y + lineHeight;
+ }
+
+ BackgroundVertex vertex;
+
+ // Top left
+ vertex.mPosition.x = quad.x - offsetX;
+ vertex.mPosition.y = quad.y - offsetY;
+ vertex.mColor = backgroundColor;
+ mesh.mVertices.PushBack(vertex);
+
+ // Top right
+ vertex.mPosition.x = quad.z - offsetX;
+ vertex.mPosition.y = quad.y - offsetY;
+ vertex.mColor = backgroundColor;
+ mesh.mVertices.PushBack(vertex);
+
+ // Bottom left
+ vertex.mPosition.x = quad.x - offsetX;
+ vertex.mPosition.y = quad.w - offsetY;
+ vertex.mColor = backgroundColor;
+ mesh.mVertices.PushBack(vertex);
+
+ // Bottom right
+ vertex.mPosition.x = quad.z - offsetX;
+ vertex.mPosition.y = quad.w - offsetY;
+ vertex.mColor = backgroundColor;
+ mesh.mVertices.PushBack(vertex);
+
+ // Six indices in counter clockwise winding
+ mesh.mIndices.PushBack(1u + 4 * numberOfQuads);
+ mesh.mIndices.PushBack(0u + 4 * numberOfQuads);
+ mesh.mIndices.PushBack(2u + 4 * numberOfQuads);
+ mesh.mIndices.PushBack(2u + 4 * numberOfQuads);
+ mesh.mIndices.PushBack(3u + 4 * numberOfQuads);
+ mesh.mIndices.PushBack(1u + 4 * numberOfQuads);
+
+ numberOfQuads++;
+ }
+
+ if(lineIndex != prevLineIndex)
+ {
+ prevLineIndex = lineIndex;
+ }
+ }
+
+ // Only create the background actor if there are glyphs with background color
+ if(mesh.mVertices.Count() > 0u)
+ {
+ Property::Map quadVertexFormat;
+ quadVertexFormat["aPosition"] = Property::VECTOR2;
+ quadVertexFormat["aColor"] = Property::VECTOR4;
+
+ VertexBuffer quadVertices = VertexBuffer::New(quadVertexFormat);
+ quadVertices.SetData(&mesh.mVertices[0], mesh.mVertices.Size());
+
+ Geometry quadGeometry = Geometry::New();
+ quadGeometry.AddVertexBuffer(quadVertices);
+ quadGeometry.SetIndexBuffer(&mesh.mIndices[0], mesh.mIndices.Size());
+
+ if(!textShaderBackground)
+ {
+ textShaderBackground = Shader::New(SHADER_TEXT_CONTROLLER_BACKGROUND_SHADER_VERT, SHADER_TEXT_CONTROLLER_BACKGROUND_SHADER_FRAG);
+ }
+
+ Dali::Renderer renderer = Dali::Renderer::New(quadGeometry, textShaderBackground);
+ renderer.SetProperty(Dali::Renderer::Property::BLEND_MODE, BlendMode::ON);
+ renderer.SetProperty(Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT);
+
+ actor = Actor::New();
+ actor.SetProperty(Dali::Actor::Property::NAME, "TextBackgroundColorActor");
+ actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ actor.SetProperty(Actor::Property::SIZE, textSize);
+ actor.SetProperty(Actor::Property::COLOR_MODE, USE_OWN_MULTIPLY_PARENT_COLOR);
+ actor.AddRenderer(renderer);
+ }
+ }
+
+ return actor;
+}
+
+} // namespace Dali::Toolkit::Text
--- /dev/null
+#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_BACKGROUND_ACTOR_H
+#define DALI_TOOLKIT_TEXT_CONTROLLER_BACKGROUND_ACTOR_H
+
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/rendering/shader.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/visual-model-impl.h>
+
+namespace Dali::Toolkit::Text
+{
+class View;
+
+/**
+ * @brief Create an actor that renders the text background color
+ *
+ * @return the created actor or an empty handle if no background color needs to be rendered.
+ */
+Actor CreateControllerBackgroundActor(const View& textView, const VisualModelPtr& textVisualModel, Shader& textShaderBackground);
+
+} // namespace Dali::Toolkit::Text
+
+#endif // DALI_TOOLKIT_TEXT_CONTROLLER_BACKGROUND_ACTOR_H
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/cursor-helper-functions.h>
#include <dali-toolkit/internal/text/text-controller-impl.h>
+#include <dali-toolkit/internal/text/text-controller-placeholder-handler.h>
+#include <dali-toolkit/internal/text/text-controller-text-updater.h>
#include <dali-toolkit/internal/text/text-editable-control-interface.h>
namespace
if(controller.mImpl->IsShowingPlaceholderText())
{
// Show alternative placeholder-text when editing
- controller.ShowPlaceholderText();
+ PlaceholderHandler::ShowPlaceholderText(*controller.mImpl);
}
controller.mImpl->RequestRelayout();
if(!controller.mImpl->IsShowingRealText())
{
// Revert to regular placeholder-text when not editing
- controller.ShowPlaceholderText();
+ PlaceholderHandler::ShowPlaceholderText(*controller.mImpl);
}
}
}
else if((Dali::DALI_KEY_BACKSPACE == keyCode) ||
(Dali::DevelKey::DALI_KEY_DELETE == keyCode))
{
- textChanged = controller.DeleteEvent(keyCode);
+ textChanged = DeleteEvent(controller, keyCode);
// Will request for relayout.
relayoutNeeded = true;
// InputMethodContext is no longer handling key-events
controller.mImpl->ClearPreEditFlag();
- controller.InsertText(refinedKey, COMMIT);
+ TextUpdater::InsertText(controller, refinedKey, COMMIT);
textChanged = true;
if(controller.mImpl->IsShowingPlaceholderText() && !controller.mImpl->IsFocusedPlaceholderAvailable())
{
// Hide placeholder text
- controller.ResetText();
+ TextUpdater::ResetText(controller);
}
if(EventData::INACTIVE == state)
// A (single) replace event should come first, otherwise we wasted time processing NOOP events
DALI_ASSERT_DEBUG(it == events.Begin() && "Unexpected TEXT_REPLACED event");
- controller.TextReplacedEvent();
+ TextReplacedEvent(controller);
}
else if(ModifyEvent::TEXT_INSERTED == event.type)
{
- controller.TextInsertedEvent();
+ TextInsertedEvent(controller);
}
else if(ModifyEvent::TEXT_DELETED == event.type)
{
// Placeholder-text cannot be deleted
if(!controller.mImpl->IsShowingPlaceholderText())
{
- controller.TextDeletedEvent();
+ TextDeletedEvent(controller);
}
}
}
if(EventData::SELECTING == controller.mImpl->mEventData->mState)
{
- removed = controller.RemoveSelectedText();
+ removed = TextUpdater::RemoveSelectedText(controller);
}
else if((controller.mImpl->mEventData->mPrimaryCursorPosition > 0) && (keyCode == Dali::DALI_KEY_BACKSPACE))
{
// Remove the character before the current cursor position
- removed = controller.RemoveText(-1,
- 1,
- UPDATE_INPUT_STYLE);
+ removed = TextUpdater::RemoveText(controller, -1, 1, UPDATE_INPUT_STYLE);
}
else if((controller.mImpl->mEventData->mPrimaryCursorPosition < controller.mImpl->mModel->mLogicalModel->mText.Count()) &&
(keyCode == Dali::DevelKey::DALI_KEY_DELETE))
{
// Remove the character after the current cursor position
- removed = controller.RemoveText(0,
- 1,
- UPDATE_INPUT_STYLE);
+ removed = TextUpdater::RemoveText(controller, 0, 1, UPDATE_INPUT_STYLE);
}
if(removed)
}
else
{
- controller.ShowPlaceholderText();
+ PlaceholderHandler::ShowPlaceholderText(*controller.mImpl);
}
controller.mImpl->mEventData->mUpdateCursorPosition = true;
controller.mImpl->mEventData->mScrollAfterDelete = true;
{
case InputMethodContext::COMMIT:
{
- controller.InsertText(inputMethodContextEvent.predictiveString, Text::Controller::COMMIT);
+ TextUpdater::InsertText(controller, inputMethodContextEvent.predictiveString, Text::Controller::COMMIT);
requestRelayout = true;
retrieveCursor = true;
break;
}
case InputMethodContext::PRE_EDIT:
{
- controller.InsertText(inputMethodContextEvent.predictiveString, Text::Controller::PRE_EDIT);
+ TextUpdater::InsertText(controller, inputMethodContextEvent.predictiveString, Text::Controller::PRE_EDIT);
requestRelayout = true;
retrieveCursor = true;
break;
}
case InputMethodContext::DELETE_SURROUNDING:
{
- const bool textDeleted = controller.RemoveText(inputMethodContextEvent.cursorOffset,
- inputMethodContextEvent.numberOfChars,
- DONT_UPDATE_INPUT_STYLE);
+ const bool textDeleted = TextUpdater::RemoveText(controller,
+ inputMethodContextEvent.cursorOffset,
+ inputMethodContextEvent.numberOfChars,
+ DONT_UPDATE_INPUT_STYLE);
if(textDeleted)
{
}
else
{
- controller.ShowPlaceholderText();
+ PlaceholderHandler::ShowPlaceholderText(*controller.mImpl);
}
controller.mImpl->mEventData->mUpdateCursorPosition = true;
controller.mImpl->mEventData->mScrollAfterDelete = true;
controller.mImpl->SetClipboardHideEnable(false);
// Paste
- controller.PasteText(stringToPaste);
+ TextUpdater::PasteText(controller, stringToPaste);
controller.mImpl->SetClipboardHideEnable(true);
}
if(controller.mImpl->mEventData->mSelectionEnabled)
{
// Creates a SELECT event.
- controller.SelectEvent(currentCursorPosition.x, currentCursorPosition.y, SelectionType::INTERACTIVE);
+ SelectEvent(controller, currentCursorPosition.x, currentCursorPosition.y, SelectionType::INTERACTIVE);
}
break;
}
case Toolkit::TextSelectionPopup::SELECT_ALL:
{
// Creates a SELECT_ALL event
- controller.SelectEvent(0.f, 0.f, SelectionType::ALL);
+ SelectEvent(controller, 0.f, 0.f, SelectionType::ALL);
break;
}
case Toolkit::TextSelectionPopup::CLIPBOARD:
{
struct Controller::EventHandler
{
+ /// @copydoc Text::Controller::KeyboardFocusGainEvent
+ /// @param[in] controller A reference to the controller class
static void KeyboardFocusGainEvent(Controller& controller);
+
+ /// @copydoc Text::Controller::KeyboardFocusLostEvent
+ /// @param[in] controller A reference to the controller class
static void KeyboardFocusLostEvent(Controller& controller);
+
+ /// @copydoc Text::Controller::KeyEvent
+ /// @param[in] controller A reference to the controller class
static bool KeyEvent(Controller& controller, const Dali::KeyEvent& keyEvent);
+
+ /// @copydoc Text::Controller::AnchorEvent
+ /// @param[in] controller A reference to the controller class
static void AnchorEvent(Controller& controller, float x, float y);
+
+ /// @copydoc Text::Controller::TapEvent
+ /// @param[in] controller A reference to the controller class
static void TapEvent(Controller& controller, unsigned int tapCount, float x, float y);
+
+ /// @copydoc Text::Controller::PanEvent
+ /// @param[in] controller A reference to the controller class
static void PanEvent(Controller& controller, GestureState state, const Vector2& displacement);
+
+ /// @copydoc Text::Controller::LongPressEvent
+ /// @param[in] controller A reference to the controller class
static void LongPressEvent(Controller& controller, GestureState state, float x, float y);
+
+ /// @copydoc Text::Controller::SelectEvent
+ /// @param[in] controller A reference to the controller class
static void SelectEvent(Controller& controller, float x, float y, SelectionType selectType);
+
+ /**
+ * @brief Creates a selection event with a selection index.
+ *
+ * It could be called from the SelectText().
+ * The start and end parameters are passed through the event.
+ *
+ * @param[in] controller A reference to the controller class
+ * @param[in] start The start selection position.
+ * @param[in] end The end selection position.
+ * @param[in] selection type like the range.
+ */
static void SelectEvent(Controller& controller, const uint32_t start, const uint32_t end, SelectionType selectType);
+
+ /**
+ * @brief Process queued events which modify the model.
+ * @param[in] controller A reference to the controller class
+ */
static void ProcessModifyEvents(Controller& controller);
+
+ /**
+ * @brief Used to process an event queued from SetText()
+ * @param[in] controller A reference to the controller class
+ */
static void TextReplacedEvent(Controller& controller);
+
+ /**
+ * @brief Used to process an event queued from key events etc.
+ * @param[in] controller A reference to the controller class
+ */
static void TextInsertedEvent(Controller& controller);
+
+ /**
+ * @brief Used to process an event queued from backspace key etc.
+ * @param[in] controller A reference to the controller class
+ */
static void TextDeletedEvent(Controller& controller);
+
+ /**
+ * @brief Helper to KeyEvent() to handle the backspace or delete key case.
+ *
+ * @param[in] controller A reference to the controller class
+ * @param[in] keyCode The keycode for the key pressed
+ * @return True if a character was deleted.
+ */
static bool DeleteEvent(Controller& controller, int keyCode);
static InputMethodContext::CallbackData OnInputMethodContextEvent(Controller& controller,
// EXTERNAL INCLUDES
#include <cmath>
#include <dali/integration-api/debug.h>
-#include <dali/public-api/rendering/renderer.h>
+#include <dali/public-api/actors/layer.h>
#include <dali/devel-api/adaptor-framework/window-devel.h>
// INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
-#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
#include <dali-toolkit/internal/text/character-set-conversion.h>
#include <dali-toolkit/internal/text/cursor-helper-functions.h>
#include <dali-toolkit/internal/text/text-control-interface.h>
#include <dali-toolkit/internal/text/text-controller-impl-data-clearer.h>
#include <dali-toolkit/internal/text/text-controller-impl-event-handler.h>
#include <dali-toolkit/internal/text/text-controller-impl-model-updater.h>
+#include <dali-toolkit/internal/text/text-controller-placeholder-handler.h>
+#include <dali-toolkit/internal/text/text-controller-relayouter.h>
#include <dali-toolkit/internal/text/text-editable-control-interface.h>
#include <dali-toolkit/internal/text/text-enumerations-impl.h>
#include <dali-toolkit/internal/text/text-run-container.h>
Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
#endif
-struct BackgroundVertex
-{
- Vector2 mPosition; ///< Vertex posiiton
- Vector4 mColor; ///< Vertex color
-};
+constexpr float MAX_FLOAT = std::numeric_limits<float>::max();
-struct BackgroundMesh
-{
- Vector<BackgroundVertex> mVertices; ///< container of vertices
- Vector<unsigned short> mIndices; ///< container of indices
-};
+const std::string EMPTY_STRING("");
} // namespace
return numberOfWhiteSpaces;
}
+void Controller::Impl::GetText(std::string& text) const
+{
+ if(!IsShowingPlaceholderText())
+ {
+ // Retrieves the text string.
+ GetText(0u, text);
+ }
+ else
+ {
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::GetText %p empty (but showing placeholder)\n", this);
+ }
+}
+
void Controller::Impl::GetText(CharacterIndex index, std::string& text) const
{
// Get the total number of characters.
}
}
+Toolkit::DevelText::TextDirection::Type Controller::Impl::GetTextDirection()
+{
+ if(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.
+ mTextUpdateInfo.mParagraphCharacterIndex = 0u;
+ mTextUpdateInfo.mRequestedNumberOfCharacters = mModel->mLogicalModel->mText.Count();
+
+ // Make sure the model is up-to-date before layouting
+ UpdateModel(onlyOnceOperations);
+
+ Vector3 naturalSize;
+ Relayouter::DoRelayout(*this,
+ Size(MAX_FLOAT, MAX_FLOAT),
+ static_cast<OperationsMask>(onlyOnceOperations |
+ LAYOUT | REORDER | UPDATE_DIRECTION),
+ naturalSize.GetVectorXY());
+
+ // Do not do again the only once operations.
+ mOperationsPending = static_cast<OperationsMask>(mOperationsPending & ~onlyOnceOperations);
+
+ // Clear the update info. This info will be set the next time the text is updated.
+ mTextUpdateInfo.Clear();
+
+ // FullRelayoutNeeded should be true because DoRelayout is MAX_FLOAT, MAX_FLOAT.
+ mTextUpdateInfo.mFullRelayoutNeeded = true;
+
+ mUpdateTextDirection = false;
+ }
+
+ return mIsTextDirectionRTL ? Toolkit::DevelText::TextDirection::RIGHT_TO_LEFT : Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT;
+}
+
void Controller::Impl::CalculateTextUpdateIndices(Length& numberOfCharacters)
{
mTextUpdateInfo.mParagraphCharacterIndex = 0u;
return false;
}
+string Controller::Impl::GetSelectedText()
+{
+ string text;
+ if(EventData::SELECTING == mEventData->mState)
+ {
+ RetrieveSelection(text, false);
+ }
+ return text;
+}
+
+string Controller::Impl::CopyText()
+{
+ string text;
+ RetrieveSelection(text, false);
+ SendSelectionToClipboard(false); // Text not modified
+
+ mEventData->mUpdateCursorPosition = true;
+
+ RequestRelayout(); // Cursor, Handles, Selection Highlight, Popup
+
+ return text;
+}
+
+string Controller::Impl::CutText()
+{
+ string text;
+ RetrieveSelection(text, false);
+
+ if(!IsEditable())
+ {
+ return EMPTY_STRING;
+ }
+
+ SendSelectionToClipboard(true); // Synchronous call to modify text
+ mOperationsPending = ALL_OPERATIONS;
+
+ if((0u != mModel->mLogicalModel->mText.Count()) ||
+ !IsPlaceholderAvailable())
+ {
+ QueueModifyEvent(ModifyEvent::TEXT_DELETED);
+ }
+ else
+ {
+ PlaceholderHandler::ShowPlaceholderText(*this);
+ }
+
+ mEventData->mUpdateCursorPosition = true;
+ mEventData->mScrollAfterDelete = true;
+
+ RequestRelayout();
+
+ if(nullptr != mEditableControlInterface)
+ {
+ mEditableControlInterface->TextChanged(true);
+ }
+ return text;
+}
+
void Controller::Impl::SetTextSelectionRange(const uint32_t* pStart, const uint32_t* pEnd)
{
if(nullptr == mEventData)
}
}
-Actor Controller::Impl::CreateBackgroundActor()
-{
- // NOTE: Currently we only support background color for left-to-right text.
-
- Actor actor;
-
- Length numberOfGlyphs = mView.GetNumberOfGlyphs();
- if(numberOfGlyphs > 0u)
- {
- Vector<GlyphInfo> glyphs;
- glyphs.Resize(numberOfGlyphs);
-
- Vector<Vector2> positions;
- positions.Resize(numberOfGlyphs);
-
- // Get the line where the glyphs are laid-out.
- const LineRun* lineRun = mModel->mVisualModel->mLines.Begin();
- float alignmentOffset = lineRun->alignmentOffset;
- numberOfGlyphs = mView.GetGlyphs(glyphs.Begin(),
- positions.Begin(),
- alignmentOffset,
- 0u,
- numberOfGlyphs);
-
- glyphs.Resize(numberOfGlyphs);
- positions.Resize(numberOfGlyphs);
-
- const GlyphInfo* const glyphsBuffer = glyphs.Begin();
- const Vector2* const positionsBuffer = positions.Begin();
-
- BackgroundMesh mesh;
- mesh.mVertices.Reserve(4u * glyphs.Size());
- mesh.mIndices.Reserve(6u * glyphs.Size());
-
- const Vector2 textSize = mView.GetLayoutSize();
-
- const float offsetX = alignmentOffset + textSize.width * 0.5f;
- const float offsetY = textSize.height * 0.5f;
-
- const Vector4* const backgroundColorsBuffer = mView.GetBackgroundColors();
- const ColorIndex* const backgroundColorIndicesBuffer = mView.GetBackgroundColorIndices();
- const Vector4& defaultBackgroundColor = mModel->mVisualModel->IsBackgroundEnabled() ? mModel->mVisualModel->GetBackgroundColor() : Color::TRANSPARENT;
-
- Vector4 quad;
- uint32_t numberOfQuads = 0u;
- Length yLineOffset = 0;
- Length prevLineIndex = 0;
- LineIndex lineIndex;
- Length numberOfLines;
-
- for(uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i)
- {
- const GlyphInfo& glyph = *(glyphsBuffer + i);
-
- // Get the background color of the character.
- // The color index zero is reserved for the default background color (i.e. Color::TRANSPARENT)
- const bool isMarkupBackground = mView.IsMarkupBackgroundColorSet();
- const ColorIndex backgroundColorIndex = isMarkupBackground ? *(backgroundColorIndicesBuffer + i) : 0u;
- const bool isDefaultBackgroundColor = (0u == backgroundColorIndex);
- const Vector4& backgroundColor = isDefaultBackgroundColor ? defaultBackgroundColor : *(backgroundColorsBuffer + backgroundColorIndex - 1u);
-
- mModel->mVisualModel->GetNumberOfLines(i, 1, lineIndex, numberOfLines);
- Length lineHeight = lineRun[lineIndex].ascender + -(lineRun[lineIndex].descender) + lineRun[lineIndex].lineSpacing;
-
- if(lineIndex != prevLineIndex)
- {
- yLineOffset += lineHeight;
- }
-
- // Only create quads for glyphs with a background color
- if(backgroundColor != Color::TRANSPARENT)
- {
- const Vector2 position = *(positionsBuffer + i);
-
- if(i == 0u && glyphSize == 1u) // Only one glyph in the whole text
- {
- quad.x = position.x;
- quad.y = yLineOffset;
- quad.z = quad.x + std::max(glyph.advance, glyph.xBearing + glyph.width);
- quad.w = lineHeight;
- }
- else if((lineIndex != prevLineIndex) || (i == 0u)) // The first glyph in the line
- {
- quad.x = position.x;
- quad.y = yLineOffset;
- quad.z = quad.x - glyph.xBearing + glyph.advance;
- quad.w = quad.y + lineHeight;
- }
- else if(i == glyphSize - 1u) // The last glyph in the whole text
- {
- quad.x = position.x - glyph.xBearing;
- quad.y = yLineOffset;
- quad.z = quad.x + std::max(glyph.advance, glyph.xBearing + glyph.width);
- quad.w = quad.y + lineHeight;
- }
- else // The glyph in the middle of the text
- {
- quad.x = position.x - glyph.xBearing;
- quad.y = yLineOffset;
- quad.z = quad.x + glyph.advance;
- quad.w = quad.y + lineHeight;
- }
-
- BackgroundVertex vertex;
-
- // Top left
- vertex.mPosition.x = quad.x - offsetX;
- vertex.mPosition.y = quad.y - offsetY;
- vertex.mColor = backgroundColor;
- mesh.mVertices.PushBack(vertex);
-
- // Top right
- vertex.mPosition.x = quad.z - offsetX;
- vertex.mPosition.y = quad.y - offsetY;
- vertex.mColor = backgroundColor;
- mesh.mVertices.PushBack(vertex);
-
- // Bottom left
- vertex.mPosition.x = quad.x - offsetX;
- vertex.mPosition.y = quad.w - offsetY;
- vertex.mColor = backgroundColor;
- mesh.mVertices.PushBack(vertex);
-
- // Bottom right
- vertex.mPosition.x = quad.z - offsetX;
- vertex.mPosition.y = quad.w - offsetY;
- vertex.mColor = backgroundColor;
- mesh.mVertices.PushBack(vertex);
-
- // Six indices in counter clockwise winding
- mesh.mIndices.PushBack(1u + 4 * numberOfQuads);
- mesh.mIndices.PushBack(0u + 4 * numberOfQuads);
- mesh.mIndices.PushBack(2u + 4 * numberOfQuads);
- mesh.mIndices.PushBack(2u + 4 * numberOfQuads);
- mesh.mIndices.PushBack(3u + 4 * numberOfQuads);
- mesh.mIndices.PushBack(1u + 4 * numberOfQuads);
-
- numberOfQuads++;
- }
-
- if(lineIndex != prevLineIndex)
- {
- prevLineIndex = lineIndex;
- }
- }
-
- // Only create the background actor if there are glyphs with background color
- if(mesh.mVertices.Count() > 0u)
- {
- Property::Map quadVertexFormat;
- quadVertexFormat["aPosition"] = Property::VECTOR2;
- quadVertexFormat["aColor"] = Property::VECTOR4;
-
- VertexBuffer quadVertices = VertexBuffer::New(quadVertexFormat);
- quadVertices.SetData(&mesh.mVertices[0], mesh.mVertices.Size());
-
- Geometry quadGeometry = Geometry::New();
- quadGeometry.AddVertexBuffer(quadVertices);
- quadGeometry.SetIndexBuffer(&mesh.mIndices[0], mesh.mIndices.Size());
-
- if(!mShaderBackground)
- {
- mShaderBackground = Shader::New(SHADER_TEXT_CONTROLLER_BACKGROUND_SHADER_VERT, SHADER_TEXT_CONTROLLER_BACKGROUND_SHADER_FRAG);
- }
-
- Dali::Renderer renderer = Dali::Renderer::New(quadGeometry, mShaderBackground);
- renderer.SetProperty(Dali::Renderer::Property::BLEND_MODE, BlendMode::ON);
- renderer.SetProperty(Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT);
-
- actor = Actor::New();
- actor.SetProperty(Dali::Actor::Property::NAME, "TextBackgroundColorActor");
- actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
- actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
- actor.SetProperty(Actor::Property::SIZE, textSize);
- actor.SetProperty(Actor::Property::COLOR_MODE, USE_OWN_MULTIPLY_PARENT_COLOR);
- actor.AddRenderer(renderer);
- }
- }
-
- return actor;
-}
-
void Controller::Impl::RelayoutForNewLineSize()
{
// relayout all characters
Length GetNumberOfWhiteSpaces(CharacterIndex index) const;
/**
+ * @brief Retrieve any text previously set.
+ *
+ * @param[out] text A string of UTF-8 characters.
+ */
+ void GetText(std::string& text) const;
+
+ /**
* @brief Retrieve any text previously set starting from the given @p index.
*
* @param[in] index The character index from where to retrieve the text.
Dali::LayoutDirection::Type GetLayoutDirection(Dali::Actor& actor) const;
/**
+ * @brief Checks text direction.
+ * @return The text direction.
+ */
+ Toolkit::DevelText::TextDirection::Type GetTextDirection();
+
+ /**
* @brief Calculates the start character index of the first paragraph to be updated and
* the end character index of the last paragraph to be updated.
*
bool SetPrimaryCursorPosition(CharacterIndex index, bool focused);
/**
+ * @copydoc Text::SelectableControlInterface::GetSelectedText()
+ */
+ string GetSelectedText();
+
+ /**
+ * @copydoc Text::EditableControlInterface::CopyText()
+ */
+ string CopyText();
+
+ /**
+ * @copydoc Text::EditableControlInterface::CutText()
+ */
+ string CutText();
+
+ /**
* @copydoc Text::SelectableControlInterface::SetTextSelectionRange()
*/
void SetTextSelectionRange(const uint32_t* pStart, const uint32_t* pEndf);
void ScrollTextToMatchCursor();
/**
- * @brief Create an actor that renders the text background color
- *
- * @return the created actor or an empty handle if no background color needs to be rendered.
- */
- Actor CreateBackgroundActor();
-
- /**
* @brief fill needed relayout parameters when line size is changed & request relayout.
*/
void RelayoutForNewLineSize();
if(controller.mImpl->IsShowingPlaceholderText() ||
(0u == controller.mImpl->mModel->mLogicalModel->mText.Count()))
{
- controller.ShowPlaceholderText();
+ ShowPlaceholderText(*controller.mImpl);
}
}
if(controller.mImpl->IsShowingPlaceholderText() ||
(0u == controller.mImpl->mModel->mLogicalModel->mText.Count()))
{
- controller.ShowPlaceholderText();
+ ShowPlaceholderText(*controller.mImpl);
}
}
}
}
}
-void Controller::PlaceholderHandler::ShowPlaceholderText(Controller& controller)
+void Controller::PlaceholderHandler::ShowPlaceholderText(Controller::Impl& impl)
{
- Controller::Impl& impl = *controller.mImpl;
-
if(impl.IsPlaceholderAvailable())
{
EventData*& eventData = impl.mEventData;
static const Vector4& GetPlaceholderTextColor(const Controller& controller);
static void SetPlaceholderProperty(Controller& controller, const Property::Map& map);
static void GetPlaceholderProperty(Controller& controller, Property::Map& map);
- static void ShowPlaceholderText(Controller& controller);
+ static void ShowPlaceholderText(Controller::Impl& impl);
static void CreatePlaceholderFont(Controller& controller);
};
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/layouts/layout-parameters.h>
+#include <dali-toolkit/internal/text/text-controller-event-handler.h>
#include <dali-toolkit/internal/text/text-controller-impl.h>
namespace
// Store the actual control's size to restore later.
const Size actualControlSize = visualModel->mControlSize;
- DoRelayout(controller,
+ DoRelayout(impl,
requestedControllerSize,
static_cast<OperationsMask>(onlyOnceOperations |
requestedOperationsMask),
Vector3 naturalSizeVec3;
// Make sure the model is up-to-date before layouting
- controller.ProcessModifyEvents();
+ EventHandler::ProcessModifyEvents(controller);
Controller::Impl& impl = *controller.mImpl;
ModelPtr& model = impl.mModel;
// Make sure the model is up-to-date before layouting
impl.UpdateModel(onlyOnceOperations);
- DoRelayout(controller,
+ DoRelayout(impl,
Size(layoutSize.width, MAX_FLOAT),
static_cast<OperationsMask>(onlyOnceOperations | LAYOUT),
textSize);
DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::GetHeightForWidth %p width %f\n", &controller, width);
// Make sure the model is up-to-date before layouting
- controller.ProcessModifyEvents();
+ EventHandler::ProcessModifyEvents(controller);
Controller::Impl& impl = *controller.mImpl;
ModelPtr& model = impl.mModel;
}
// Make sure the model is up-to-date before layouting.
- controller.ProcessModifyEvents();
+ EventHandler::ProcessModifyEvents(controller);
bool updated = impl.UpdateModel(operationsPending);
// Layout the text.
Size layoutSize;
- updated = DoRelayout(controller, size, operationsPending, layoutSize) || updated;
+ updated = DoRelayout(impl, size, operationsPending, layoutSize) || updated;
if(updated)
{
if(!isEditable || !controller.IsMultiLineEnabled())
{
// After doing the text layout, the vertical offset to place the actor in the desired position can be calculated.
- controller.CalculateVerticalOffset(size);
+ CalculateVerticalOffset(controller, size);
}
if(isEditable)
return updateTextType;
}
-bool Controller::Relayouter::DoRelayout(Controller& controller, const Size& size, OperationsMask operationsRequired, Size& layoutSize)
+bool Controller::Relayouter::DoRelayout(Controller::Impl& impl, const Size& size, OperationsMask operationsRequired, Size& layoutSize)
{
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::DoRelayout %p size %f,%f\n", &controller, size.width, size.height);
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::Relayouter::DoRelayout %p size %f,%f\n", &impl, size.width, size.height);
bool viewUpdated(false);
- Controller::Impl& impl = *controller.mImpl;
-
// Calculate the operations to be done.
const OperationsMask operations = static_cast<OperationsMask>(impl.mOperationsPending & operationsRequired);
(lastIndex > charactersToGlyph.Count() && charactersToGlyph.Count() > 0u))
{
std::string currentText;
- controller.GetText(currentText);
+ impl.GetText(currentText);
DALI_LOG_ERROR("Controller::DoRelayout: Attempting to access invalid buffer\n");
DALI_LOG_ERROR("Current text is: %s\n", currentText.c_str());
}
#if defined(DEBUG_ENABLED)
std::string currentText;
- controller.GetText(currentText);
- DALI_LOG_INFO(gLogFilter, Debug::Concise, "Controller::DoRelayout [%p] mImpl->mIsTextDirectionRTL[%s] [%s]\n", &controller, (impl.mIsTextDirectionRTL) ? "true" : "false", currentText.c_str());
+ impl.GetText(currentText);
+ DALI_LOG_INFO(gLogFilter, Debug::Concise, "Controller::Relayouter::DoRelayout [%p] mImpl->mIsTextDirectionRTL[%s] [%s]\n", &impl, (impl.mIsTextDirectionRTL) ? "true" : "false", currentText.c_str());
#endif
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::DoRelayout, view updated %s\n", (viewUpdated ? "true" : "false"));
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::Relayouter::DoRelayout, view updated %s\n", (viewUpdated ? "true" : "false"));
return viewUpdated;
}
/**
* @brief Called by the Controller to do certain operations when relayouting.
*
- * @param[in] controller A reference to the controller class
+ * @param[in] impl A reference to the controller impl class
* @param[in] size The size to set
* @param[in] operationsRequired The operations we need to do
* @param[in/out] layoutSize The Layout size which can be updated depending on the result of the performed operations
* @return
*/
- static bool DoRelayout(Controller& controller, const Size& size, OperationsMask operationsRequired, Size& layoutSize);
+
+ static bool DoRelayout(Controller::Impl& impl, const Size& size, OperationsMask operationsRequired, Size& layoutSize);
/**
* @brief Called by the Controller to calculate the veritcal offset give the control size.
#include <dali-toolkit/internal/text/character-set-conversion.h>
#include <dali-toolkit/internal/text/markup-processor.h>
#include <dali-toolkit/internal/text/text-controller-impl.h>
+#include <dali-toolkit/internal/text/text-controller-placeholder-handler.h>
#include <dali-toolkit/internal/text/text-editable-control-interface.h>
namespace
}
else
{
- controller.ShowPlaceholderText();
+ PlaceholderHandler::ShowPlaceholderText(impl);
}
unsigned int oldCursorPos = (nullptr != eventData ? eventData->mPrimaryCursorPosition : 0);
impl.IsPlaceholderAvailable())
{
// Show place-holder if empty after removing the pre-edit text
- controller.ShowPlaceholderText();
+ PlaceholderHandler::ShowPlaceholderText(impl);
eventData->mUpdateCursorPosition = true;
impl.ClearPreEditFlag();
}
/// @param[in] controller The controller
static void SetText(Controller& controller, const std::string& text);
- /// @copydoc Text::Contoller::InsertText
- /// @param[in] controller The controller
+ /**
+ * @brief Called by editable UI controls when key events are received.
+ *
+ * @param[in] controller The controller
+ * @param[in] text The text to insert.
+ * @param[in] type Used to distinguish between regular key events and InputMethodContext events.
+ */
static void InsertText(Controller& controller, const std::string& text, Controller::InsertType type);
- /// @copydoc Text::Contoller::PasteText
+ /// @copydoc Text::EditableControlInterface::PasteText()
/// @param[in] controller The controller
static void PasteText(Controller& controller, const std::string& stringToPaste);
- /// @copydoc Text::Contoller::RemoveText
- /// @param[in] controller The controller
+ /**
+ * @brief Remove a given number of characters
+ *
+ * When predictve text is used the pre-edit text is removed and inserted again with the new characters.
+ * The UpdateInputStyleType @type parameter if set to DONT_UPDATE_INPUT_STYLE avoids to update the input
+ * style when pre-edit text is removed.
+ *
+ * @param[in] controller The controller
+ * @param[in] cursorOffset Start position from the current cursor position to start deleting characters.
+ * @param[in] numberOfCharacters The number of characters to delete from the cursorOffset.
+ * @param[in] type Whether to update the input style.
+ * @return True if the remove was successful.
+ */
static bool RemoveText(Controller& controller, int cursorOffset, int numberOfCharacters, UpdateInputStyleType type);
- /// @copydoc Text::Contoller::RemoveSelectedText
- /// @param[in] controller The controller
+ /**
+ * @brief Checks if text is selected and if so removes it.
+ * @param[in] controller The controller
+ * @return true if text was removed
+ */
static bool RemoveSelectedText(Controller& controller);
- /// @copydoc Text::Contoller::ResetText
- /// @param[in] controller The controller
+ /**
+ * @brief Used to remove the text included the placeholder text.
+ * @param[in] controller The controller
+ */
static void ResetText(Controller& controller);
- /// @copydoc Text::Contoller::InsertTextAnchor
- /// @param[in] controller The controller
+ /**
+ * @brief Update anchor position from given number of inserted characters.
+ *
+ * @param[in] controller The controller
+ * @param[in] numberOfCharacters The number of inserted characters.
+ * @param[in] previousCursorIndex A cursor position before event occurs.
+ */
static void InsertTextAnchor(Controller& controller, int numberOfCharacters, CharacterIndex previousCursorIndex);
- /// @copydoc Text::Contoller::RemoveTextAnchor
- /// @param[in] controller The controller
+ /**
+ * @brief Update anchor position from given number of removed characters.
+ *
+ * @param[in] controller The controller
+ * @param[in] cursorOffset Start position from the current cursor position to start deleting characters.
+ * @param[in] numberOfCharacters The number of removed characters.
+ * @param[in] previousCursorIndex A cursor position before event occurs.
+ */
static void RemoveTextAnchor(Controller& controller, int cursorOffset, int numberOfCharacters, CharacterIndex previousCursorIndex);
};
// 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>
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::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)
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::ResetCursorPosition(CharacterIndex cursorIndex)
{
// Reset the cursor position
Actor Controller::CreateBackgroundActor()
{
- return mImpl->CreateBackgroundActor();
+ return CreateControllerBackgroundActor(mImpl->mView, mImpl->mModel->mVisualModel, mImpl->mShaderBackground);
}
void Controller::GetAnchorActors(std::vector<Toolkit::TextAnchor>& anchorActors)
void SelectEvent(float x, float y, SelectionType selection);
/**
- * @brief Creates a selection event with a selection index.
- *
- * It could be called from the SelectText().
- * The start and end parameters are passed through the event.
- *
- * @param[in] start The start selection position.
- * @param[in] end The end selection position.
- * @param[in] selection type like the range.
- */
- void SelectEvent(const uint32_t start, const uint32_t end, SelectionType selection);
-
- /**
* @copydoc Text::SelectableControlInterface::SetTextSelectionRange()
*/
void SetTextSelectionRange(const uint32_t* start, const uint32_t* end);
*/
void DisplayTimeExpired() override;
-private: // Update.
- /**
- * @brief Called by editable UI controls when key events are received.
- *
- * @param[in] text The text to insert.
- * @param[in] type Used to distinguish between regular key events and InputMethodContext events.
- */
- void InsertText(const std::string& text, InsertType type);
-
- /**
- * @copydoc Text::EditableControlInterface::PasteText()
- */
- void PasteText(const std::string& stringToPaste);
-
- /**
- * @brief Remove a given number of characters
- *
- * When predictve text is used the pre-edit text is removed and inserted again with the new characters.
- * The UpdateInputStyleType @type parameter if set to DONT_UPDATE_INPUT_STYLE avoids to update the input
- * style when pre-edit text is removed.
- *
- * @param[in] cursorOffset Start position from the current cursor position to start deleting characters.
- * @param[in] numberOfCharacters The number of characters to delete from the cursorOffset.
- * @param[in] type Whether to update the input style.
- * @return True if the remove was successful.
- */
- bool RemoveText(int cursorOffset,
- int numberOfCharacters,
- UpdateInputStyleType type);
-
- /**
- * @brief Checks if text is selected and if so removes it.
- * @return true if text was removed
- */
- bool RemoveSelectedText();
-
- /**
- * @brief Update anchor position from given number of inserted characters.
- *
- * @param[in] numberOfCharacters The number of inserted characters.
- * @param[in] previousCursorIndex A cursor position before event occurs.
- */
- void InsertTextAnchor(int numberOfCharacters,
- CharacterIndex previousCursorIndex);
-
- /**
- * @brief Update anchor position from given number of removed characters.
- *
- * @param[in] cursorOffset Start position from the current cursor position to start deleting characters.
- * @param[in] numberOfCharacters The number of removed characters.
- * @param[in] previousCursorIndex A cursor position before event occurs.
- */
- void RemoveTextAnchor(int cursorOffset,
- int numberOfCharacters,
- CharacterIndex previousCursorIndex);
-
-private: // Relayout.
- /**
- * @brief Lays-out the text.
- *
- * GetNaturalSize(), GetHeightForWidth() and Relayout() calls this method.
- *
- * @param[in] size A the size of a bounding box to layout text within.
- * @param[in] operations The layout operations which need to be done.
- * @param[out] layoutSize The size of the laid-out text.
- */
- bool DoRelayout(const Size& size,
- OperationsMask operations,
- Size& layoutSize);
-
- /**
- * @brief Calulates the vertical offset to align the text inside the bounding box.
- *
- * @param[in] size The size of the bounding box.
- */
- void CalculateVerticalOffset(const Size& size);
-
-private: // Events.
- /**
- * @brief Process queued events which modify the model.
- */
- void ProcessModifyEvents();
-
- /**
- * @brief Used to process an event queued from SetText()
- */
- void TextReplacedEvent();
-
- /**
- * @brief Used to process an event queued from key events etc.
- */
- void TextInsertedEvent();
-
- /**
- * @brief Used to process an event queued from backspace key etc.
- */
- void TextDeletedEvent();
-
- /**
- * @brief Helper to KeyEvent() to handle the backspace or delete key case.
- *
- * @param[in] keyCode The keycode for the key pressed
- * @return True if a character was deleted.
- */
- bool DeleteEvent(int keyCode);
-
-private: // Helpers.
- /**
- * @brief Used to remove the text included the placeholder text.
- */
- void ResetText();
-
- /**
- * @brief Helper to show the place holder text..
- */
- void ShowPlaceholderText();
-
private: // Private contructors & copy operator.
/**
* @brief Private constructor.