#include <dali/integration-api/debug.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(EventData::INTERRUPTED != controller.mImpl->mEventData->mState)
{
+ // Init selection position
+ if(controller.mImpl->mEventData->mState == EventData::SELECTING)
+ {
+ uint32_t oldStart, oldEnd;
+ oldStart = controller.mImpl->mEventData->mLeftSelectionPosition;
+ oldEnd = controller.mImpl->mEventData->mRightSelectionPosition;
+
+ controller.mImpl->mEventData->mLeftSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
+ controller.mImpl->mEventData->mRightSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
+
+ if(controller.mImpl->mSelectableControlInterface != nullptr)
+ {
+ controller.mImpl->mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, controller.mImpl->mEventData->mPrimaryCursorPosition, controller.mImpl->mEventData->mPrimaryCursorPosition);
+ }
+ }
+
controller.mImpl->ChangeState(EventData::INACTIVE);
if(!controller.mImpl->IsShowingRealText())
{
// Revert to regular placeholder-text when not editing
- controller.ShowPlaceholderText();
+ PlaceholderHandler::ShowPlaceholderText(*controller.mImpl);
}
}
}
// Release the active highlight.
if(controller.mImpl->mEventData->mState == EventData::SELECTING)
{
+ uint32_t oldStart, oldEnd;
+ oldStart = controller.mImpl->mEventData->mLeftSelectionPosition;
+ oldEnd = controller.mImpl->mEventData->mRightSelectionPosition;
+
controller.mImpl->ChangeState(EventData::EDITING);
// Update selection position.
controller.mImpl->mEventData->mLeftSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
controller.mImpl->mEventData->mRightSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
controller.mImpl->mEventData->mUpdateCursorPosition = true;
+
+ if(controller.mImpl->mSelectableControlInterface != nullptr)
+ {
+ controller.mImpl->mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, controller.mImpl->mEventData->mLeftSelectionPosition, controller.mImpl->mEventData->mRightSelectionPosition);
+ }
+
controller.mImpl->RequestRelayout();
}
return false;
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;
DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::KeyEvent %p keyString %s\n", &controller, keyString.c_str());
if(!controller.IsEditable()) return false;
- if(!keyString.empty())
+ std::string refinedKey = keyString;
+ if(controller.mImpl->mInputFilter != NULL && !refinedKey.empty())
+ {
+ bool accepted = false;
+ bool rejected = false;
+ accepted = controller.mImpl->mInputFilter->Contains(Toolkit::InputFilter::Property::ACCEPTED, keyString);
+ rejected = controller.mImpl->mInputFilter->Contains(Toolkit::InputFilter::Property::REJECTED, keyString);
+
+ if(!accepted)
+ {
+ // The filtered key is set to empty.
+ refinedKey = "";
+ // Signal emits when the character to be inserted is filtered by the accepted filter.
+ controller.mImpl->mEditableControlInterface->InputFiltered(Toolkit::InputFilter::Property::ACCEPTED);
+ }
+ if(rejected)
+ {
+ // The filtered key is set to empty.
+ refinedKey = "";
+ // Signal emits when the character to be inserted is filtered by the rejected filter.
+ controller.mImpl->mEditableControlInterface->InputFiltered(Toolkit::InputFilter::Property::REJECTED);
+ }
+ }
+
+ if(!refinedKey.empty())
{
// InputMethodContext is no longer handling key-events
controller.mImpl->ClearPreEditFlag();
- controller.InsertText(keyString, COMMIT);
+ TextUpdater::InsertText(controller, refinedKey, COMMIT);
textChanged = true;
(NULL != controller.mImpl->mEditableControlInterface))
{
// Do this last since it provides callbacks into application code
- controller.mImpl->mEditableControlInterface->TextChanged();
+ controller.mImpl->mEditableControlInterface->TextChanged(false);
}
return true;
}
+void Controller::EventHandler::AnchorEvent(Controller& controller, float x, float y)
+{
+ if(!controller.mImpl->mMarkupProcessorEnabled ||
+ !controller.mImpl->mModel->mLogicalModel->mAnchors.Count() ||
+ !controller.mImpl->IsShowingRealText())
+ {
+ return;
+ }
+
+ CharacterIndex cursorPosition = 0u;
+
+ // Convert from control's coords to text's coords.
+ const float xPosition = x - controller.mImpl->mModel->mScrollPosition.x;
+ const float yPosition = y - controller.mImpl->mModel->mScrollPosition.y;
+
+ // Whether to touch point hits on a glyph.
+ bool matchedCharacter = false;
+ cursorPosition = Text::GetClosestCursorIndex(controller.mImpl->mModel->mVisualModel,
+ controller.mImpl->mModel->mLogicalModel,
+ controller.mImpl->mMetrics,
+ xPosition,
+ yPosition,
+ CharacterHitTest::TAP,
+ matchedCharacter);
+
+ for(const auto& anchor : controller.mImpl->mModel->mLogicalModel->mAnchors)
+ {
+ // Anchor clicked if the calculated cursor position is within the range of anchor.
+ if(cursorPosition >= anchor.startIndex && cursorPosition < anchor.endIndex)
+ {
+ if(controller.mImpl->mAnchorControlInterface && anchor.href)
+ {
+ std::string href(anchor.href);
+ controller.mImpl->mAnchorControlInterface->AnchorClicked(href);
+ break;
+ }
+ }
+ }
+}
+
void Controller::EventHandler::TapEvent(Controller& controller, unsigned int tapCount, float x, float y)
{
DALI_ASSERT_DEBUG(controller.mImpl->mEventData && "Unexpected TapEvent");
if(controller.mImpl->IsShowingPlaceholderText() && !controller.mImpl->IsFocusedPlaceholderAvailable())
{
// Hide placeholder text
- controller.ResetText();
+ TextUpdater::ResetText(controller);
}
if(EventData::INACTIVE == state)
}
}
+void Controller::EventHandler::SelectEvent(Controller& controller, const uint32_t start, const uint32_t end, SelectionType selectType)
+{
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::SelectEvent\n");
+
+ if(NULL != controller.mImpl->mEventData)
+ {
+ if(selectType == SelectionType::RANGE)
+ {
+ Event event(Event::SELECT_RANGE);
+ event.p2.mUint = start;
+ event.p3.mUint = end;
+ controller.mImpl->mEventData->mEventQueue.push_back(event);
+ }
+
+ controller.mImpl->mEventData->mCheckScrollAmount = true;
+ controller.mImpl->mEventData->mIsLeftHandleSelected = true;
+ controller.mImpl->mEventData->mIsRightHandleSelected = true;
+ controller.mImpl->RequestRelayout();
+ }
+}
+
void Controller::EventHandler::ProcessModifyEvents(Controller& controller)
{
Vector<ModifyEvent>& events = controller.mImpl->mModifyEvents;
// 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(NULL != controller.mImpl->mEventData)
{
+ uint32_t oldStart, oldEnd;
+ oldStart = controller.mImpl->mEventData->mLeftSelectionPosition;
+ oldEnd = controller.mImpl->mEventData->mRightSelectionPosition;
+
// When the text is being modified, delay cursor blinking
controller.mImpl->mEventData->mDecorator->DelayCursorBlink();
// Update selection position after modifying the text
controller.mImpl->mEventData->mLeftSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
controller.mImpl->mEventData->mRightSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
+
+ if(controller.mImpl->mSelectableControlInterface != nullptr && controller.mImpl->mEventData->mState == EventData::SELECTING)
+ {
+ controller.mImpl->mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, controller.mImpl->mEventData->mLeftSelectionPosition, controller.mImpl->mEventData->mRightSelectionPosition);
+ }
}
// DISCARD temporary text
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;
(NULL != controller.mImpl->mEditableControlInterface))
{
// Do this last since it provides callbacks into application code
- controller.mImpl->mEditableControlInterface->TextChanged();
+ controller.mImpl->mEditableControlInterface->TextChanged(false);
}
return callbackData;
controller.mImpl->SetClipboardHideEnable(false);
// Paste
- controller.PasteText(stringToPaste);
+ TextUpdater::PasteText(controller, stringToPaste);
controller.mImpl->SetClipboardHideEnable(true);
}
{
case Toolkit::TextSelectionPopup::CUT:
{
- if(!controller.IsEditable()) return;
- controller.mImpl->SendSelectionToClipboard(true); // Synchronous call to modify text
- controller.mImpl->mOperationsPending = ALL_OPERATIONS;
-
- if((0u != controller.mImpl->mModel->mLogicalModel->mText.Count()) ||
- !controller.mImpl->IsPlaceholderAvailable())
- {
- controller.mImpl->QueueModifyEvent(ModifyEvent::TEXT_DELETED);
- }
- else
- {
- controller.ShowPlaceholderText();
- }
-
- controller.mImpl->mEventData->mUpdateCursorPosition = true;
- controller.mImpl->mEventData->mScrollAfterDelete = true;
-
- controller.mImpl->RequestRelayout();
-
- if(NULL != controller.mImpl->mEditableControlInterface)
- {
- controller.mImpl->mEditableControlInterface->TextChanged();
- }
+ controller.CutText();
break;
}
case Toolkit::TextSelectionPopup::COPY:
{
- controller.mImpl->SendSelectionToClipboard(false); // Text not modified
-
- controller.mImpl->mEventData->mUpdateCursorPosition = true;
-
- controller.mImpl->RequestRelayout(); // Cursor, Handles, Selection Highlight, Popup
+ controller.CopyText();
break;
}
case Toolkit::TextSelectionPopup::PASTE:
{
- controller.mImpl->RequestGetTextFromClipboard(); // Request clipboard service to retrieve an item
+ controller.PasteText();
break;
}
case Toolkit::TextSelectionPopup::SELECT:
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: