/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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/devel-api/common/stage.h>
#include <dali/devel-api/object/property-helper-devel.h>
#include <dali/integration-api/debug.h>
+#include <dali/public-api/actors/layer.h>
#include <dali/public-api/adaptor-framework/key.h>
#include <dali/public-api/common/dali-common.h>
#include <dali/public-api/object/type-registry-helper.h>
#include <cstring>
// INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
#include <dali-toolkit/devel-api/controls/control-devel.h>
#include <dali-toolkit/devel-api/controls/text-controls/text-field-devel.h>
-#include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
#include <dali-toolkit/devel-api/text/rendering-backend.h>
+#include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
#include <dali-toolkit/internal/controls/text-controls/text-field-property-handler.h>
+#include <dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h>
#include <dali-toolkit/internal/styling/style-manager-impl.h>
#include <dali-toolkit/internal/text/rendering/text-backend.h>
#include <dali-toolkit/internal/text/text-effects-style.h>
DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextField, "selectedTextEnd", INTEGER, SELECTED_TEXT_END )
DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextField, "enableEditing", BOOLEAN, ENABLE_EDITING )
DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextField, "fontSizeScale", FLOAT, FONT_SIZE_SCALE )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextField, "enableFontSizeScale", BOOLEAN, ENABLE_FONT_SIZE_SCALE )
DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextField, "primaryCursorPosition", INTEGER, PRIMARY_CURSOR_POSITION )
DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextField, "grabHandleColor", VECTOR4, GRAB_HANDLE_COLOR )
DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextField, "inputFilter", MAP, INPUT_FILTER )
DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextField, "ellipsisPosition", INTEGER, ELLIPSIS_POSITION )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextField, "strikethrough", MAP, STRIKETHROUGH )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextField, "inputStrikethrough", MAP, INPUT_STRIKETHROUGH )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextField, "characterSpacing", FLOAT, CHARACTER_SPACING )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextField, "selectionPopupStyle", MAP, SELECTION_POPUP_STYLE )
DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "textChanged", SIGNAL_TEXT_CHANGED )
DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "maxLengthReached", SIGNAL_MAX_LENGTH_REACHED )
DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "cursorPositionChanged", SIGNAL_CURSOR_POSITION_CHANGED)
DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "selectionChanged", SIGNAL_SELECTION_CHANGED )
DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "selectionCleared", SIGNAL_SELECTION_CLEARED )
+DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "selectionStarted", SIGNAL_SELECTION_STARTED )
DALI_TYPE_REGISTRATION_END()
// clang-format on
+Toolkit::TextField::InputStyle::Mask ConvertInputStyle(Text::InputStyle::Mask inputStyleMask)
+{
+ Toolkit::TextField::InputStyle::Mask fieldInputStyleMask = Toolkit::TextField::InputStyle::NONE;
+
+ if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_COLOR))
+ {
+ fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::COLOR);
+ }
+ if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_FAMILY))
+ {
+ fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_FAMILY);
+ }
+ if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_POINT_SIZE))
+ {
+ fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::POINT_SIZE);
+ }
+ if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_WEIGHT))
+ {
+ fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_STYLE);
+ }
+ if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_WIDTH))
+ {
+ fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_STYLE);
+ }
+ if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_SLANT))
+ {
+ fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_STYLE);
+ }
+ if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_UNDERLINE))
+ {
+ fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::UNDERLINE);
+ }
+ if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_SHADOW))
+ {
+ fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::SHADOW);
+ }
+ if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_EMBOSS))
+ {
+ fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::EMBOSS);
+ }
+ if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_OUTLINE))
+ {
+ fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::OUTLINE);
+ }
+ return fieldInputStyleMask;
+}
+
} // namespace
Toolkit::TextField TextField::New()
fieldImpl.SelectionClearedSignal().Connect(tracker, functor);
}
}
+ else if(0 == strcmp(signalName.c_str(), SIGNAL_SELECTION_STARTED))
+ {
+ if(field)
+ {
+ Internal::TextField& fieldImpl(GetImpl(field));
+ fieldImpl.SelectionStartedSignal().Connect(tracker, functor);
+ }
+ }
else
{
// signalName does not match any signal
return mSelectionClearedSignal;
}
+DevelTextField::SelectionStartedSignalType& TextField::SelectionStartedSignal()
+{
+ return mSelectionStartedSignal;
+}
+
+void TextField::OnAccessibilityStatusChanged()
+{
+ CommonTextUtils::SynchronizeTextAnchorsInParent(Self(), mController, mAnchorActors);
+}
+
void TextField::OnInitialize()
{
Actor self = Self();
self.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT);
self.OnSceneSignal().Connect(this, &TextField::OnSceneConnect);
- //Enable highightability
- self.SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
-
DevelControl::SetInputMethodContext(*this, mInputMethodContext);
if(Dali::Toolkit::TextField::EXCEED_POLICY_CLIP == mExceedPolicy)
EnableClipping();
}
- DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) {
- return std::unique_ptr<Dali::Accessibility::Accessible>(
- new AccessibleImpl(actor, Dali::Accessibility::Role::ENTRY));
- });
+ // Accessibility
+ self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::ENTRY);
+ self.SetProperty(DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
+
+ Accessibility::Bridge::EnabledSignal().Connect(this, &TextField::OnAccessibilityStatusChanged);
+ Accessibility::Bridge::DisabledSignal().Connect(this, &TextField::OnAccessibilityStatusChanged);
+}
+
+DevelControl::ControlAccessible* TextField::CreateAccessibleObject()
+{
+ return new TextFieldAccessible(Self());
}
void TextField::OnStyleChange(Toolkit::StyleManager styleManager, StyleChange::Type change)
}
}
+void TextField::OnPropertySet(Property::Index index, const Property::Value& propertyValue)
+{
+ DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField::OnPropertySet index[%d]\n", index);
+
+ switch(index)
+ {
+ case DevelActor::Property::USER_INTERACTION_ENABLED:
+ {
+ const bool enabled = propertyValue.Get<bool>();
+ mController->SetUserInteractionEnabled(enabled);
+ if(mStencil)
+ {
+ float opacity = enabled ? 1.0f : mController->GetDisabledColorOpacity();
+ mStencil.SetProperty(Actor::Property::OPACITY, opacity);
+ }
+ break;
+ }
+ default:
+ {
+ Control::OnPropertySet(index, propertyValue); // up call to control for non-handled properties
+ break;
+ }
+ }
+}
+
void TextField::OnRelayout(const Vector2& size, RelayoutContainer& container)
{
DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField OnRelayout\n");
mActiveLayer.SetProperty(Actor::Property::POSITION, Vector2(padding.start, padding.top));
ResizeActor(mActiveLayer, contentSize);
}
+ if(mCursorLayer)
+ {
+ mCursorLayer.SetProperty(Actor::Property::POSITION, Vector2(padding.start, padding.top));
+ ResizeActor(mCursorLayer, contentSize);
+ }
// If there is text changed, callback is called.
if(mTextChanged)
EmitCursorPositionChangedSignal();
}
+ if(mSelectionStarted)
+ {
+ EmitSelectionStartedSignal();
+ }
+
if(mSelectionChanged)
{
EmitSelectionChangedSignal();
void TextField::RenderText(Text::Controller::UpdateTextType updateTextType)
{
- Actor renderableActor;
-
- if(Text::Controller::NONE_UPDATED != (Text::Controller::MODEL_UPDATED & updateTextType))
- {
- if(mRenderer)
- {
- Dali::Toolkit::TextField handle = Dali::Toolkit::TextField(GetOwner());
-
- renderableActor = mRenderer->Render(mController->GetView(),
- handle,
- Property::INVALID_INDEX, // Animatable property not supported
- mAlignmentOffset,
- DepthIndex::CONTENT);
- }
-
- if(renderableActor != mRenderableActor)
- {
- UnparentAndReset(mBackgroundActor);
- UnparentAndReset(mRenderableActor);
- mRenderableActor = renderableActor;
-
- if(mRenderableActor)
- {
- mBackgroundActor = mController->CreateBackgroundActor();
- }
- }
- }
-
- if(mRenderableActor)
- {
- const Vector2& scrollOffset = mController->GetTextModel()->GetScrollPosition();
-
- float renderableActorPositionX, renderableActorPositionY;
-
- if(mStencil)
- {
- renderableActorPositionX = scrollOffset.x + mAlignmentOffset;
- renderableActorPositionY = scrollOffset.y;
- }
- else
- {
- Extents padding;
- padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
-
- // Support Right-To-Left of padding
- Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>(Self().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
- if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection)
- {
- std::swap(padding.start, padding.end);
- }
-
- renderableActorPositionX = scrollOffset.x + mAlignmentOffset + padding.start;
- renderableActorPositionY = scrollOffset.y + padding.top;
- }
-
- mRenderableActor.SetProperty(Actor::Property::POSITION, Vector2(renderableActorPositionX, renderableActorPositionY));
-
- // Make sure the actors are parented correctly with/without clipping
- Actor self = mStencil ? mStencil : Self();
-
- Actor highlightActor;
-
- for(std::vector<Actor>::iterator it = mClippingDecorationActors.begin(),
- endIt = mClippingDecorationActors.end();
- it != endIt;
- ++it)
- {
- self.Add(*it);
- it->LowerToBottom();
-
- if(it->GetProperty<std::string>(Dali::Actor::Property::NAME) == "HighlightActor")
- {
- highlightActor = *it;
- }
- }
- mClippingDecorationActors.clear();
-
- self.Add(mRenderableActor);
-
- if(mBackgroundActor)
- {
- if(mDecorator && mDecorator->IsHighlightVisible())
- {
- self.Add(mBackgroundActor);
- mBackgroundActor.SetProperty(Actor::Property::POSITION, Vector2(renderableActorPositionX, renderableActorPositionY)); // In text field's coords.
- mBackgroundActor.LowerBelow(highlightActor);
- }
- else
- {
- mRenderableActor.Add(mBackgroundActor);
- mBackgroundActor.SetProperty(Actor::Property::POSITION, Vector2(0.0f, 0.0f)); // In renderable actor's coords.
- mBackgroundActor.LowerToBottom();
- }
- }
- }
+ CommonTextUtils::RenderText(Self(), mRenderer, mController, mDecorator, mAlignmentOffset, mRenderableActor, mBackgroundActor, mCursorLayer, mStencil, mClippingDecorationActors, mAnchorActors, updateTextType);
}
void TextField::OnKeyInputFocusGained()
notifier.ContentSelectedSignal().Connect(this, &TextField::OnClipboardTextSelected);
}
- mController->KeyboardFocusGainEvent(); // Called in the case of no virtual keyboard to trigger this event
+ if(IsEditable() && mController->IsUserInteractionEnabled())
+ {
+ mController->KeyboardFocusGainEvent(); // Called in the case of no virtual keyboard to trigger this event
+ }
EmitKeyInputFocusSignal(true); // Calls back into the Control hence done last.
}
mController->TapEvent(gesture.GetNumberOfTaps(), localPoint.x - padding.start, localPoint.y - padding.top);
mController->AnchorEvent(localPoint.x - padding.start, localPoint.y - padding.top);
+ Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get();
+ if (keyboardFocusManager)
+ {
+ keyboardFocusManager.SetCurrentFocusActor(Self());
+ }
SetKeyInputFocus();
}
void TextField::OnPan(const PanGesture& gesture)
{
mController->PanEvent(gesture.GetState(), gesture.GetDisplacement());
+ if(gesture.GetState() == GestureState::STARTED && !mController->IsScrollable(gesture.GetDisplacement()))
+ {
+ Dali::DevelActor::SetNeedGesturePropagation(Self(), true);
+ }
}
void TextField::OnLongPress(const LongPressGesture& gesture)
// Make sure ClearKeyInputFocus when only key is up
if(event.GetState() == KeyEvent::UP)
{
+ Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get();
+ if (keyboardFocusManager)
+ {
+ keyboardFocusManager.ClearFocus();
+ }
ClearKeyInputFocus();
}
void TextField::TextInserted(unsigned int position, unsigned int length, const std::string& content)
{
- if(Accessibility::IsUp())
- {
- Control::Impl::GetAccessibilityObject(Self())->EmitTextInserted(position, length, content);
- }
+ GetAccessibleObject()->EmitTextInserted(position, length, content);
}
void TextField::TextDeleted(unsigned int position, unsigned int length, const std::string& content)
{
- if(Accessibility::IsUp())
- {
- Control::Impl::GetAccessibilityObject(Self())->EmitTextDeleted(position, length, content);
- }
+ GetAccessibleObject()->EmitTextDeleted(position, length, content);
}
void TextField::CursorPositionChanged(unsigned int oldPosition, unsigned int newPosition)
{
- if(Accessibility::IsUp())
- {
- Control::Impl::GetAccessibilityObject(Self())->EmitTextCursorMoved(newPosition);
- }
+ GetAccessibleObject()->EmitTextCursorMoved(newPosition);
if((oldPosition != newPosition) && !mCursorPositionChanged)
{
void TextField::InputStyleChanged(Text::InputStyle::Mask inputStyleMask)
{
Dali::Toolkit::TextField handle(GetOwner());
-
- Toolkit::TextField::InputStyle::Mask fieldInputStyleMask = Toolkit::TextField::InputStyle::NONE;
-
- if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_COLOR))
- {
- fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::COLOR);
- }
- if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_FAMILY))
- {
- fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_FAMILY);
- }
- if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_POINT_SIZE))
- {
- fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::POINT_SIZE);
- }
- if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_WEIGHT))
- {
- fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_STYLE);
- }
- if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_WIDTH))
- {
- fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_STYLE);
- }
- if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_FONT_SLANT))
- {
- fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::FONT_STYLE);
- }
- if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_UNDERLINE))
- {
- fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::UNDERLINE);
- }
- if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_SHADOW))
- {
- fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::SHADOW);
- }
- if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_EMBOSS))
- {
- fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::EMBOSS);
- }
- if(InputStyle::NONE != static_cast<InputStyle::Mask>(inputStyleMask & InputStyle::INPUT_OUTLINE))
- {
- fieldInputStyleMask = static_cast<Toolkit::TextField::InputStyle::Mask>(fieldInputStyleMask | Toolkit::TextField::InputStyle::OUTLINE);
- }
-
- mInputStyleChangedSignal.Emit(handle, fieldInputStyleMask);
+ mInputStyleChangedSignal.Emit(handle, ConvertInputStyle(inputStyleMask));
}
void TextField::AnchorClicked(const std::string& href)
mSelectionCleared = false;
}
+void TextField::EmitSelectionStartedSignal()
+{
+ Dali::Toolkit::TextField handle(GetOwner());
+ mSelectionStartedSignal.Emit(handle);
+ mSelectionStarted = false;
+}
+
void TextField::SelectionChanged(uint32_t oldStart, uint32_t oldEnd, uint32_t newStart, uint32_t newEnd)
{
if(((oldStart != newStart) || (oldEnd != newEnd)) && !mSelectionChanged)
{
mSelectionCleared = true;
}
+ else
+ {
+ if(oldStart == oldEnd)
+ {
+ mSelectionStarted = true;
+ }
+ }
mSelectionChanged = true;
mOldSelectionStart = oldStart;
}
}
-void TextField::AddDecoration(Actor& actor, bool needsClipping)
+void TextField::AddDecoration(Actor& actor, DecorationType type, bool needsClipping)
{
if(actor)
{
{
mClippingDecorationActors.push_back(actor);
}
- else
+
+ // If the actor is a layer type, add it.
+ if(type == DecorationType::ACTIVE_LAYER)
+ {
+ AddLayer(mActiveLayer, actor);
+ }
+ else if(type == DecorationType::CURSOR_LAYER)
{
- actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
- actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
- Self().Add(actor);
- mActiveLayer = actor;
+ AddLayer(mCursorLayer, actor);
}
}
}
+void TextField::AddLayer(Actor& layer, Actor& actor)
+{
+ actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ Self().Add(actor);
+ layer = actor;
+}
+
void TextField::GetControlBackgroundColor(Vector4& color) const
{
Property::Value propValue = Self().GetProperty(Toolkit::Control::Property::BACKGROUND);
mSelectionCleared(false),
mOldPosition(0u),
mOldSelectionStart(0u),
- mOldSelectionEnd(0u)
+ mOldSelectionEnd(0u),
+ mSelectionStarted(false)
{
}
}
}
-std::string TextField::AccessibleImpl::GetName()
-{
- auto self = Toolkit::TextField::DownCast(Self());
- return self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-}
-
-std::string TextField::AccessibleImpl::GetText(size_t startOffset, size_t endOffset)
+Vector<Vector2> TextField::GetTextSize(const uint32_t startIndex, const uint32_t endIndex) const
{
- if(endOffset <= startOffset)
- {
- return {};
- }
-
- auto self = Toolkit::TextField::DownCast(Self());
- auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-
- if(startOffset > text.size() || endOffset > text.size())
- {
- return {};
- }
-
- return text.substr(startOffset, endOffset - startOffset);
+ return mController->GetTextSize(startIndex, endIndex);
}
-size_t TextField::AccessibleImpl::GetCharacterCount()
+Vector<Vector2> TextField::GetTextPosition(const uint32_t startIndex, const uint32_t endIndex) const
{
- auto self = Toolkit::TextField::DownCast(Self());
- auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-
- return text.size();
+ return mController->GetTextPosition(startIndex, endIndex);
}
-size_t TextField::AccessibleImpl::GetCursorOffset()
+std::string TextField::TextFieldAccessible::GetName() const
{
- auto self = Toolkit::TextField::DownCast(Self());
- return Dali::Toolkit::GetImpl(self).GetTextController()->GetCursorPosition();
-}
-
-bool TextField::AccessibleImpl::SetCursorOffset(size_t offset)
-{
- auto self = Toolkit::TextField::DownCast(Self());
- auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
- if(offset > text.size())
- {
- return false;
- }
-
- auto& selfImpl = Dali::Toolkit::GetImpl(self);
- selfImpl.GetTextController()->ResetCursorPosition(offset);
- selfImpl.RequestTextRelayout();
-
- return true;
-}
-
-Dali::Accessibility::Range TextField::AccessibleImpl::GetTextAtOffset(
- size_t offset, Dali::Accessibility::TextBoundary boundary)
-{
- auto self = Toolkit::TextField::DownCast(Self());
- auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
- auto textSize = text.size();
-
- auto range = Dali::Accessibility::Range{};
-
- switch(boundary)
- {
- case Dali::Accessibility::TextBoundary::CHARACTER:
- {
- if(offset < textSize)
- {
- range.content = text[offset];
- range.startOffset = offset;
- range.endOffset = offset + 1;
- }
- break;
- }
- case Dali::Accessibility::TextBoundary::WORD:
- case Dali::Accessibility::TextBoundary::LINE:
- {
- auto textString = text.c_str();
- auto breaks = std::vector<char>(textSize, 0);
-
- if(boundary == Dali::Accessibility::TextBoundary::WORD)
- {
- Accessibility::Accessible::FindWordSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
- }
- else
- {
- Accessibility::Accessible::FindLineSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
- }
-
- auto index = 0u;
- auto counter = 0u;
- while(index < textSize && counter <= offset)
- {
- auto start = index;
- if(breaks[index])
- {
- while(breaks[index])
- {
- index++;
- }
- counter++;
- }
- else
- {
- if(boundary == Dali::Accessibility::TextBoundary::WORD)
- {
- index++;
- }
- if(boundary == Dali::Accessibility::TextBoundary::LINE)
- {
- counter++;
- }
- }
-
- if((counter > 0) && ((counter - 1) == offset))
- {
- range.content = text.substr(start, index - start + 1);
- range.startOffset = start;
- range.endOffset = index + 1;
- }
-
- if(boundary == Dali::Accessibility::TextBoundary::LINE)
- {
- index++;
- }
- }
- break;
- }
- case Dali::Accessibility::TextBoundary::SENTENCE:
- {
- /* not supported by default */
- break;
- }
- case Dali::Accessibility::TextBoundary::PARAGRAPH:
- {
- /* Paragraph is not supported by libunibreak library */
- break;
- }
- default:
- break;
- }
-
- return range;
-}
-
-Dali::Accessibility::Range TextField::AccessibleImpl::GetRangeOfSelection(size_t selectionIndex)
-{
- // Since DALi supports only one selection indexes higher than 0 are ignored
- if(selectionIndex > 0)
+ if(IsHiddenInput())
{
return {};
}
- auto self = Toolkit::TextField::DownCast(Self());
- auto controller = Dali::Toolkit::GetImpl(self).GetTextController();
- std::string value{};
- controller->RetrieveSelection(value);
- auto indices = controller->GetSelectionIndexes();
-
- return {static_cast<size_t>(indices.first), static_cast<size_t>(indices.second), value};
+ return GetWholeText();
}
-bool TextField::AccessibleImpl::RemoveSelection(size_t selectionIndex)
+const std::vector<Toolkit::TextAnchor>& TextField::TextFieldAccessible::GetTextAnchors() const
{
- // Since DALi supports only one selection indexes higher than 0 are ignored
- if(selectionIndex > 0)
- {
- return false;
- }
-
auto self = Toolkit::TextField::DownCast(Self());
- Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(0, 0);
- return true;
-}
-bool TextField::AccessibleImpl::SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset)
-{
- // Since DALi supports only one selection indexes higher than 0 are ignored
- if(selectionIndex > 0)
- {
- return false;
- }
-
- auto self = Toolkit::TextField::DownCast(Self());
- Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(startOffset, endOffset);
- return true;
+ return Toolkit::GetImpl(self).mAnchorActors;
}
-bool TextField::AccessibleImpl::CopyText(size_t startPosition, size_t endPosition)
+Toolkit::Text::ControllerPtr TextField::TextFieldAccessible::GetTextController() const
{
- if(endPosition <= startPosition)
- {
- return false;
- }
-
auto self = Toolkit::TextField::DownCast(Self());
- auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
- Dali::Toolkit::GetImpl(self).GetTextController()->CopyStringToClipboard(text.substr(startPosition, endPosition - startPosition));
- return true;
+ return Toolkit::GetImpl(self).GetTextController();
}
-bool TextField::AccessibleImpl::CutText(size_t startPosition, size_t endPosition)
+std::uint32_t TextField::TextFieldAccessible::GetSubstituteCharacter() const
{
- if(endPosition <= startPosition)
- {
- return false;
- }
-
- auto self = Toolkit::TextField::DownCast(Self());
- auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
- Dali::Toolkit::GetImpl(self).GetTextController()->CopyStringToClipboard(text.substr(startPosition, endPosition - startPosition));
-
- self.SetProperty(Toolkit::TextField::Property::TEXT, text.substr(0, startPosition) + text.substr(endPosition));
+ auto self = Toolkit::TextField::DownCast(Self());
+ auto hiddenInputSettings = self.GetProperty<Property::Map>(Toolkit::TextField::Property::HIDDEN_INPUT_SETTINGS);
+ auto substChar = hiddenInputSettings.Find(Toolkit::HiddenInput::Property::SUBSTITUTE_CHARACTER);
- return true;
-}
-
-bool TextField::AccessibleImpl::DeleteText(size_t startPosition, size_t endPosition)
-{
- if(endPosition <= startPosition)
+ if(substChar)
{
- return false;
+ return static_cast<std::uint32_t>(substChar->Get<int>());
}
- auto self = Toolkit::TextField::DownCast(Self());
- auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-
- self.SetProperty(Toolkit::TextField::Property::TEXT, text.substr(0, startPosition) + text.substr(endPosition));
-
- return true;
+ return TextControlAccessible::GetSubstituteCharacter();
}
-Dali::Accessibility::States TextField::AccessibleImpl::CalculateStates()
+bool TextField::TextFieldAccessible::IsHiddenInput() const
{
- using namespace Dali::Accessibility;
-
- auto states = DevelControl::AccessibleImpl::CalculateStates();
-
- states[State::EDITABLE] = true;
- states[State::FOCUSABLE] = true;
-
- Toolkit::Control focusControl = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl();
- if(mSelf == focusControl)
- {
- states[State::FOCUSED] = true;
- }
+ auto self = Toolkit::TextField::DownCast(Self());
+ auto hiddenInputSettings = self.GetProperty<Property::Map>(Toolkit::TextField::Property::HIDDEN_INPUT_SETTINGS);
+ auto mode = hiddenInputSettings.Find(Toolkit::HiddenInput::Property::MODE);
- return states;
+ return (mode && (mode->Get<int>() != Toolkit::HiddenInput::Mode::HIDE_NONE));
}
-bool TextField::AccessibleImpl::InsertText(size_t startPosition, std::string text)
+void TextField::TextFieldAccessible::RequestTextRelayout()
{
- auto self = Toolkit::TextField::DownCast(Self());
- auto insertedText = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
+ auto self = Toolkit::TextField::DownCast(Self());
+ auto& selfImpl = Toolkit::GetImpl(self);
- insertedText.insert(startPosition, text);
-
- self.SetProperty(Toolkit::TextField::Property::TEXT, std::move(insertedText));
-
- return true;
-}
-
-bool TextField::AccessibleImpl::SetTextContents(std::string newContents)
-{
- auto self = Toolkit::TextField::DownCast(Self());
- self.SetProperty(Toolkit::TextField::Property::TEXT, std::move(newContents));
- return true;
+ selfImpl.RequestTextRelayout();
}
} // namespace Internal