application.SendNotification();
application.Render();
- // Check that the focus is successfully to clear
- DALI_TEST_CHECK(manager.GetCurrentFocusActor() == Actor());
+ // Since no focus has been moved, the current focus actor is the same.
+ DALI_TEST_CHECK(manager.GetCurrentFocusActor() == first);
// Make the second actor focusableInTouchMode
second.SetProperty(DevelActor::Property::TOUCH_FOCUSABLE, true);
END_TEST;
}
+
+int UtcDaliKeyboardFocusManagerWithUserInteractionEnabled(void)
+{
+ ToolkitTestApplication application;
+
+ tet_infoline(" UtcDaliKeyboardFocusManagerWithUserInteractionEnabled");
+
+ KeyboardFocusManager manager = KeyboardFocusManager::Get();
+ DALI_TEST_CHECK(manager);
+
+ // Create the first actor and add it to the stage
+ Actor first = Actor::New();
+ first.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE, true);
+ application.GetScene().Add(first);
+
+ // Create the second actor and add it to the first actor.
+ Actor second = Actor::New();
+ second.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE, true);
+ first.Add(second);
+
+ // Check that no actor is being focused yet.
+ DALI_TEST_CHECK(manager.GetCurrentFocusActor() == Actor());
+
+ // Check that the focus is set on the first actor
+ DALI_TEST_CHECK(manager.SetCurrentFocusActor(first) == true);
+ DALI_TEST_CHECK(manager.GetCurrentFocusActor() == first);
+
+ // Set USER_INTERACTION_ENABLED false.
+ second.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, false);
+
+ // Check that it will fail to set focus on the second actor as it's not userInteractionEnabled
+ DALI_TEST_CHECK(manager.SetCurrentFocusActor(second) == false);
+ DALI_TEST_CHECK(manager.GetCurrentFocusActor() == first);
+
+ // Set KeyboardFocusableChildren true.
+ second.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, true);
+
+ // Check that the focus is set on the second actor
+ DALI_TEST_CHECK(manager.SetCurrentFocusActor(second) == true);
+ DALI_TEST_CHECK(manager.GetCurrentFocusActor() == second);
+
+ END_TEST;
+}
\ No newline at end of file
#include <dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h>
#include <dali-toolkit/devel-api/text/rendering-backend.h>
#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
+
+#include <dali/devel-api/actors/actor-devel.h>
#include <dali/devel-api/adaptor-framework/clipboard.h>
#include <dali/devel-api/adaptor-framework/key-devel.h>
#include <dali/devel-api/text-abstraction/font-client.h>
application.SendNotification();
application.Render();
+ textEditor.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, true);
+ DALI_TEST_EQUALS(textEditor.GetProperty(DevelActor::Property::USER_INTERACTION_ENABLED).Get<bool>(), true, TEST_LOCATION);
+
textEditor.SetKeyInputFocus();
textEditor.SetProperty(DevelTextEditor::Property::ENABLE_EDITING, false);
application.ProcessEvent(GenerateKey("D", "", "D", KEY_D_CODE, 0, 0, Integration::KeyEvent::DOWN, "D", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
DALI_TEST_EQUALS(textEditor.GetProperty(TextEditor::Property::TEXT).Get<std::string>(), "D", TEST_LOCATION);
DALI_TEST_EQUALS(textEditor.GetProperty(DevelTextEditor::Property::ENABLE_EDITING).Get<bool>(), true, TEST_LOCATION);
+ // Check the user interaction enabled and for coverage
+ DevelTextEditor::SelectWholeText(textEditor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ textEditor.SetKeyInputFocus();
+ textEditor.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, false);
+ application.ProcessEvent(GenerateKey("D", "", "D", KEY_D_CODE, 0, 0, Integration::KeyEvent::DOWN, "D", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(textEditor.GetProperty(TextEditor::Property::TEXT).Get<std::string>(), "D", TEST_LOCATION);
+ DALI_TEST_EQUALS(textEditor.GetProperty(DevelActor::Property::USER_INTERACTION_ENABLED).Get<bool>(), false, TEST_LOCATION);
+
END_TEST;
}
END_TEST;
}
+int UtcDaliToolkitTextEditorMarkupRelativeLineHeight(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliToolkitTextEditorMarkupRelativeLineHeight");
+
+ TextEditor editor = TextEditor::New();
+ editor.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f));
+ editor.SetProperty(TextEditor::Property::POINT_SIZE, 10);
+ editor.SetProperty(TextEditor::Property::TEXT, "line 1\nline 2\nline 3\nline 4\nline 5");
+ editor.SetProperty(DevelTextEditor::Property::RELATIVE_LINE_SIZE, 1.0f);
+ editor.SetProperty(DevelTextEditor::Property::ELLIPSIS, false);
+ editor.SetProperty(TextEditor::Property::ENABLE_MARKUP, true);
+
+ TextEditor editorSingleLineParagraph = TextEditor::New();
+ editorSingleLineParagraph.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f));
+ editorSingleLineParagraph.SetProperty(TextEditor::Property::POINT_SIZE, 10);
+ editorSingleLineParagraph.SetProperty(TextEditor::Property::TEXT, "<p>line 1</p><p rel-line-height=0.5>line 2</p>line 3<p rel-line-height=3>line 4</p>line 5");
+ editorSingleLineParagraph.SetProperty(DevelTextEditor::Property::RELATIVE_LINE_SIZE, 1.0f);
+ editorSingleLineParagraph.SetProperty(DevelTextEditor::Property::ELLIPSIS, false);
+ editorSingleLineParagraph.SetProperty(TextEditor::Property::ENABLE_MARKUP, true);
+
+ TextEditor editorMultiLineParagraph = TextEditor::New();
+ editorMultiLineParagraph.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f));
+ editorMultiLineParagraph.SetProperty(TextEditor::Property::POINT_SIZE, 10);
+ editorMultiLineParagraph.SetProperty(TextEditor::Property::TEXT, "<p>line 1</p><p rel-line-height=0.5>line\n2</p>line 3<p rel-line-height=3>line\n4</p>line 5");
+ editorMultiLineParagraph.SetProperty(DevelTextEditor::Property::RELATIVE_LINE_SIZE, 1.0f);
+ editorMultiLineParagraph.SetProperty(DevelTextEditor::Property::ELLIPSIS, false);
+ editorMultiLineParagraph.SetProperty(TextEditor::Property::ENABLE_MARKUP, true);
+
+ application.GetScene().Add(editor);
+ application.GetScene().Add(editorSingleLineParagraph);
+ application.GetScene().Add(editorMultiLineParagraph);
+ application.SendNotification();
+ application.Render();
+
+ Vector3 naturalSize = editor.GetNaturalSize();
+ Vector3 relativeSingleNaturalSize = editorSingleLineParagraph.GetNaturalSize();
+ Vector3 relativeMultiNaturalSize = editorMultiLineParagraph.GetNaturalSize();
+
+ float lineSize = naturalSize.y / 5.0f; //total size/number of lines
+
+ //no effect of relative line size for paragraph with single line
+ DALI_TEST_EQUALS(naturalSize.y, relativeSingleNaturalSize.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(lineSize*8.5f, relativeMultiNaturalSize.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+ END_TEST;
+}
+
int UtcDaliToolkitTextEditorRelativeLineHeight(void)
{
ToolkitTestApplication application;
END_TEST;
}
+int UtcDaliTextEditorLineSpacingKeyArrowDown(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("UtcDaliTextEditorLineSpacingKeyArrowDown");
+
+ TextEditor editor = TextEditor::New();
+ DALI_TEST_CHECK(editor);
+
+ application.GetScene().Add(editor);
+
+ std::string cutText = "";
+ std::string copiedText = "";
+
+ editor.SetProperty(TextEditor::Property::TEXT, "l1\nl2\nl3\n4");
+ editor.SetProperty(TextEditor::Property::POINT_SIZE, 10.f);
+ editor.SetProperty(Actor::Property::SIZE, Vector2(300.f, 200.f));
+ editor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+ editor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ editor.SetProperty(TextEditor::Property::ENABLE_MARKUP, true);
+ editor.SetProperty(TextEditor::Property::LINE_SPACING, -15);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Tap on the text editor
+ TestGenerateTap(application, 1.0f, 1.0f);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Move to second line of the text.
+ application.ProcessEvent(GenerateKey("", "", "", DALI_KEY_CURSOR_DOWN, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(editor.GetProperty(DevelTextEditor::Property::PRIMARY_CURSOR_POSITION).Get<int>(), 3, TEST_LOCATION);
+
+ END_TEST;
+}
+
int UtcDaliTextEditorNegativeLineSpacingWithEllipsis(void)
{
ToolkitTestApplication application;
#include <dali/integration-api/events/key-event-integ.h>
#include <dali/integration-api/events/touch-event-integ.h>
#include <dali/public-api/rendering/renderer.h>
+#include <dali/devel-api/actors/actor-devel.h>
#include <dali-toolkit-test-suite-utils.h>
#include <dali-toolkit/dali-toolkit.h>
application.SendNotification();
application.Render();
+ textField.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, true);
+ DALI_TEST_EQUALS(textField.GetProperty(DevelActor::Property::USER_INTERACTION_ENABLED).Get<bool>(), true, TEST_LOCATION);
+
textField.SetKeyInputFocus();
textField.SetProperty(DevelTextField::Property::ENABLE_EDITING, false);
application.ProcessEvent(GenerateKey("D", "", "D", KEY_D_CODE, 0, 0, Integration::KeyEvent::DOWN, "D", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
DALI_TEST_EQUALS(textField.GetProperty(TextField::Property::TEXT).Get<std::string>(), "D", TEST_LOCATION);
DALI_TEST_EQUALS(textField.GetProperty(DevelTextField::Property::ENABLE_EDITING).Get<bool>(), true, TEST_LOCATION);
+ // Check the user interaction enabled and for coverage
+ DevelTextField::SelectWholeText(textField);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ textField.SetKeyInputFocus();
+ textField.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, false);
+ application.ProcessEvent(GenerateKey("D", "", "D", KEY_D_CODE, 0, 0, Integration::KeyEvent::DOWN, "D", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(textField.GetProperty(TextField::Property::TEXT).Get<std::string>(), "D", TEST_LOCATION);
+ DALI_TEST_EQUALS(textField.GetProperty(DevelActor::Property::USER_INTERACTION_ENABLED).Get<bool>(), false, TEST_LOCATION);
+
END_TEST;
}
END_TEST;
}
+int UtcDaliToolkitTextLabelMarkupRelativeLineHeight(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliToolkitTextLabelMarkupRelativeLineHeight");
+
+ TextLabel label = TextLabel::New();
+ label.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f));
+ label.SetProperty(TextLabel::Property::POINT_SIZE, 10);
+ label.SetProperty(TextLabel::Property::MULTI_LINE, true);
+ label.SetProperty(TextLabel::Property::TEXT, "line 1\nline 2\nline 3\nline 4\nline 5");
+ label.SetProperty(DevelTextLabel::Property::RELATIVE_LINE_SIZE, 1.0f);
+ label.SetProperty(TextLabel::Property::ELLIPSIS, false);
+ label.SetProperty(TextLabel::Property::ENABLE_MARKUP, true);
+
+ TextLabel labelSingleLineParagraph = TextLabel::New();
+ labelSingleLineParagraph.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f));
+ labelSingleLineParagraph.SetProperty(TextLabel::Property::POINT_SIZE, 10);
+ labelSingleLineParagraph.SetProperty(TextLabel::Property::MULTI_LINE, true);
+ labelSingleLineParagraph.SetProperty(TextLabel::Property::TEXT, "<p>line 1</p><p rel-line-height=0.5>line 2</p>line 3<p rel-line-height=3>line 4</p>line 5");
+ labelSingleLineParagraph.SetProperty(DevelTextLabel::Property::RELATIVE_LINE_SIZE, 1.0f);
+ labelSingleLineParagraph.SetProperty(TextLabel::Property::ELLIPSIS, false);
+ labelSingleLineParagraph.SetProperty(TextLabel::Property::ENABLE_MARKUP, true);
+
+ TextLabel labelMultiLineParagraph = TextLabel::New();
+ labelMultiLineParagraph.SetProperty(Actor::Property::SIZE, Vector2(200.0f, 300.f));
+ labelMultiLineParagraph.SetProperty(TextLabel::Property::POINT_SIZE, 10);
+ labelMultiLineParagraph.SetProperty(TextLabel::Property::MULTI_LINE, true);
+ labelMultiLineParagraph.SetProperty(TextLabel::Property::TEXT, "<p>line 1</p><p rel-line-height=0.5>line\n2</p>line 3<p rel-line-height=3>line\n4</p>line 5");
+ labelMultiLineParagraph.SetProperty(DevelTextLabel::Property::RELATIVE_LINE_SIZE, 1.0f);
+ labelMultiLineParagraph.SetProperty(TextLabel::Property::ELLIPSIS, false);
+ labelMultiLineParagraph.SetProperty(TextLabel::Property::ENABLE_MARKUP, true);
+
+ application.GetScene().Add(label);
+ application.GetScene().Add(labelSingleLineParagraph);
+ application.GetScene().Add(labelMultiLineParagraph);
+ application.SendNotification();
+ application.Render();
+
+ Vector3 naturalSize = label.GetNaturalSize();
+ Vector3 relativeSingleNaturalSize = labelSingleLineParagraph.GetNaturalSize();
+ Vector3 relativeMultiNaturalSize = labelMultiLineParagraph.GetNaturalSize();
+
+ float lineSize = naturalSize.y / 5.0f; //total size/number of lines
+
+ //no effect of relative line size for paragraph with single line
+ DALI_TEST_EQUALS(naturalSize.y, relativeSingleNaturalSize.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(lineSize*8.5f, relativeMultiNaturalSize.y, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+
+ END_TEST;
+}
+
int UtcDaliToolkitTextLabelRelativeLineHeight(void)
{
ToolkitTestApplication application;
bool IsFocusable(Actor& actor)\r
{\r
return (actor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) &&\r
+ actor.GetProperty<bool>(DevelActor::Property::USER_INTERACTION_ENABLED) &&\r
actor.GetProperty<bool>(Actor::Property::VISIBLE) &&\r
actor.GetProperty<Vector4>(Actor::Property::WORLD_COLOR).a > FULLY_TRANSPARENT);\r
}\r
#include <dali-toolkit/internal/controls/control/control-data-impl.h>
#include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
#include <dali-toolkit/internal/controls/text-controls/text-editor-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>
}
}
+void TextEditor::OnPropertySet(Property::Index index, const Property::Value& propertyValue)
+{
+ DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor::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 TextEditor::OnRelayout(const Vector2& size, RelayoutContainer& container)
{
DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor OnRelayout\n");
notifier.ContentSelectedSignal().Connect(this, &TextEditor::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();
}
// 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 OnSceneConnection(int depth) override;
/**
+ * @copydoc Control::OnPropertySet()
+ */
+ void OnPropertySet(Property::Index index, const Property::Value& propertyValue) override;
+
+ /**
* @copydoc Dali::CustomActorImpl::OnKeyEvent(const KeyEvent&)
*/
bool OnKeyEvent(const KeyEvent& event) override;
#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>
}
}
+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");
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();
}
// 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 OnSceneConnection(int depth) override;
/**
+ * @copydoc Control::OnPropertySet()
+ */
+ void OnPropertySet(Property::Index index, const Property::Value& propertyValue) override;
+
+ /**
* @copydoc Dali::CustomActorImpl::OnKeyEvent(const KeyEvent&)
*/
bool OnKeyEvent(const KeyEvent& event) override;
}
}
- if(actor && actor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) && actor.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
+ if(actor && actor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) && actor.GetProperty<bool>(DevelActor::Property::USER_INTERACTION_ENABLED) && actor.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
{
Integration::SceneHolder currentWindow = Integration::SceneHolder::Get(actor);
}
// Check whether the actor is in the stage and is keyboard focusable.
- if(actor && actor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) && actor.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
+ if(actor && actor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) && actor.GetProperty<bool>(DevelActor::Property::USER_INTERACTION_ENABLED) && actor.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
{
if((mIsFocusIndicatorShown == SHOW) && (mEnableFocusIndicator == ENABLE))
{
}
}
- if(nextFocusableActor && nextFocusableActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE))
+ if(nextFocusableActor && nextFocusableActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) && nextFocusableActor.GetProperty<bool>(DevelActor::Property::USER_INTERACTION_ENABLED))
{
// Whether the next focusable actor is a layout control
if(IsLayoutControl(nextFocusableActor))
Actor nextFocusableActor = GetImplementation(control).GetNextKeyboardFocusableActor(actor, direction, mFocusGroupLoopEnabled);
if(nextFocusableActor)
{
- if(!nextFocusableActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE))
+ if(!(nextFocusableActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) || nextFocusableActor.GetProperty<bool>(DevelActor::Property::USER_INTERACTION_ENABLED)))
{
// If the actor is not focusable, ask the same layout control for the next actor to focus
return DoMoveFocusWithinLayoutControl(control, nextFocusableActor, direction);
mIsWaitingKeyboardFocusChangeCommit = false;
}
- if(committedFocusActor && committedFocusActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE))
+ if(committedFocusActor && committedFocusActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) && committedFocusActor.GetProperty<bool>(DevelActor::Property::USER_INTERACTION_ENABLED))
{
// Whether the commited focusable actor is a layout control
if(IsLayoutControl(committedFocusActor))
void KeyboardFocusManager::ClearFocus()
{
+ ClearFocusIndicator();
Actor actor = GetCurrentFocusActor();
if(actor)
{
- if(mFocusIndicatorActor)
- {
- actor.Remove(mFocusIndicatorActor);
- }
-
// Send notification for the change of focus actor
if(!mFocusChangedSignal.Empty())
{
currentlyFocusedControl.ClearKeyInputFocus();
}
}
-
mCurrentFocusActor.Reset();
+}
+
+void KeyboardFocusManager::ClearFocusIndicator()
+{
+ Actor actor = GetCurrentFocusActor();
+ if(actor)
+ {
+ if(mFocusIndicatorActor)
+ {
+ actor.Remove(mFocusIndicatorActor);
+ }
+ }
mIsFocusIndicatorShown = (mAlwaysShowIndicator == ALWAYS_SHOW) ? SHOW : HIDE;
}
// We only do this on a Down event, otherwise the clear action may override a manually focused actor.
if(((touch.GetPointCount() < 1) || (touch.GetState(0) == PointState::DOWN)))
{
- // If mClearFocusOnTouch is false, do not clear the focus even if user touch the screen.
- if(mClearFocusOnTouch)
+ // If you touch the currently focused actor again, you don't need to do SetCurrentFocusActor again.
+ Actor hitActor = touch.GetHitActor(0);
+ if(hitActor && hitActor == GetCurrentFocusActor())
{
- ClearFocus();
+ return;
}
-
// If KEYBOARD_FOCUSABLE and TOUCH_FOCUSABLE is true, set focus actor
- Actor hitActor = touch.GetHitActor(0);
if(hitActor && hitActor.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE) && hitActor.GetProperty<bool>(DevelActor::Property::TOUCH_FOCUSABLE))
{
+ // If mClearFocusOnTouch is false, do not clear the focus
+ if(mClearFocusOnTouch)
+ {
+ ClearFocus();
+ }
SetCurrentFocusActor(hitActor);
}
+ else
+ {
+ // If mClearFocusOnTouch is false, do not clear the focus indicator even if user touch the screen.
+ if(mClearFocusOnTouch)
+ {
+ ClearFocusIndicator();
+ }
+ }
}
}
*/
bool EmitCustomWheelSignals(Actor actor, const WheelEvent& event);
+ /**
+ * Clear the focus indicator actor.
+ */
+ void ClearFocusIndicator();
+
private:
// Undefined
KeyboardFocusManager(const KeyboardFocusManager&);
BoundedParagraphRun()
: characterRun{},
horizontalAlignment(Text::HorizontalAlignment::BEGIN),
- horizontalAlignmentDefined{false}
+ relativeLineSize(1),
+ horizontalAlignmentDefined{false},
+ relativeLineSizeDefined(false)
{
}
CharacterRun characterRun; ///< The initial character index within the whole text and the number of characters of the run.
Text::HorizontalAlignment::Type horizontalAlignment; ///< The paragraph horizontal alignment. Values "BEGIN" "CENTER" "END".
+ float relativeLineSize; ///< The relative line height to be used for this paragaraph.
bool horizontalAlignmentDefined : 1; ///< Whether the horizontal alignment is defined.
+ bool relativeLineSizeDefined : 1; ///< Whether the relative line height is defined for this paragraph.
};
} // namespace Text
void Decorator::SetEditable(bool editable)
{
mImpl->mHidePrimaryCursorAndGrabHandle = !editable;
+ // If editable is false, all decorators should be disabled.
+ if(!editable)
+ {
+ if(IsHighlightActive())
+ {
+ SetHighlightActive(false);
+ }
+ if(IsHandleActive(LEFT_SELECTION_HANDLE))
+ {
+ SetHandleActive(LEFT_SELECTION_HANDLE, false);
+ }
+ if(IsHandleActive(RIGHT_SELECTION_HANDLE))
+ {
+ SetHandleActive(RIGHT_SELECTION_HANDLE, false);
+ }
+ if(IsPopupActive())
+ {
+ SetPopupActive(false);
+ }
+ }
+
mImpl->Relayout(mImpl->mControlSize);
}
/** Handles **/
glyphIndexInSecondHalfLine{0u},
characterIndexInSecondHalfLine{0u},
numberOfGlyphsInSecondHalfLine{0u},
- numberOfCharactersInSecondHalfLine{0u}
+ numberOfCharactersInSecondHalfLine{0u},
+ relativeLineSize{1.0f}
{
}
characterIndexInSecondHalfLine = 0u;
numberOfGlyphsInSecondHalfLine = 0u;
numberOfCharactersInSecondHalfLine = 0u;
+ relativeLineSize = 1.0f;
}
GlyphIndex glyphIndex; ///< Index of the first glyph to be laid-out.
CharacterIndex characterIndexInSecondHalfLine; ///< Index of the first character to be laid-out for the second half of line.
Length numberOfGlyphsInSecondHalfLine; ///< The number of glyph which fit in one line for the second half of line.
Length numberOfCharactersInSecondHalfLine; ///< The number of characters which fit in one line for the second half of line.
+
+ float relativeLineSize; ///< The relative line size to be applied for this line.
};
struct LayoutBidiParameters
* @brief get the line spacing.
*
* @param[in] textSize The text size.
+ * @param[in] relativeLineSize The relative line size to be applied.
* @return the line spacing value.
*/
- float GetLineSpacing(float textSize)
+ float GetLineSpacing(float textSize, float relativeLineSize)
{
float lineSpacing;
float relTextSize;
lineSpacing += mDefaultLineSpacing;
//subtract line spcaing if relativeLineSize < 1 & larger than min height
- relTextSize = textSize * mRelativeLineSize;
+ relTextSize = textSize * relativeLineSize;
if(relTextSize > mDefaultLineSize)
{
- if(mRelativeLineSize < 1)
+ if(relativeLineSize < 1)
{
//subtract the difference (always will be positive)
lineSpacing -= (textSize - relTextSize);
// Sets the minimum descender.
lineLayout.descender = std::min(lineLayout.descender, fontMetrics.descender);
- lineLayout.lineSpacing = GetLineSpacing(lineLayout.ascender + -lineLayout.descender);
+ lineLayout.lineSpacing = GetLineSpacing(lineLayout.ascender + -lineLayout.descender, lineLayout.relativeLineSize);
}
/**
// It needs to add as well space for the cursor if the text is in edit mode and extra space in case the text is outlined.
tmpLineLayout.penX = -glyphMetrics.xBearing + mCursorWidth + outlineWidth;
+ tmpLineLayout.relativeLineSize = lineLayout.relativeLineSize;
+
// Calculate the line height if there is no characters.
FontId lastFontId = glyphMetrics.fontId;
UpdateLineHeight(glyphMetrics, tmpLineLayout);
LineRun* lineRun = nullptr;
LineLayout ellipsisLayout;
+
+ ellipsisLayout.relativeLineSize = layout.relativeLineSize;
+
if(0u != numberOfLines)
{
// Get the last line and layout it again with the 'completelyFill' flag to true.
lineRun.direction = layout.direction;
lineRun.ellipsis = false;
- lineRun.lineSpacing = GetLineSpacing(lineRun.ascender + -lineRun.descender);
+ lineRun.lineSpacing = GetLineSpacing(lineRun.ascender + -lineRun.descender, layout.relativeLineSize);
// Update the actual size.
if(lineRun.width > layoutSize.width)
lineRun.direction = LTR;
lineRun.ellipsis = false;
- lineRun.lineSpacing = GetLineSpacing(lineRun.ascender + -lineRun.descender);
+ BoundedParagraphRun currentParagraphRun;
+ LineLayout tempLineLayout;
+ (GetBoundedParagraph(layoutParameters.textModel->GetBoundedParagraphRuns(), characterIndex, currentParagraphRun) ? SetRelativeLineSize(¤tParagraphRun, tempLineLayout) : SetRelativeLineSize(nullptr, tempLineLayout));
+
+ lineRun.lineSpacing = GetLineSpacing(lineRun.ascender + -lineRun.descender, tempLineLayout.relativeLineSize);
layoutSize.height += GetLineHeight(lineRun, true);
}
}
}
+ /**
+ * @brief Sets the relative line size for the LineLayout
+ *
+ * @param[in] currentParagraphRun Contains the bounded paragraph for this line layout.
+ * @param[in,out] lineLayout The line layout to be updated.
+ */
+ void SetRelativeLineSize(BoundedParagraphRun* currentParagraphRun, LineLayout& lineLayout)
+ {
+ lineLayout.relativeLineSize = mRelativeLineSize;
+
+ if(currentParagraphRun != nullptr && currentParagraphRun->relativeLineSizeDefined)
+ {
+ lineLayout.relativeLineSize = currentParagraphRun->relativeLineSize;
+ }
+ }
+
+ /**
+ * @brief Get the bounded paragraph for the characterIndex if exists.
+ *
+ * @param[in] boundedParagraphRuns The bounded paragraph list to search in.
+ * @param[in] characterIndex The character index to get bounded paragraph for.
+ * @param[out] currentParagraphRun Contains the bounded paragraph if found for the characterIndex.
+ *
+ * @return returns true if a bounded paragraph was found.
+ */
+ bool GetBoundedParagraph(const Vector<BoundedParagraphRun> boundedParagraphRuns, CharacterIndex characterIndex, BoundedParagraphRun& currentParagraphRun)
+ {
+ for(Vector<BoundedParagraphRun>::Iterator it = boundedParagraphRuns.Begin(),
+ endIt = boundedParagraphRuns.End();
+ it != endIt;
+ ++it)
+ {
+ BoundedParagraphRun& tempParagraphRun = *it;
+
+ if(characterIndex >= tempParagraphRun.characterRun.characterIndex &&
+ characterIndex < (tempParagraphRun.characterRun.characterIndex + tempParagraphRun.characterRun.numberOfCharacters))
+ {
+ currentParagraphRun = tempParagraphRun;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
bool LayoutText(Parameters& layoutParameters,
Size& layoutSize,
bool elideTextEnabled,
layoutParameters.textModel->mVisualModel->SetFirstMiddleIndexOfElidedGlyphs(0u);
layoutParameters.textModel->mVisualModel->SetSecondMiddleIndexOfElidedGlyphs(0u);
- Vector<LineRun>& lines = layoutParameters.textModel->mVisualModel->mLines;
+ Vector<LineRun>& lines = layoutParameters.textModel->mVisualModel->mLines;
+ const Vector<BoundedParagraphRun>& boundedParagraphRuns = layoutParameters.textModel->GetBoundedParagraphRuns();
if(0u == layoutParameters.numberOfGlyphs)
{
// Retrieve BiDi info.
const bool hasBidiParagraphs = !layoutParameters.textModel->mLogicalModel->mBidirectionalParagraphInfo.Empty();
- const CharacterIndex* const glyphsToCharactersBuffer = hasBidiParagraphs ? layoutParameters.textModel->mVisualModel->mGlyphsToCharacters.Begin() : nullptr;
+ const CharacterIndex* const glyphsToCharactersBuffer = layoutParameters.textModel->mVisualModel->mGlyphsToCharacters.Begin();
const Vector<BidirectionalParagraphInfoRun>& bidirectionalParagraphsInfo = layoutParameters.textModel->mLogicalModel->mBidirectionalParagraphInfo;
const Vector<BidirectionalLineInfoRun>& bidirectionalLinesInfo = layoutParameters.textModel->mLogicalModel->mBidirectionalLineInfo;
LineLayout layout;
layout.direction = layoutBidiParameters.paragraphDirection;
layout.glyphIndex = index;
+
+ BoundedParagraphRun currentParagraphRun;
+ (GetBoundedParagraph(boundedParagraphRuns, *(glyphsToCharactersBuffer + index), currentParagraphRun) ? SetRelativeLineSize(¤tParagraphRun, layout) : SetRelativeLineSize(nullptr, layout));
+
GetLineLayoutForBox(layoutParameters,
layoutBidiParameters,
layout,
DALI_LOG_INFO(gLogFilter, Debug::Verbose, " number of characters %d\n", layout.numberOfCharacters);
DALI_LOG_INFO(gLogFilter, Debug::Verbose, " length %f\n", layout.length);
+ CharacterIndex lastCharacterInParagraph = currentParagraphRun.characterRun.characterIndex + currentParagraphRun.characterRun.numberOfCharacters - 1;
+
+ //check if this is the last line in paragraph, if false we should use the default relative line size (the one set using the property)
+ if(lastCharacterInParagraph >= layout.characterIndex && lastCharacterInParagraph < layout.characterIndex+layout.numberOfCharacters)
+ {
+ layout.relativeLineSize = mRelativeLineSize;
+ }
+
if(0u == layout.numberOfGlyphs + layout.numberOfGlyphsInSecondHalfLine)
{
// The width is too small and no characters are laid-out.
}
// Updates the vertical pen's position.
- penY += -layout.descender + layout.lineSpacing + GetLineSpacing(layout.ascender + -layout.descender);
+ penY += -layout.descender + layout.lineSpacing + GetLineSpacing(layout.ascender + -layout.descender, layout.relativeLineSize);
// Increase the glyph index.
index = nextIndex;
namespace
{
const std::string XHTML_ALIGN_ATTRIBUTE("align");
-}
+const std::string XHTML_RELATIVE_LINE_HEIGHT_ATTRIBUTE("rel-line-height");
+} // namespace
void ProcessHorizontalAlignment(const Attribute& attribute, BoundedParagraphRun& boundedParagraphRun)
{
boundedParagraphRun.horizontalAlignment);
}
+void ProcessRelativeLineHeight(const Attribute& attribute, BoundedParagraphRun& boundedParagraphRun)
+{
+ boundedParagraphRun.relativeLineSize = StringToFloat(attribute.valueBuffer);
+ boundedParagraphRun.relativeLineSizeDefined = true;
+}
+
void ProcessAttributesOfParagraphTag(const Tag& tag, BoundedParagraphRun& boundedParagraphRun)
{
// By default the align attribute is not defined until it's parsed.
{
ProcessHorizontalAlignment(attribute, boundedParagraphRun);
}
+ else if(TokenComparison(XHTML_RELATIVE_LINE_HEIGHT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+ {
+ ProcessRelativeLineHeight(attribute, boundedParagraphRun);
+ }
}
}
-
} // namespace Text
} // namespace Toolkit
*/
void ProcessAttributesOfParagraphTag(const Tag& tag, BoundedParagraphRun& boundedParagraphRun);
+/**
+ * @brief Retrieves the relative line height value from the paragraph tag and sets it to the bounded paragraph run.
+ *
+ * @param[in] attribute the relative line height attribute.
+ * @param[in,out] boundedParagraphRun The bounded paragraph run.
+ */
+void ProcessRelativeLineHeight(const Attribute& attribute, BoundedParagraphRun& boundedParagraphRun);
+
} // namespace Text
} // namespace Toolkit
// Increases the vertical offset with the line's ascender.
glyphData.verticalOffset += static_cast<int>(line.ascender);
- // Include line spacing after first line
- if(lineIndex > 0u)
- {
- glyphData.verticalOffset += static_cast<int>(line.lineSpacing);
- }
-
// Retrieves the glyph's outline width
float outlineWidth = static_cast<float>(mModel->GetOutlineWidth());
DrawStrikethrough(bufferWidth, bufferHeight, glyphData, baseline, strikethroughStartingYPosition, maxStrikethroughHeight, lineExtentLeft, lineExtentRight, modelStrikethroughProperties, currentStrikethroughProperties, line);
}
- // Increases the vertical offset with the line's descender.
- glyphData.verticalOffset += static_cast<int>(-line.descender);
+ // Increases the vertical offset with the line's descender & line spacing.
+ glyphData.verticalOffset += static_cast<int>(-line.descender+line.lineSpacing);
}
return glyphData.bitmapBuffer;
bool textChanged = false;
bool relayoutNeeded = false;
+ bool isEditable = controller.IsEditable() && controller.IsUserInteractionEnabled();
if((NULL != controller.mImpl->mEventData) &&
(keyEvent.GetState() == KeyEvent::DOWN))
(Dali::DALI_KEY_CURSOR_DOWN == keyCode))
{
// If don't have any text, do nothing.
- if(!controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters)
+ if(!controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters || !isEditable)
{
return false;
}
// Do nothing
return false;
}
- else if(keyEvent.IsCtrlModifier() && !keyEvent.IsShiftModifier())
+ else if(keyEvent.IsCtrlModifier() && !keyEvent.IsShiftModifier() && isEditable)
{
bool consumed = false;
if(keyName == KEY_C_NAME || keyName == KEY_INSERT_NAME || logicalKey == KEY_C_NAME || logicalKey == KEY_INSERT_NAME)
else
{
DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::KeyEvent %p keyString %s\n", &controller, keyString.c_str());
- if(!controller.IsEditable()) return false;
+ if(!isEditable) return false;
std::string refinedKey = keyString;
if(controller.mImpl->mInputFilter != NULL && !refinedKey.empty())
impl.GetCursorPosition(primaryCursorPosition, cursorInfo);
// Get the line below.
- const LineRun& line = *(visualModel->mLines.Begin() + lineIndex + 1u);
+ const LineRun& nextline = *(visualModel->mLines.Begin() + lineIndex + 1u);
+ const LineRun& currline = *(visualModel->mLines.Begin() + lineIndex);
// Get last line index
const LineIndex lastLineIndex = (visualModel->mLines.Size() > 0 ? visualModel->mLines.Size() - 1u : 0);
const bool isLastLine = (lineIndex + 1u == lastLineIndex);
// Get the next hit 'y' point.
- const float hitPointY = cursorInfo.lineOffset + cursorInfo.lineHeight + 0.5f * GetLineHeight(line, isLastLine);
+ const float hitPointY = cursorInfo.lineOffset + GetLineHeight(currline, false) + 0.5f * GetLineHeight(nextline, isLastLine);
// Use the cursor hook position 'x' and the next hit 'y' position to calculate the new cursor index.
bool matchedCharacter = false;
if(mEventData->mDecorator)
{
- mEventData->mDecorator->SetEditable(editable);
+ bool decoratorEditable = editable && mIsUserInteractionEnabled;
+ mEventData->mDecorator->SetEditable(decoratorEditable);
}
}
}
}
}
+void Controller::Impl::SetUserInteractionEnabled(bool enabled)
+{
+ mIsUserInteractionEnabled = enabled;
+
+ if(mEventData && mEventData->mDecorator)
+ {
+ bool editable = mEventData->mEditingEnabled && enabled;
+ mEventData->mDecorator->SetEditable(editable);
+ }
+}
+
void Controller::Impl::ClearFontData()
{
if(mFontDefaults)
const float DEFAULT_TEXTFIT_MAX = 100.f;
const float DEFAULT_TEXTFIT_STEP = 1.f;
const float DEFAULT_FONT_SIZE_SCALE = 1.f;
+const float DEFAULT_DISABLED_COLOR_OPACITY = 0.3f;
//Forward declarations
struct CursorInfo;
mTextFitMaxSize(DEFAULT_TEXTFIT_MAX),
mTextFitStepSize(DEFAULT_TEXTFIT_STEP),
mFontSizeScale(DEFAULT_FONT_SIZE_SCALE),
+ mDisabledColorOpacity(DEFAULT_DISABLED_COLOR_OPACITY),
mFontSizeScaleEnabled(true),
mTextFitEnabled(false),
mTextFitChanged(false),
- mIsLayoutDirectionChanged(false)
+ mIsLayoutDirectionChanged(false),
+ mIsUserInteractionEnabled(true)
{
mModel = Model::New();
void SetDefaultColor(const Vector4& color);
/**
+ * @copydoc Controller::SetUserInteractionEnabled()
+ */
+ void SetUserInteractionEnabled(bool enabled);
+
+ /**
* @brief Helper to clear font-specific data (only).
*/
void ClearFontData();
float mTextFitMaxSize; ///< Maximum Font Size for text fit. Default 100
float mTextFitStepSize; ///< Step Size for font intervalse. Default 1
float mFontSizeScale; ///< Scale value for Font Size. Default 1.0
+ float mDisabledColorOpacity; ///< Color opacity when disabled.
bool mFontSizeScaleEnabled : 1; ///< Whether the font size scale is enabled.
bool mTextFitEnabled : 1; ///< Whether the text's fit is enabled.
bool mTextFitChanged : 1; ///< Whether the text fit property has changed.
bool mIsLayoutDirectionChanged : 1; ///< Whether the layout has changed.
+ bool mIsUserInteractionEnabled : 1; ///< Whether the user interaction is enabled.
private:
friend ControllerImplEventHandler;
return mImpl->mTextColor;
}
+void Controller::SetDisabledColorOpacity(float opacity)
+{
+ mImpl->mDisabledColorOpacity = opacity;
+}
+
+float Controller::GetDisabledColorOpacity() const
+{
+ return mImpl->mDisabledColorOpacity;
+}
+
+void Controller::SetUserInteractionEnabled(bool enabled)
+{
+ mImpl->SetUserInteractionEnabled(enabled);
+}
+
+bool Controller::IsUserInteractionEnabled() const
+{
+ return mImpl->mIsUserInteractionEnabled;
+}
+
void Controller::SetPlaceholderTextColor(const Vector4& textColor)
{
PlaceholderHandler::SetPlaceholderTextColor(*this, textColor);
bool IsTextFitChanged() const;
/**
+ * @brief Sets disabled color opacity.
+ *
+ * @param[in] opacity The color opacity value in disabled state.
+ */
+ void SetDisabledColorOpacity(float opacity);
+
+ /**
+ * @brief Retrieves the disabled color opacity.
+ *
+ * @return The disabled color opacity value for disabled state.
+ */
+ float GetDisabledColorOpacity() const;
+
+ /**
* @brief Enable or disable the placeholder text elide.
* @param enabled Whether to enable the placeholder text elide.
*/
const Vector4& GetDefaultColor() const;
/**
+ * @brief Sets the user interaction enabled.
+ *
+ * @param enabled whether to enable the user interaction.
+ */
+ void SetUserInteractionEnabled(bool enabled);
+
+ /**
+ * @brief Whether the user interaction is enabled.
+ *
+ * @return true if the user interaction is enabled, false otherwise.
+ */
+ bool IsUserInteractionEnabled() const;
+
+ /**
* @brief Set the text color
*
* @param textColor The text color