From 49afc0dd527fa11d087b2ac8c9770338799f2992 Mon Sep 17 00:00:00 2001 From: David Capello Date: Tue, 27 Aug 2024 14:38:16 -0300 Subject: [PATCH] Add support to move the text box when we drag it from the edges --- src/app/ui/editor/writing_text_state.cpp | 80 ++++++++++++++++++++++-- src/app/ui/editor/writing_text_state.h | 25 +++++++- 2 files changed, 99 insertions(+), 6 deletions(-) diff --git a/src/app/ui/editor/writing_text_state.cpp b/src/app/ui/editor/writing_text_state.cpp index 2a501b311..a3a77b274 100644 --- a/src/app/ui/editor/writing_text_state.cpp +++ b/src/app/ui/editor/writing_text_state.cpp @@ -99,6 +99,12 @@ public: return m_extraCel; } + void setExtraCelBounds(const gfx::Rect& bounds) { + m_extraCel->cel()->setBounds(bounds); + renderExtraCelBase(); + renderExtraCelText(true); + } + private: bool onProcessMessage(Message* msg) override { switch (msg->type()) { @@ -237,7 +243,8 @@ private: WritingTextState::WritingTextState(Editor* editor, const gfx::Rect& bounds) - : m_editor(editor) + : m_delayedMouseMove(this, editor, 5) + , m_editor(editor) , m_bounds(bounds) , m_entry(new TextEditor(editor, editor->getSite(), bounds)) { @@ -258,8 +265,22 @@ WritingTextState::~WritingTextState() bool WritingTextState::onMouseDown(Editor* editor, MouseMessage* msg) { + m_delayedMouseMove.onMouseDown(msg); + m_hit = calcHit(editor, msg->position()); + if (msg->left()) { + if (m_hit == Hit::Edges) { + m_mouseMoveReceived = false; + m_movingBounds = true; + m_cursorStart = editor->screenToEditorF(msg->position()); + m_boundsOrigin = m_bounds.origin(); + + editor->captureMouse(); + return true; + } + drop(); + return true; } else if (msg->right()) { cancel(); @@ -271,16 +292,53 @@ bool WritingTextState::onMouseDown(Editor* editor, MouseMessage* msg) bool WritingTextState::onMouseUp(Editor* editor, MouseMessage* msg) { + m_delayedMouseMove.onMouseUp(msg); + const bool result = StandbyState::onMouseUp(editor, msg); - if (msg->middle()) { - if (m_entry) - m_entry->requestFocus(); + if (m_movingBounds) { + m_movingBounds = false; + + // Drop if the user just clicked (so other text box is created) + if (!m_mouseMoveReceived) + drop(); } + return result; } -bool WritingTextState::onSetCursor(Editor* editor, const gfx::Point&) +bool WritingTextState::onMouseMove(Editor* editor, ui::MouseMessage* msg) { + m_delayedMouseMove.onMouseMove(msg); + + // Use StandbyState implementation + return StandbyState::onMouseMove(editor, msg); +} + +void WritingTextState::onCommitMouseMove(Editor* editor, + const gfx::PointF& spritePos) +{ + if (!m_movingBounds) + return; + + gfx::Point delta(spritePos - m_cursorStart); + if (delta.x == 0 && delta.y == 0) + return; + + m_mouseMoveReceived = true; + + m_bounds.setOrigin(gfx::Point(delta + m_boundsOrigin)); + m_entry->setExtraCelBounds(m_bounds); + m_entry->setBounds(calcEntryBounds()); +} + +bool WritingTextState::onSetCursor(Editor* editor, + const gfx::Point& mouseScreenPos) +{ + if (calcHit(editor, mouseScreenPos) == Hit::Edges) { + editor->showMouseCursor(kMoveCursor); + return true; + } + editor->showMouseCursor(kArrowCursor); return true; } @@ -438,4 +496,16 @@ void WritingTextState::drop() m_editor->invalidate(); } +WritingTextState::Hit WritingTextState::calcHit(Editor* editor, + const gfx::Point& mouseScreenPos) +{ + auto edges = editor->editorToScreen(m_bounds); + if (!edges.contains(mouseScreenPos) && + edges.enlarge(32*guiscale()).contains(mouseScreenPos)) { + return Hit::Edges; + } + + return Hit::Normal; +} + } // namespace app diff --git a/src/app/ui/editor/writing_text_state.h b/src/app/ui/editor/writing_text_state.h index c88682a69..02ce2b84c 100644 --- a/src/app/ui/editor/writing_text_state.h +++ b/src/app/ui/editor/writing_text_state.h @@ -8,6 +8,7 @@ #define APP_UI_EDITOR_WRITING_TEXT_STATE_H_INCLUDED #pragma once +#include "app/ui/editor/delayed_mouse_move.h" #include "app/ui/editor/standby_state.h" #include @@ -15,7 +16,8 @@ namespace app { class CommandExecutionEvent; - class WritingTextState : public StandbyState { + class WritingTextState : public StandbyState + , DelayedMouseMoveDelegate { public: WritingTextState(Editor* editor, const gfx::Rect& bounds); @@ -28,11 +30,21 @@ namespace app { void onEditorResize(Editor* editor) override; bool onMouseDown(Editor* editor, ui::MouseMessage* msg) override; bool onMouseUp(Editor* editor, ui::MouseMessage* msg) override; + bool onMouseMove(Editor* editor, ui::MouseMessage* msg) override; bool onSetCursor(Editor* editor, const gfx::Point& mouseScreenPos) override; bool onKeyDown(Editor* editor, ui::KeyMessage* msg) override; bool onKeyUp(Editor* editor, ui::KeyMessage* msg) override; private: + enum class Hit { + Normal, + Edges, + }; + + // DelayedMouseMoveDelegate impl + void onCommitMouseMove(Editor* editor, + const gfx::PointF& spritePos) override; + gfx::Rect calcEntryBounds(); void onBeforeCommandExecution(CommandExecutionEvent& ev); void onFontChange(); @@ -41,8 +53,11 @@ namespace app { void switchCaretVisiblity(); + Hit calcHit(Editor* editor, const gfx::Point& mouseScreenPos); + class TextEditor; + DelayedMouseMove m_delayedMouseMove; Editor* m_editor; gfx::Rect m_bounds; std::unique_ptr m_entry; @@ -50,6 +65,14 @@ namespace app { // True if the text was discarded. bool m_discarded = false; + // To move text entry bounds when we drag the mouse from the edges + // of the TextEditor. + Hit m_hit = Hit::Normal; + bool m_mouseMoveReceived = false; + bool m_movingBounds = false; + gfx::PointF m_cursorStart; + gfx::Point m_boundsOrigin; + obs::scoped_connection m_beforeCmdConn; obs::scoped_connection m_fontChangeConn; };