diff --git a/include/Nazara/Widgets/AbstractTextAreaWidget.hpp b/include/Nazara/Widgets/AbstractTextAreaWidget.hpp index a1615b04f..074476b64 100644 --- a/include/Nazara/Widgets/AbstractTextAreaWidget.hpp +++ b/include/Nazara/Widgets/AbstractTextAreaWidget.hpp @@ -73,10 +73,13 @@ namespace Nz NazaraSignal(OnTextAreaCursorMove, const AbstractTextAreaWidget* /*textArea*/, Vector2ui* /*newCursorPosition*/); NazaraSignal(OnTextAreaKeyBackspace, const AbstractTextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/); + NazaraSignal(OnTextAreaKeyCopy, const AbstractTextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/); + NazaraSignal(OnTextAreaKeyCut, const AbstractTextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/); NazaraSignal(OnTextAreaKeyDown, const AbstractTextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/); NazaraSignal(OnTextAreaKeyEnd, const AbstractTextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/); NazaraSignal(OnTextAreaKeyHome, const AbstractTextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/); NazaraSignal(OnTextAreaKeyLeft, const AbstractTextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/); + NazaraSignal(OnTextAreaKeyPaste, const AbstractTextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/); NazaraSignal(OnTextAreaKeyReturn, const AbstractTextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/); NazaraSignal(OnTextAreaKeyRight, const AbstractTextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/); NazaraSignal(OnTextAreaKeyUp, const AbstractTextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/); @@ -86,13 +89,15 @@ namespace Nz virtual AbstractTextDrawer& GetTextDrawer() = 0; virtual const AbstractTextDrawer& GetTextDrawer() const = 0; - void Layout() override; + virtual void CopySelectionToClipboard(const Vector2ui& selectionBegin, const Vector2ui& selectionEnd) = 0; virtual void HandleIndentation(bool add) = 0; virtual void HandleSelectionIndentation(bool add) = 0; virtual void HandleWordCursorMove(bool left) = 0; bool IsFocusable() const override; + void Layout() override; + void OnFocusLost() override; void OnFocusReceived() override; bool OnKeyPressed(const WindowEvent::KeyEvent& key) override; @@ -103,10 +108,13 @@ namespace Nz void OnMouseMoved(int x, int y, int deltaX, int deltaY) override; void OnTextEntered(char32_t character, bool repeated) override; + virtual void PasteFromClipboard(const Vector2ui& targetPosition) = 0; + + void RefreshCursor(); + inline void SetCursorPositionInternal(std::size_t glyphIndex); inline void SetCursorPositionInternal(Vector2ui cursorPosition); - void RefreshCursor(); virtual void UpdateDisplayText() = 0; void UpdateTextSprite(); diff --git a/include/Nazara/Widgets/RichTextAreaWidget.hpp b/include/Nazara/Widgets/RichTextAreaWidget.hpp index 2952510e7..158f36168 100644 --- a/include/Nazara/Widgets/RichTextAreaWidget.hpp +++ b/include/Nazara/Widgets/RichTextAreaWidget.hpp @@ -50,6 +50,8 @@ namespace Nz RichTextAreaWidget& operator=(RichTextAreaWidget&&) = default; private: + void CopySelectionToClipboard(const Vector2ui& selectionBegin, const Vector2ui& selectionEnd) override; + AbstractTextDrawer& GetTextDrawer() override; const AbstractTextDrawer& GetTextDrawer() const override; @@ -57,6 +59,8 @@ namespace Nz void HandleSelectionIndentation(bool add) override; void HandleWordCursorMove(bool left) override; + void PasteFromClipboard(const Vector2ui& targetPosition) override; + void UpdateDisplayText() override; RichTextDrawer m_drawer; diff --git a/include/Nazara/Widgets/TextAreaWidget.hpp b/include/Nazara/Widgets/TextAreaWidget.hpp index f9dbbd024..f7025e148 100644 --- a/include/Nazara/Widgets/TextAreaWidget.hpp +++ b/include/Nazara/Widgets/TextAreaWidget.hpp @@ -57,6 +57,8 @@ namespace Nz NazaraSignal(OnTextChanged, const AbstractTextAreaWidget* /*textArea*/, const std::string& /*text*/); private: + void CopySelectionToClipboard(const Vector2ui& selectionBegin, const Vector2ui& selectionEnd) override; + AbstractTextDrawer& GetTextDrawer() override; const AbstractTextDrawer& GetTextDrawer() const override; @@ -64,6 +66,8 @@ namespace Nz void HandleSelectionIndentation(bool add) override; void HandleWordCursorMove(bool left) override; + void PasteFromClipboard(const Vector2ui& targetPosition) override; + void UpdateDisplayText() override; void UpdateMinimumSize(); diff --git a/src/Nazara/Widgets/AbstractTextAreaWidget.cpp b/src/Nazara/Widgets/AbstractTextAreaWidget.cpp index f28f4c3cb..bb7885391 100644 --- a/src/Nazara/Widgets/AbstractTextAreaWidget.cpp +++ b/src/Nazara/Widgets/AbstractTextAreaWidget.cpp @@ -165,6 +165,59 @@ namespace Nz switch (key.virtualKey) { + // Copy (Ctrl+C) + case Keyboard::VKey::C: + { + if (!key.control) + break; + + bool ignoreDefaultAction = (m_echoMode != EchoMode::Normal); + OnTextAreaKeyCopy(this, &ignoreDefaultAction); + + if (ignoreDefaultAction || !HasSelection()) + return true; + + CopySelectionToClipboard(m_cursorPositionBegin, m_cursorPositionEnd); + return true; + } + + // Paste (Ctrl+V) + case Keyboard::VKey::V: + { + if (!key.control) + break; + + bool ignoreDefaultAction = false; + OnTextAreaKeyPaste(this, &ignoreDefaultAction); + + if (ignoreDefaultAction) + return true; + + if (HasSelection()) + EraseSelection(); + + PasteFromClipboard(m_cursorPositionBegin); + return true; + } + + // Cut (Ctrl+X) + case Keyboard::VKey::X: + { + if (!key.control) + break; + + bool ignoreDefaultAction = (m_echoMode != EchoMode::Normal); + OnTextAreaKeyCut(this, &ignoreDefaultAction); + + if (ignoreDefaultAction || !HasSelection()) + return true; + + CopySelectionToClipboard(m_cursorPositionBegin, m_cursorPositionEnd); + EraseSelection(); + + return true; + } + case Keyboard::VKey::Backspace: { bool ignoreDefaultAction = false; diff --git a/src/Nazara/Widgets/RichTextAreaWidget.cpp b/src/Nazara/Widgets/RichTextAreaWidget.cpp index dc9e2f0bb..2ea2dbf78 100644 --- a/src/Nazara/Widgets/RichTextAreaWidget.cpp +++ b/src/Nazara/Widgets/RichTextAreaWidget.cpp @@ -154,6 +154,11 @@ namespace Nz UpdateDisplayText(); } + void RichTextAreaWidget::CopySelectionToClipboard(const Vector2ui& selectionBegin, const Vector2ui& selectionEnd) + { + // TODO + } + AbstractTextDrawer& RichTextAreaWidget::GetTextDrawer() { return m_drawer; @@ -176,6 +181,11 @@ namespace Nz { } + void RichTextAreaWidget::PasteFromClipboard(const Vector2ui& targetPosition) + { + // TODO + } + void RichTextAreaWidget::UpdateDisplayText() { /*m_drawer.Clear(); diff --git a/src/Nazara/Widgets/TextAreaWidget.cpp b/src/Nazara/Widgets/TextAreaWidget.cpp index c0a6a3115..8c9fa0a66 100644 --- a/src/Nazara/Widgets/TextAreaWidget.cpp +++ b/src/Nazara/Widgets/TextAreaWidget.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -110,6 +111,17 @@ namespace Nz } } + void TextAreaWidget::CopySelectionToClipboard(const Vector2ui& selectionBegin, const Vector2ui& selectionEnd) + { + std::size_t glyphCount = ComputeCharacterCount(m_text); + assert(glyphCount > 0); + + std::size_t startIndex = GetCharacterPosition(m_text, GetGlyphIndex(selectionBegin)); + std::size_t endIndex = GetCharacterPosition(m_text, std::min(GetGlyphIndex(selectionEnd), glyphCount - 1)); + + Clipboard::SetString(m_text.substr(startIndex, endIndex - startIndex)); + } + AbstractTextDrawer& TextAreaWidget::GetTextDrawer() { return m_drawer; @@ -216,6 +228,21 @@ namespace Nz } } + void TextAreaWidget::PasteFromClipboard(const Vector2ui& targetPosition) + { + std::size_t glyphCount = ComputeCharacterCount(m_text); + std::size_t targetIndex = GetCharacterPosition(m_text, std::min(GetGlyphIndex(targetPosition), glyphCount)); + + std::string clipboardString = Clipboard::GetString(); + if (clipboardString.empty()) + return; + + m_text.insert(targetIndex, clipboardString); + UpdateDisplayText(); + + SetCursorPosition(targetIndex + ComputeCharacterCount(clipboardString)); + } + void TextAreaWidget::UpdateDisplayText() { switch (m_echoMode)