diff --git a/CMakeLists.txt b/CMakeLists.txt index b0745a5..76073e4 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,7 @@ set(sources "src/main.cpp" "src/GUIHolder.cpp" "src/GlobalConfig.cpp" "src/RichTextUserInput.cpp" + "src/CustomEvents.cpp" "src/Bookmarks/BookmarkListItem.cpp" "src/Bookmarks/BookmarkManager.cpp" "src/ResourceDisplay/ResourceDisplay.cpp" diff --git a/src/CustomEvents.cpp b/src/CustomEvents.cpp new file mode 100644 index 0000000..a9878f9 --- /dev/null +++ b/src/CustomEvents.cpp @@ -0,0 +1,38 @@ +#include "CustomEvents.hpp" +#include +#include + +namespace CustomEvents { + +bool alreadyInitialized = false; + +uint32_t PASTE_EVENT; +std::queue pasteEventData; + +void init() { + if(!alreadyInitialized) { + PASTE_EVENT = SDL_RegisterEvents(1); + alreadyInitialized = true; + } +} + +bool emit_paste_event(const PasteEventData& pasteData) { + SDL_Event event; + SDL_zero(event); + event.type = PASTE_EVENT; + if(SDL_PushEvent(&event)) { + pasteEventData.push(pasteData); + return true; + } + return false; +} + +const PasteEventData& get_paste_event_data() { + return pasteEventData.front(); +} + +void pop_paste_event_data() { + pasteEventData.pop(); +} + +} diff --git a/src/CustomEvents.hpp b/src/CustomEvents.hpp new file mode 100644 index 0000000..2075289 --- /dev/null +++ b/src/CustomEvents.hpp @@ -0,0 +1,26 @@ +#pragma once +#include +#include +#include +#include "RichText/TextBox.hpp" + +namespace CustomEvents { + void init(); + + enum class PasteEventDataType { + TEXT, + IMAGE + }; + struct PasteEventData { + PasteEventDataType type; + std::string data; + std::optional richText; + std::optional mousePos; + }; + + bool emit_paste_event(const PasteEventData& pasteData); + const PasteEventData& get_paste_event_data(); + void pop_paste_event_data(); + + extern uint32_t PASTE_EVENT; +} diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index fa5c3df..ef28773 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -58,6 +58,10 @@ void DrawingProgram::on_tab_out() { controls.middleClickHeld = false; } +void DrawingProgram::input_paste_callback(const CustomEvents::PasteEventData& paste) { + drawTool->input_paste_callback(paste); +} + void DrawingProgram::input_drop_file_callback(const InputManager::DropCallbackArgs& drop) { if(std::filesystem::is_regular_file(drop.data)) { #ifdef __EMSCRIPTEN_ @@ -83,6 +87,14 @@ void DrawingProgram::input_drop_text_callback(const InputManager::DropCallbackAr } } +void DrawingProgram::input_text_key_callback(const InputManager::KeyCallbackArgs& key) { + drawTool->input_text_key_callback(key); +} + +void DrawingProgram::input_text_callback(const InputManager::TextCallbackArgs& text) { + drawTool->input_text_callback(text); +} + void DrawingProgram::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) { auto buttonCallbacks = [&](const InputManager::MouseButtonCallbackArgs& b) { drawTool->input_mouse_button_on_canvas_callback(b); diff --git a/src/DrawingProgram/DrawingProgram.hpp b/src/DrawingProgram/DrawingProgram.hpp index a6fff4b..2bb34c7 100644 --- a/src/DrawingProgram/DrawingProgram.hpp +++ b/src/DrawingProgram/DrawingProgram.hpp @@ -59,8 +59,11 @@ class DrawingProgram { void send_transforms_for(const std::vector& objsToSendTransformsFor); void on_tab_out(); + void input_paste_callback(const CustomEvents::PasteEventData& paste); void input_drop_text_callback(const InputManager::DropCallbackArgs& drop); void input_drop_file_callback(const InputManager::DropCallbackArgs& drop); + void input_text_key_callback(const InputManager::KeyCallbackArgs& key); + void input_text_callback(const InputManager::TextCallbackArgs& text); void input_key_callback(const InputManager::KeyCallbackArgs& key); void input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button); void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion); @@ -131,7 +134,6 @@ class DrawingProgram { std::optional rightClickPopupLocation; - uint32_t nextID = 0; friend class EyeDropperTool; diff --git a/src/DrawingProgram/Tools/DrawingProgramToolBase.cpp b/src/DrawingProgram/Tools/DrawingProgramToolBase.cpp index 453ef28..6dd5081 100644 --- a/src/DrawingProgram/Tools/DrawingProgramToolBase.cpp +++ b/src/DrawingProgram/Tools/DrawingProgramToolBase.cpp @@ -55,6 +55,9 @@ std::unique_ptr DrawingProgramToolBase::allocate_tool_ty return nullptr; } +void DrawingProgramToolBase::input_paste_callback(const CustomEvents::PasteEventData& paste) {} +void DrawingProgramToolBase::input_text_key_callback(const InputManager::KeyCallbackArgs& key) {} +void DrawingProgramToolBase::input_text_callback(const InputManager::TextCallbackArgs& text) {} void DrawingProgramToolBase::input_key_callback(const InputManager::KeyCallbackArgs& key) {} void DrawingProgramToolBase::input_mouse_button_on_canvas_callback(const InputManager::MouseButtonCallbackArgs& button) {} void DrawingProgramToolBase::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) {} diff --git a/src/DrawingProgram/Tools/DrawingProgramToolBase.hpp b/src/DrawingProgram/Tools/DrawingProgramToolBase.hpp index f26a26b..48c0db3 100644 --- a/src/DrawingProgram/Tools/DrawingProgramToolBase.hpp +++ b/src/DrawingProgram/Tools/DrawingProgramToolBase.hpp @@ -36,6 +36,9 @@ class DrawingProgramToolBase { virtual void draw(SkCanvas* canvas, const DrawData& drawData) = 0; virtual void switch_tool(DrawingProgramToolType newTool) = 0; virtual bool prevent_undo_or_redo() = 0; + virtual void input_paste_callback(const CustomEvents::PasteEventData& paste); + virtual void input_text_key_callback(const InputManager::KeyCallbackArgs& key); + virtual void input_text_callback(const InputManager::TextCallbackArgs& text); virtual void input_key_callback(const InputManager::KeyCallbackArgs& key); virtual void input_mouse_button_on_canvas_callback(const InputManager::MouseButtonCallbackArgs& button); virtual void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion); diff --git a/src/DrawingProgram/Tools/EditTool.cpp b/src/DrawingProgram/Tools/EditTool.cpp index 5970b74..87d17b8 100644 --- a/src/DrawingProgram/Tools/EditTool.cpp +++ b/src/DrawingProgram/Tools/EditTool.cpp @@ -33,7 +33,7 @@ void EditTool::gui_toolbox() { auto& gui = drawP.world.main.g.gui; if(objInfoBeingEdited) - compEditTool->edit_gui(objInfoBeingEdited); + compEditTool->edit_gui(); else { gui.new_id("edit tool", [&] { text_label_centered(gui, "Edit"); @@ -46,6 +46,21 @@ void EditTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp) { switch_tool(get_type()); } +void EditTool::input_paste_callback(const CustomEvents::PasteEventData& paste) { + if(objInfoBeingEdited) + compEditTool->input_paste_callback(paste); +} + +void EditTool::input_text_key_callback(const InputManager::KeyCallbackArgs& key) { + if(objInfoBeingEdited) + compEditTool->input_text_key_callback(key); +} + +void EditTool::input_text_callback(const InputManager::TextCallbackArgs& text) { + if(objInfoBeingEdited) + compEditTool->input_text_callback(text); +} + void EditTool::input_key_callback(const InputManager::KeyCallbackArgs& key) { drawP.selection.input_key_callback_modify_selection(key); } @@ -122,12 +137,12 @@ void EditTool::input_mouse_button_on_canvas_callback(const InputManager::MouseBu switch_tool(get_type()); if(objInfoBeingEdited) - compEditTool->input_mouse_button_on_canvas_callback(objInfoBeingEdited, button, pointDragging); + compEditTool->input_mouse_button_on_canvas_callback(button, pointDragging); } } else { if(objInfoBeingEdited) - compEditTool->input_mouse_button_on_canvas_callback(objInfoBeingEdited, button, pointDragging); + compEditTool->input_mouse_button_on_canvas_callback(button, pointDragging); if(pointDragging) pointDragging = nullptr; } @@ -147,14 +162,14 @@ void EditTool::input_mouse_motion_callback(const InputManager::MouseMotionCallba objInfoBeingEdited->obj->commit_update(drawP); } } - compEditTool->input_mouse_motion_callback(objInfoBeingEdited, motion, pointDragging); + compEditTool->input_mouse_motion_callback(motion, pointDragging); } drawP.selection.input_mouse_motion_callback_modify_selection(motion); } void EditTool::right_click_popup_gui(Vector2f popupPos) { if(objInfoBeingEdited) - return compEditTool->right_click_popup_gui(objInfoBeingEdited, popupPos); + return compEditTool->right_click_popup_gui(popupPos); else return drawP.selection_action_menu(popupPos); } @@ -165,7 +180,7 @@ void EditTool::add_point_handle(const HandleData& handle) { void EditTool::switch_tool(DrawingProgramToolType newTool) { if(objInfoBeingEdited) { - compEditTool->commit_edit_updates(objInfoBeingEdited, prevData); + compEditTool->commit_edit_updates(prevData); objInfoBeingEdited->obj->commit_update(drawP); objInfoBeingEdited->obj->send_comp_update(drawP, true); @@ -221,23 +236,23 @@ void EditTool::edit_start(CanvasComponentContainer::ObjInfo* comp, bool initUndo bool isEditing = true; switch(comp->obj->get_comp().get_type()) { case CanvasComponentType::TEXTBOX: { - compEditTool = std::make_unique(drawP); + compEditTool = std::make_unique(drawP, comp); break; } case CanvasComponentType::ELLIPSE: { - compEditTool = std::make_unique(drawP); + compEditTool = std::make_unique(drawP, comp); break; } case CanvasComponentType::RECTANGLE: { - compEditTool = std::make_unique(drawP); + compEditTool = std::make_unique(drawP, comp); break; } case CanvasComponentType::IMAGE: { - compEditTool = std::make_unique(drawP); + compEditTool = std::make_unique(drawP, comp); break; } case CanvasComponentType::BRUSHSTROKE: { - compEditTool = std::make_unique(drawP); + compEditTool = std::make_unique(drawP, comp); break; } default: { @@ -249,7 +264,7 @@ void EditTool::edit_start(CanvasComponentContainer::ObjInfo* comp, bool initUndo objInfoBeingEdited = comp; oldData = comp->obj->get_comp().get_data_copy(); undoAfterEditDone = initUndoAfterEditDone; - compEditTool->edit_start(*this, objInfoBeingEdited, prevData); + compEditTool->edit_start(*this, prevData); drawP.world.main.g.gui.set_to_layout(); } } @@ -261,7 +276,7 @@ bool EditTool::is_editable(CanvasComponentContainer::ObjInfo* comp) { void EditTool::tool_update() { if(objInfoBeingEdited) { objInfoBeingEdited->obj->send_comp_update(drawP, false); - bool shouldNotReset = compEditTool->edit_update(objInfoBeingEdited); + bool shouldNotReset = compEditTool->edit_update(); if(!shouldNotReset) switch_tool(get_type()); } diff --git a/src/DrawingProgram/Tools/EditTool.hpp b/src/DrawingProgram/Tools/EditTool.hpp index 921b9bf..0f40581 100644 --- a/src/DrawingProgram/Tools/EditTool.hpp +++ b/src/DrawingProgram/Tools/EditTool.hpp @@ -26,6 +26,9 @@ class EditTool : public DrawingProgramToolBase { virtual void switch_tool(DrawingProgramToolType newTool) override; virtual void draw(SkCanvas* canvas, const DrawData& drawData) override; virtual bool prevent_undo_or_redo() override; + virtual void input_paste_callback(const CustomEvents::PasteEventData& paste) override; + virtual void input_text_key_callback(const InputManager::KeyCallbackArgs& key) override; + virtual void input_text_callback(const InputManager::TextCallbackArgs& text) override; virtual void input_key_callback(const InputManager::KeyCallbackArgs& key) override; virtual void input_mouse_button_on_canvas_callback(const InputManager::MouseButtonCallbackArgs& button) override; virtual void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) override; diff --git a/src/DrawingProgram/Tools/EditTools/BrushEditTool.cpp b/src/DrawingProgram/Tools/EditTools/BrushEditTool.cpp index a1f3c12..16ddbc2 100644 --- a/src/DrawingProgram/Tools/EditTools/BrushEditTool.cpp +++ b/src/DrawingProgram/Tools/EditTools/BrushEditTool.cpp @@ -7,18 +7,18 @@ #include "../../../GUIStuff/ElementHelpers/TextLabelHelpers.hpp" #include "../../../GUIStuff/ElementHelpers/LayoutHelpers.hpp" -BrushEditTool::BrushEditTool(DrawingProgram& initDrawP): - DrawingProgramEditToolBase(initDrawP) +BrushEditTool::BrushEditTool(DrawingProgram& initDrawP, CanvasComponentContainer::ObjInfo* initComp): + DrawingProgramEditToolBase(initDrawP, initComp) {} -void BrushEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) { +void BrushEditTool::edit_gui() { using namespace GUIStuff; using namespace ElementHelpers; auto& a = static_cast(comp->obj->get_comp()); auto& gui = drawP.world.main.g.gui; Toolbar& t = drawP.world.main.toolbar; - auto commit_update_func = [&, comp] { comp->obj->commit_update(drawP); }; + auto commit_update_func = [&] { comp->obj->commit_update(drawP); }; gui.new_id("edit tool brush", [&] { text_label_centered(gui, "Edit Brush Stroke"); @@ -29,14 +29,14 @@ void BrushEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) { }); } -void BrushEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { +void BrushEditTool::edit_start(EditTool& editTool, std::any& prevData) { auto& a = static_cast(comp->obj->get_comp()); oldColor = a.d.color; } -void BrushEditTool::commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { +void BrushEditTool::commit_edit_updates(std::any& prevData) { } -bool BrushEditTool::edit_update(CanvasComponentContainer::ObjInfo* comp) { +bool BrushEditTool::edit_update() { return true; } diff --git a/src/DrawingProgram/Tools/EditTools/BrushEditTool.hpp b/src/DrawingProgram/Tools/EditTools/BrushEditTool.hpp index 027fb39..4bd6ee1 100644 --- a/src/DrawingProgram/Tools/EditTools/BrushEditTool.hpp +++ b/src/DrawingProgram/Tools/EditTools/BrushEditTool.hpp @@ -8,11 +8,11 @@ class DrawingProgram; class BrushEditTool : public DrawingProgramEditToolBase { public: - BrushEditTool(DrawingProgram& initDrawP); - virtual void edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override; - virtual void commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override; - virtual bool edit_update(CanvasComponentContainer::ObjInfo* comp) override; - virtual void edit_gui(CanvasComponentContainer::ObjInfo* comp) override; + BrushEditTool(DrawingProgram& initDrawP, CanvasComponentContainer::ObjInfo* initComp); + virtual void edit_start(EditTool& editTool, std::any& prevData) override; + virtual void commit_edit_updates(std::any& prevData) override; + virtual bool edit_update() override; + virtual void edit_gui() override; private: Vector4f oldColor; }; diff --git a/src/DrawingProgram/Tools/EditTools/DrawingProgramEditToolBase.cpp b/src/DrawingProgram/Tools/EditTools/DrawingProgramEditToolBase.cpp index e4416e6..8901e67 100644 --- a/src/DrawingProgram/Tools/EditTools/DrawingProgramEditToolBase.cpp +++ b/src/DrawingProgram/Tools/EditTools/DrawingProgramEditToolBase.cpp @@ -1,17 +1,21 @@ #include "DrawingProgramEditToolBase.hpp" #include "../../../MainProgram.hpp" -DrawingProgramEditToolBase::DrawingProgramEditToolBase(DrawingProgram& initDrawP): - drawP(initDrawP) +DrawingProgramEditToolBase::DrawingProgramEditToolBase(DrawingProgram& initDrawP, CanvasComponentContainer::ObjInfo* initComp): + drawP(initDrawP), + comp(initComp) {} -void DrawingProgramEditToolBase::right_click_popup_gui(CanvasComponentContainer::ObjInfo* comp, Vector2f popupPos) { +void DrawingProgramEditToolBase::right_click_popup_gui(Vector2f popupPos) { Toolbar& t = drawP.world.main.toolbar; t.paint_popup(popupPos); } -void DrawingProgramEditToolBase::input_key_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::KeyCallbackArgs& key) {} -void DrawingProgramEditToolBase::input_mouse_button_on_canvas_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::MouseButtonCallbackArgs& button, bool isDraggingPoint) {} -void DrawingProgramEditToolBase::input_mouse_motion_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::MouseMotionCallbackArgs& motion, bool isDraggingPoint) {} +void DrawingProgramEditToolBase::input_paste_callback(const CustomEvents::PasteEventData& paste) {} +void DrawingProgramEditToolBase::input_text_key_callback(const InputManager::KeyCallbackArgs& key) {} +void DrawingProgramEditToolBase::input_text_callback(const InputManager::TextCallbackArgs& text) {} +void DrawingProgramEditToolBase::input_key_callback(const InputManager::KeyCallbackArgs& key) {} +void DrawingProgramEditToolBase::input_mouse_button_on_canvas_callback(const InputManager::MouseButtonCallbackArgs& button, bool isDraggingPoint) {} +void DrawingProgramEditToolBase::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion, bool isDraggingPoint) {} DrawingProgramEditToolBase::~DrawingProgramEditToolBase() {} diff --git a/src/DrawingProgram/Tools/EditTools/DrawingProgramEditToolBase.hpp b/src/DrawingProgram/Tools/EditTools/DrawingProgramEditToolBase.hpp index 3186ee6..a72efe0 100644 --- a/src/DrawingProgram/Tools/EditTools/DrawingProgramEditToolBase.hpp +++ b/src/DrawingProgram/Tools/EditTools/DrawingProgramEditToolBase.hpp @@ -8,16 +8,20 @@ class EditTool; class DrawingProgramEditToolBase { public: - DrawingProgramEditToolBase(DrawingProgram& initDrawP); - virtual void edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* compContainer, std::any& prevData) = 0; - virtual void commit_edit_updates(CanvasComponentContainer::ObjInfo* compContainer, std::any& prevData) = 0; - virtual bool edit_update(CanvasComponentContainer::ObjInfo* compContainer) = 0; - virtual void edit_gui(CanvasComponentContainer::ObjInfo* compContainer) = 0; - virtual void right_click_popup_gui(CanvasComponentContainer::ObjInfo* comp, Vector2f popupPos); - virtual void input_key_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::KeyCallbackArgs& key); - virtual void input_mouse_button_on_canvas_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::MouseButtonCallbackArgs& button, bool isDraggingPoint); - virtual void input_mouse_motion_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::MouseMotionCallbackArgs& motion, bool isDraggingPoint); + DrawingProgramEditToolBase(DrawingProgram& initDrawP, CanvasComponentContainer::ObjInfo* initComp); + virtual void edit_start(EditTool& editTool, std::any& prevData) = 0; + virtual void commit_edit_updates(std::any& prevData) = 0; + virtual bool edit_update() = 0; + virtual void edit_gui() = 0; + virtual void right_click_popup_gui(Vector2f popupPos); + virtual void input_paste_callback(const CustomEvents::PasteEventData& paste); + virtual void input_text_key_callback(const InputManager::KeyCallbackArgs& key); + virtual void input_text_callback(const InputManager::TextCallbackArgs& text); + virtual void input_key_callback(const InputManager::KeyCallbackArgs& key); + virtual void input_mouse_button_on_canvas_callback(const InputManager::MouseButtonCallbackArgs& button, bool isDraggingPoint); + virtual void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion, bool isDraggingPoint); virtual ~DrawingProgramEditToolBase(); protected: DrawingProgram& drawP; + CanvasComponentContainer::ObjInfo* comp; }; diff --git a/src/DrawingProgram/Tools/EditTools/EllipseDrawEditTool.cpp b/src/DrawingProgram/Tools/EditTools/EllipseDrawEditTool.cpp index 493105f..c9729cf 100644 --- a/src/DrawingProgram/Tools/EditTools/EllipseDrawEditTool.cpp +++ b/src/DrawingProgram/Tools/EditTools/EllipseDrawEditTool.cpp @@ -12,19 +12,19 @@ #include "../../../GUIStuff/ElementHelpers/LayoutHelpers.hpp" #include "../../../GUIStuff/ElementHelpers/NumberSliderHelpers.hpp" -EllipseDrawEditTool::EllipseDrawEditTool(DrawingProgram& initDrawP): - DrawingProgramEditToolBase(initDrawP) +EllipseDrawEditTool::EllipseDrawEditTool(DrawingProgram& initDrawP, CanvasComponentContainer::ObjInfo* initComp): + DrawingProgramEditToolBase(initDrawP, initComp) {} -void EllipseDrawEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) { +void EllipseDrawEditTool::edit_gui() { using namespace GUIStuff; using namespace ElementHelpers; auto& a = static_cast(comp->obj->get_comp()); auto& gui = drawP.world.main.g.gui; Toolbar& t = drawP.world.main.toolbar; - auto commit_update_func = [&, comp] { comp->obj->commit_update(drawP); }; - auto commit_update_and_layout_func = [&, comp] { + auto commit_update_func = [&] { comp->obj->commit_update(drawP); }; + auto commit_update_and_layout_func = [&] { comp->obj->commit_update(drawP); drawP.world.main.g.gui.set_to_layout(); }; @@ -52,7 +52,7 @@ void EllipseDrawEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) { }); } -void EllipseDrawEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { +void EllipseDrawEditTool::edit_start(EditTool& editTool, std::any& prevData) { auto& a = static_cast(comp->obj->get_comp()); prevData = a.d; @@ -60,9 +60,9 @@ void EllipseDrawEditTool::edit_start(EditTool& editTool, CanvasComponentContaine editTool.add_point_handle({&a.d.p2, &a.d.p1, nullptr}); } -void EllipseDrawEditTool::commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { +void EllipseDrawEditTool::commit_edit_updates(std::any& prevData) { } -bool EllipseDrawEditTool::edit_update(CanvasComponentContainer::ObjInfo* comp) { +bool EllipseDrawEditTool::edit_update() { return true; } diff --git a/src/DrawingProgram/Tools/EditTools/EllipseDrawEditTool.hpp b/src/DrawingProgram/Tools/EditTools/EllipseDrawEditTool.hpp index c640803..9f9cc5a 100644 --- a/src/DrawingProgram/Tools/EditTools/EllipseDrawEditTool.hpp +++ b/src/DrawingProgram/Tools/EditTools/EllipseDrawEditTool.hpp @@ -9,11 +9,11 @@ class DrawingProgram; class EllipseDrawEditTool : public DrawingProgramEditToolBase { public: - EllipseDrawEditTool(DrawingProgram& initDrawP); - virtual void edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override; - virtual void commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override; - virtual bool edit_update(CanvasComponentContainer::ObjInfo* comp) override; - virtual void edit_gui(CanvasComponentContainer::ObjInfo* comp) override; + EllipseDrawEditTool(DrawingProgram& initDrawP, CanvasComponentContainer::ObjInfo* initComp); + virtual void edit_start(EditTool& editTool, std::any& prevData) override; + virtual void commit_edit_updates(std::any& prevData) override; + virtual bool edit_update() override; + virtual void edit_gui() override; private: void commit(); diff --git a/src/DrawingProgram/Tools/EditTools/ImageEditTool.cpp b/src/DrawingProgram/Tools/EditTools/ImageEditTool.cpp index 3ab20fc..f8abdd6 100644 --- a/src/DrawingProgram/Tools/EditTools/ImageEditTool.cpp +++ b/src/DrawingProgram/Tools/EditTools/ImageEditTool.cpp @@ -17,11 +17,11 @@ #include #endif -ImageEditTool::ImageEditTool(DrawingProgram& initDrawP): - DrawingProgramEditToolBase(initDrawP) +ImageEditTool::ImageEditTool(DrawingProgram& initDrawP, CanvasComponentContainer::ObjInfo* initComp): + DrawingProgramEditToolBase(initDrawP, initComp) {} -void ImageEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { +void ImageEditTool::edit_start(EditTool& editTool, std::any& prevData) { auto& a = static_cast(comp->obj->get_comp()); static Vector2f staticZero = {0.0f, 0.0f}; static Vector2f staticOne = {1.0f, 1.0f}; @@ -36,17 +36,17 @@ void ImageEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::Obj comp->obj->commit_update(drawP); } -void ImageEditTool::commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { +void ImageEditTool::commit_edit_updates(std::any& prevData) { auto& a = static_cast(comp->obj->get_comp()); a.d.editing = false; comp->obj->commit_update(drawP); } -bool ImageEditTool::edit_update(CanvasComponentContainer::ObjInfo* comp) { +bool ImageEditTool::edit_update() { return true; } -void ImageEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) { +void ImageEditTool::edit_gui() { using namespace GUIStuff; using namespace ElementHelpers; diff --git a/src/DrawingProgram/Tools/EditTools/ImageEditTool.hpp b/src/DrawingProgram/Tools/EditTools/ImageEditTool.hpp index 53ce119..bb24048 100644 --- a/src/DrawingProgram/Tools/EditTools/ImageEditTool.hpp +++ b/src/DrawingProgram/Tools/EditTools/ImageEditTool.hpp @@ -6,9 +6,9 @@ class DrawingProgram; class ImageEditTool : public DrawingProgramEditToolBase { public: - ImageEditTool(DrawingProgram& initDrawP); - virtual void edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override; - virtual void commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override; - virtual bool edit_update(CanvasComponentContainer::ObjInfo* comp) override; - virtual void edit_gui(CanvasComponentContainer::ObjInfo* comp) override; + ImageEditTool(DrawingProgram& initDrawP, CanvasComponentContainer::ObjInfo* initComp); + virtual void edit_start(EditTool& editTool, std::any& prevData) override; + virtual void commit_edit_updates(std::any& prevData) override; + virtual bool edit_update() override; + virtual void edit_gui() override; }; diff --git a/src/DrawingProgram/Tools/EditTools/RectDrawEditTool.cpp b/src/DrawingProgram/Tools/EditTools/RectDrawEditTool.cpp index 9a03afe..bb4b21b 100644 --- a/src/DrawingProgram/Tools/EditTools/RectDrawEditTool.cpp +++ b/src/DrawingProgram/Tools/EditTools/RectDrawEditTool.cpp @@ -9,20 +9,20 @@ #include "../../../GUIStuff/ElementHelpers/TextLabelHelpers.hpp" #include "../../../GUIStuff/ElementHelpers/RadioButtonHelpers.hpp" -RectDrawEditTool::RectDrawEditTool(DrawingProgram& initDrawP): - DrawingProgramEditToolBase(initDrawP) +RectDrawEditTool::RectDrawEditTool(DrawingProgram& initDrawP, CanvasComponentContainer::ObjInfo* initComp): + DrawingProgramEditToolBase(initDrawP, initComp) {} -void RectDrawEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) { +void RectDrawEditTool::edit_gui() { using namespace GUIStuff; using namespace ElementHelpers; auto& a = static_cast(comp->obj->get_comp()); - auto commit_update_and_layout_func = [&, comp] { + auto commit_update_and_layout_func = [&] { comp->obj->commit_update(drawP); drawP.world.main.g.gui.set_to_layout(); }; - auto commit_update_func = [&, comp] { comp->obj->commit_update(drawP); }; + auto commit_update_func = [&] { comp->obj->commit_update(drawP); }; Toolbar& t = drawP.world.main.toolbar; auto& gui = drawP.world.main.g.gui; @@ -50,16 +50,16 @@ void RectDrawEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) { }); } -void RectDrawEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { +void RectDrawEditTool::edit_start(EditTool& editTool, std::any& prevData) { auto& a = static_cast(comp->obj->get_comp()); prevData = a.d; editTool.add_point_handle({&a.d.p1, nullptr, &a.d.p2}); editTool.add_point_handle({&a.d.p2, &a.d.p1, nullptr}); } -void RectDrawEditTool::commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { +void RectDrawEditTool::commit_edit_updates(std::any& prevData) { } -bool RectDrawEditTool::edit_update(CanvasComponentContainer::ObjInfo* comp) { +bool RectDrawEditTool::edit_update() { return true; } diff --git a/src/DrawingProgram/Tools/EditTools/RectDrawEditTool.hpp b/src/DrawingProgram/Tools/EditTools/RectDrawEditTool.hpp index 5a2f2e2..a7883c3 100644 --- a/src/DrawingProgram/Tools/EditTools/RectDrawEditTool.hpp +++ b/src/DrawingProgram/Tools/EditTools/RectDrawEditTool.hpp @@ -8,11 +8,11 @@ class DrawingProgram; class RectDrawEditTool : public DrawingProgramEditToolBase { public: - RectDrawEditTool(DrawingProgram& initDrawP); - virtual void edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override; - virtual void commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override; - virtual bool edit_update(CanvasComponentContainer::ObjInfo* comp) override; - virtual void edit_gui(CanvasComponentContainer::ObjInfo* comp) override; + RectDrawEditTool(DrawingProgram& initDrawP, CanvasComponentContainer::ObjInfo* initComp); + virtual void edit_start(EditTool& editTool, std::any& prevData) override; + virtual void commit_edit_updates(std::any& prevData) override; + virtual bool edit_update() override; + virtual void edit_gui() override; private: std::optional oldData; }; diff --git a/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.cpp b/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.cpp index 7bcfd10..e92d15a 100644 --- a/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.cpp +++ b/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.cpp @@ -16,89 +16,137 @@ #include "../../../GUIStuff/ElementHelpers/TextLabelHelpers.hpp" #include "../../../GUIStuff/ElementHelpers/LayoutHelpers.hpp" +#include "../../../GUIStuff/ElementHelpers/ButtonHelpers.hpp" +#include "../../../GUIStuff/ElementHelpers/NumberSliderHelpers.hpp" #include "../../../GUIStuff/Elements/PositionAdjustingPopupMenu.hpp" using namespace RichText; -TextBoxEditTool::TextBoxEditTool(DrawingProgram& initDrawP): - DrawingProgramEditToolBase(initDrawP) +TextBoxEditTool::TextBoxEditTool(DrawingProgram& initDrawP, CanvasComponentContainer::ObjInfo* initComp): + DrawingProgramEditToolBase(initDrawP, initComp) {} -void TextBoxEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) { +void TextBoxEditTool::commit_update_func() { + comp->obj->commit_update(drawP); +} + +void TextBoxEditTool::commit_update_and_layout_func() { + comp->obj->commit_update(drawP); + drawP.world.main.g.gui.set_to_layout(); +} + +void TextBoxEditTool::edit_gui() { using namespace GUIStuff; using namespace ElementHelpers; auto& a = static_cast(comp->obj->get_comp()); Toolbar& t = drawP.world.main.toolbar; auto& gui = drawP.world.main.g.gui; - auto& currentMods = *currentModsPtr; gui.new_id("edit tool text", [&] { text_label_centered(gui, "Edit Text"); - left_to_right_line_layout(gui, [&] { - text_label(gui, "Font"); - //if(gui.font_picker("font picker", &newFontName)) { - // currentMods[TextStyleModifier::ModifierType::FONT_FAMILIES] = std::make_shared(std::vector{SkString{newFontName.c_str(), newFontName.size()}}); - // add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::FONT_FAMILIES]);}); - //} - }); + //left_to_right_line_layout(gui, [&] { + // text_label(gui, "Font"); + // if(gui.font_picker("font picker", &newFontName)) { + // currentMods[TextStyleModifier::ModifierType::FONT_FAMILIES] = std::make_shared(std::vector{SkString{newFontName.c_str(), newFontName.size()}}); + // add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::FONT_FAMILIES]);}); + // } + //}); - //left_to_right_line_centered_layout(gui, [&] { - // if(svg_icon_button("Bold button", "data/icons/RemixIcon/bold.svg", newIsBold)) { - // newIsBold = !newIsBold; - // currentMods[TextStyleModifier::ModifierType::WEIGHT] = std::make_shared(newIsBold ? SkFontStyle::Weight::kBold_Weight : SkFontStyle::Weight::kNormal_Weight); - // add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::WEIGHT]);}); - // } + left_to_right_line_centered_layout(gui, [&] { + svg_icon_button(gui, "Bold button", "data/icons/RemixIcon/bold.svg", { + .isSelected = newIsBold, + .onClick = [&] { + newIsBold = !newIsBold; + currentMods[TextStyleModifier::ModifierType::WEIGHT] = std::make_shared(newIsBold ? SkFontStyle::Weight::kBold_Weight : SkFontStyle::Weight::kNormal_Weight); + add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::WEIGHT]);}); + commit_update_func(); + } + }); - // if(gui.svg_icon_button("Italic button", "data/icons/RemixIcon/italic.svg", newIsItalic)) { - // newIsItalic = !newIsItalic; - // currentMods[TextStyleModifier::ModifierType::SLANT] = std::make_shared(newIsItalic ? SkFontStyle::Slant::kItalic_Slant : SkFontStyle::Slant::kUpright_Slant); - // add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::SLANT]);}); - // } + svg_icon_button(gui, "Italic button", "data/icons/RemixIcon/italic.svg", { + .isSelected = newIsItalic, + .onClick = [&] { + newIsItalic = !newIsItalic; + currentMods[TextStyleModifier::ModifierType::SLANT] = std::make_shared(newIsItalic ? SkFontStyle::Slant::kItalic_Slant : SkFontStyle::Slant::kUpright_Slant); + add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::SLANT]);}); + commit_update_func(); + } + }); - // bool decorationEdited = false; - // if(gui.svg_icon_button("Underline button", "data/icons/RemixIcon/underline.svg", newIsUnderlined)) { - // newIsUnderlined = !newIsUnderlined; - // decorationEdited = true; - // } - // if(gui.svg_icon_button("Strikethrough button", "data/icons/RemixIcon/strikethrough.svg", newIsLinethrough)) { - // newIsLinethrough = !newIsLinethrough; - // decorationEdited = true; - // } - // if(gui.svg_icon_button("Overline button", "data/icons/RemixIcon/overline.svg", newIsOverline)) { - // newIsOverline = !newIsOverline; - // decorationEdited = true; - // } - // if(decorationEdited) { - // currentMods[TextStyleModifier::ModifierType::DECORATION] = std::make_shared(get_new_decoration_value()); - // add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::DECORATION]);}); - // } - //}); + auto decorationChange = [&] { + currentMods[TextStyleModifier::ModifierType::DECORATION] = std::make_shared(get_new_decoration_value()); + add_undo_if_selecting_area(a, [&]() {a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::DECORATION]);}); + commit_update_func(); + }; - //gui.left_to_right_line_centered_layout([&]() { - // if(gui.svg_icon_button("Align left button", "data/icons/RemixIcon/align-left.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kLeft)) - // add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kLeft);}); - // if(gui.svg_icon_button("Align center button", "data/icons/RemixIcon/align-center.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kCenter)) - // add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kCenter);}); - // if(gui.svg_icon_button("Align right button", "data/icons/RemixIcon/align-right.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kRight)) - // add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kRight);}); - // if(gui.svg_icon_button("Align justify button", "data/icons/RemixIcon/align-justify.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kJustify)) - // add_undo([&](){a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kJustify);}); - // if(gui.svg_icon_button("Text direction left", "data/icons/RemixIcon/text-direction-l.svg", currentPStyle.textDirection == skia::textlayout::TextDirection::kLtr)) - // add_undo([&](){a.textBox->set_text_direction_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextDirection::kLtr);}); - // if(gui.svg_icon_button("Text direction right", "data/icons/RemixIcon/text-direction-r.svg", currentPStyle.textDirection == skia::textlayout::TextDirection::kRtl)) - // add_undo([&](){a.textBox->set_text_direction_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextDirection::kRtl);}); - //}); + svg_icon_button(gui, "Underline button", "data/icons/RemixIcon/underline.svg", { + .isSelected = newIsUnderlined, + .onClick = [&, decorationChange] { + newIsUnderlined = !newIsUnderlined; + decorationChange(); + } + }); - //if(gui.slider_scalar_field("Font Size Slider", "Font Size", &newFontSize, 3, 100)) { - // hold_undo_data("Font Size", a); - // currentMods[TextStyleModifier::ModifierType::SIZE] = std::make_shared(newFontSize); - // a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::SIZE]); - //} - //else - // release_undo_data("Font Size"); + svg_icon_button(gui, "Strikethrough button", "data/icons/RemixIcon/strikethrough.svg", { + .isSelected = newIsLinethrough, + .onClick = [&, decorationChange] { + newIsLinethrough = !newIsLinethrough; + decorationChange(); + } + }); + + svg_icon_button(gui, "Overline button", "data/icons/RemixIcon/overline.svg", { + .isSelected = newIsOverline, + .onClick = [&, decorationChange] { + newIsOverline = !newIsOverline; + decorationChange(); + } + }); + }); + + left_to_right_line_centered_layout(gui, [&]() { + auto paragraph_operation_button = [&](const char* id, const char* svgPath, bool isSelected, const std::function& func) { + svg_icon_button(gui, id, svgPath, { + .isSelected = isSelected, + .onClick = [&, func] { + add_undo(func); + commit_update_func(); + } + }); + }; + + paragraph_operation_button("Align left button", "data/icons/RemixIcon/align-left.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kLeft, [&] { + a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kLeft); + }); + paragraph_operation_button("Align center button", "data/icons/RemixIcon/align-center.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kCenter, [&] { + a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kCenter); + }); + paragraph_operation_button("Align right button", "data/icons/RemixIcon/align-right.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kRight, [&] { + a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kRight); + }); + paragraph_operation_button("Align justify button", "data/icons/RemixIcon/align-justify.svg", currentPStyle.textAlignment == skia::textlayout::TextAlign::kJustify, [&] { + a.textBox->set_text_alignment_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextAlign::kJustify); + }); + paragraph_operation_button("Text direction left button", "data/icons/RemixIcon/text-direction-l.svg", currentPStyle.textDirection == skia::textlayout::TextDirection::kLtr, [&] { + a.textBox->set_text_direction_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextDirection::kLtr); + }); + paragraph_operation_button("Text direction right button", "data/icons/RemixIcon/text-direction-r.svg", currentPStyle.textDirection == skia::textlayout::TextDirection::kRtl, [&] { + a.textBox->set_text_direction_between(a.cursor->selectionBeginPos.fParagraphIndex, a.cursor->selectionEndPos.fParagraphIndex, skia::textlayout::TextDirection::kRtl); + }); + }); + + slider_scalar_field(gui, "Font Size Slider", "Font Size", &newFontSize, 3, 100, TextBoxScalarOptions{ + .onEdit = [&] { + currentMods[TextStyleModifier::ModifierType::SIZE] = std::make_shared(newFontSize); + a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::SIZE]); + commit_update_func(); + }, + .onSelect = [&] { hold_undo_data("Font Size", a); }, + .onDeselect = [&] { release_undo_data("Font Size"); } + }); //// Text color //gui.left_to_right_line_layout([&]() { @@ -117,8 +165,6 @@ void TextBoxEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) { // a.textBox->set_text_style_modifier_between(a.cursor->selectionBeginPos, a.cursor->selectionEndPos, currentMods[TextStyleModifier::ModifierType::COLOR]); //} - - //// Highlight color //gui.left_to_right_line_layout([&]() { // if(gui.color_button_big("Highlight Color", &newHighlightColor, &newHighlightColor == t.colorRight)) { @@ -160,10 +206,37 @@ void TextBoxEditTool::edit_gui(CanvasComponentContainer::ObjInfo* comp) { //return oldInputChangedTextBox; } -void TextBoxEditTool::input_key_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::KeyCallbackArgs& key) { +void TextBoxEditTool::input_paste_callback(const CustomEvents::PasteEventData& paste) { + if(textboxID.has_value() && textboxID.value() == drawP.world.main.input.text.current_textbox_editing_id()) { + auto& a = static_cast(comp->obj->get_comp()); + if(userInput->input_paste_callback(paste)) { + commit_update_and_layout_func(); + set_styles_at_selection(a); + } + } } -void TextBoxEditTool::input_mouse_button_on_canvas_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::MouseButtonCallbackArgs& button, bool isDraggingPoint) { +void TextBoxEditTool::input_text_key_callback(const InputManager::KeyCallbackArgs& key) { + if(textboxID.has_value() && textboxID.value() == drawP.world.main.input.text.current_textbox_editing_id()) { + auto& a = static_cast(comp->obj->get_comp()); + auto changes = userInput->input_key_callback(drawP.world.main.input, key); + if(changes.textEdited || changes.cursorChanged) { + commit_update_and_layout_func(); + set_styles_at_selection(a); + } + } +} + +void TextBoxEditTool::input_text_callback(const InputManager::TextCallbackArgs& text) { + if(textboxID.has_value() && textboxID.value() == drawP.world.main.input.text.current_textbox_editing_id()) { + auto& a = static_cast(comp->obj->get_comp()); + userInput->add_text_to_textbox(text.str); + commit_update_and_layout_func(); + set_styles_at_selection(a); + } +} + +void TextBoxEditTool::input_mouse_button_on_canvas_callback(const InputManager::MouseButtonCallbackArgs& button, bool isDraggingPoint) { if(button.button == InputManager::MouseButton::LEFT && !isDraggingPoint) { auto& a = static_cast(comp->obj->get_comp()); @@ -175,11 +248,16 @@ void TextBoxEditTool::input_mouse_button_on_canvas_callback(CanvasComponentConta bool collidesWithBox = comp->obj->collides_with_cam_coords(drawP.world.drawData.cam.c, mousePointCollection); + auto oldCursor = *a.cursor; a.textBox->process_mouse_left_button(*a.cursor, a.get_mouse_pos(drawP), (button.down && button.clicks && collidesWithBox) ? button.clicks : 0, button.down, input.key(InputManager::KEY_GENERIC_LSHIFT).held); + if(oldCursor != *a.cursor) { + set_styles_at_selection(a); + commit_update_and_layout_func(); + } } } -void TextBoxEditTool::input_mouse_motion_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::MouseMotionCallbackArgs& motion, bool isDraggingPoint) { +void TextBoxEditTool::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion, bool isDraggingPoint) { auto& a = static_cast(comp->obj->get_comp()); a.init_text_box(drawP); @@ -192,11 +270,16 @@ void TextBoxEditTool::input_mouse_motion_callback(CanvasComponentContainer::ObjI InputManager& input = drawP.world.main.input; + auto oldCursor = *a.cursor; a.textBox->process_mouse_left_button(*a.cursor, a.get_mouse_pos(drawP), 0, drawP.controls.leftClickHeld, input.key(InputManager::KEY_GENERIC_LSHIFT).held); + if(oldCursor != *a.cursor) { + set_styles_at_selection(a); + commit_update_and_layout_func(); + } } } -void TextBoxEditTool::right_click_popup_gui(CanvasComponentContainer::ObjInfo* comp, Vector2f popupPos) { +void TextBoxEditTool::right_click_popup_gui(Vector2f popupPos) { using namespace GUIStuff; using namespace ElementHelpers; @@ -241,8 +324,7 @@ void TextBoxEditTool::release_undo_data(const std::string& undoName) { auto it = undoHeldData.find(undoName); if(it != undoHeldData.end()) { std::pair& undoData = it->second; - InputManager& input = drawP.world.main.input; - //input.text.add_textbox_undo(undoData.first, undoData.second); + userInput->add_textbox_undo(undoData.first, undoData.second); undoHeldData.erase(it); } } @@ -250,15 +332,12 @@ void TextBoxEditTool::release_undo_data(const std::string& undoName) { void TextBoxEditTool::add_undo_if_selecting_area(TextBoxCanvasComponent& a, const std::function& func) { if(a.cursor->selectionBeginPos == a.cursor->selectionEndPos) func(); - else { - InputManager& input = drawP.world.main.input; - //input.text.do_textbox_operation_with_undo(func); - } + else + userInput->do_textbox_operation_with_undo(func); } void TextBoxEditTool::add_undo(const std::function& func) { - InputManager& input = drawP.world.main.input; - //input.text.do_textbox_operation_with_undo(func); + userInput->do_textbox_operation_with_undo(func); } uint8_t TextBoxEditTool::get_new_decoration_value() { @@ -295,11 +374,12 @@ void TextBoxEditTool::set_styles_at_selection(TextBoxCanvasComponent& a) { currentPStyle = a.textBox->get_paragraph_style_data_at(start.fParagraphIndex); } -void TextBoxEditTool::commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { +void TextBoxEditTool::commit_edit_updates(std::any& prevData) { auto& a = static_cast(comp->obj->get_comp()); a.d.editing = false; comp->obj->commit_update(drawP); - //drawP.world.main.input.remove_rich_text_box_input(a.textBox); + if(textboxID.has_value()) + drawP.world.main.input.remove_text_box(textboxID.value()); } TextBoxEditTool::TextBoxEditToolAllData TextBoxEditTool::get_all_data(const TextBoxCanvasComponent& a) { @@ -309,7 +389,7 @@ TextBoxEditTool::TextBoxEditToolAllData TextBoxEditTool::get_all_data(const Text }; } -void TextBoxEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::ObjInfo* comp, std::any& prevData) { +void TextBoxEditTool::edit_start(EditTool& editTool, std::any& prevData) { auto& a = static_cast(comp->obj->get_comp()); auto& cur = a.cursor; auto& textbox = a.textBox; @@ -321,7 +401,6 @@ void TextBoxEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::O textbox->process_mouse_left_button(*cur, textSelectPos, 1, false, false); prevData = get_all_data(a); a.d.editing = true; - a.textBox->inputChangedTextBox = true; set_styles_at_selection(a); @@ -330,15 +409,16 @@ void TextBoxEditTool::edit_start(EditTool& editTool, CanvasComponentContainer::O comp->obj->commit_update(drawP); - //drawP.world.main.input.set_rich_text_box_input_back(a.textBox, a.cursor, true, nullptr, { - // .inputType = SDL_TextInputType::SDL_TEXTINPUT_TYPE_TEXT, - // .capitalization = SDL_Capitalization::SDL_CAPITALIZE_NONE, - // .autocorrect = true, - // .multiline = true, - // .androidInputType = InputManager::AndroidInputType::ANDROIDTEXT_TYPE_CLASS_TEXT - //}, currentModsPtr); + userInput = std::make_unique(textbox, cur, currentModsPtr); + textboxID = drawP.world.main.input.set_text_box_back(std::nullopt, { + .inputType = SDL_TextInputType::SDL_TEXTINPUT_TYPE_TEXT, + .capitalization = SDL_Capitalization::SDL_CAPITALIZE_NONE, + .autocorrect = true, + .multiline = true, + .androidInputType = InputManager::AndroidInputType::ANDROIDTEXT_TYPE_CLASS_TEXT + }); } -bool TextBoxEditTool::edit_update(CanvasComponentContainer::ObjInfo* comp) { +bool TextBoxEditTool::edit_update() { return true; } diff --git a/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.hpp b/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.hpp index 57d9a77..dc712c8 100644 --- a/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.hpp +++ b/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.hpp @@ -3,23 +3,29 @@ #include "DrawingProgramEditToolBase.hpp" #include #include +#include "../../../RichTextUserInput.hpp" class DrawingProgram; class TextBoxEditTool : public DrawingProgramEditToolBase { public: - TextBoxEditTool(DrawingProgram& initDrawP); + TextBoxEditTool(DrawingProgram& initDrawP, CanvasComponentContainer::ObjInfo* initComp); - virtual void edit_start(EditTool& editTool,CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override; - virtual void commit_edit_updates(CanvasComponentContainer::ObjInfo* comp, std::any& prevData) override; - virtual bool edit_update(CanvasComponentContainer::ObjInfo* comp) override; - virtual void edit_gui(CanvasComponentContainer::ObjInfo* comp) override; - virtual void right_click_popup_gui(CanvasComponentContainer::ObjInfo* comp, Vector2f popupPos) override; + virtual void edit_start(EditTool& editTool, std::any& prevData) override; + virtual void commit_edit_updates(std::any& prevData) override; + virtual bool edit_update() override; + virtual void edit_gui() override; + virtual void right_click_popup_gui(Vector2f popupPos) override; - virtual void input_key_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::KeyCallbackArgs& key) override; - virtual void input_mouse_button_on_canvas_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::MouseButtonCallbackArgs& button, bool isDraggingPoint) override; - virtual void input_mouse_motion_callback(CanvasComponentContainer::ObjInfo* comp, const InputManager::MouseMotionCallbackArgs& motion, bool isDraggingPoint) override; + virtual void input_paste_callback(const CustomEvents::PasteEventData& paste) override; + virtual void input_text_key_callback(const InputManager::KeyCallbackArgs& key) override; + virtual void input_text_callback(const InputManager::TextCallbackArgs& text) override; + virtual void input_mouse_button_on_canvas_callback(const InputManager::MouseButtonCallbackArgs& button, bool isDraggingPoint) override; + virtual void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion, bool isDraggingPoint) override; private: + std::unique_ptr userInput; + std::optional textboxID; + struct TextBoxEditToolAllData { TextBoxCanvasComponent::Data textboxData; RichText::TextData richText; @@ -44,6 +50,9 @@ class TextBoxEditTool : public DrawingProgramEditToolBase { void hold_undo_data(const std::string& undoName, TextBoxCanvasComponent& a); void release_undo_data(const std::string& undoName); + void commit_update_func(); + void commit_update_and_layout_func(); + std::unordered_map> undoHeldData; std::shared_ptr currentModsPtr = std::make_shared(); diff --git a/src/GUIHolder.cpp b/src/GUIHolder.cpp index 35a485b..a4af0af 100644 --- a/src/GUIHolder.cpp +++ b/src/GUIHolder.cpp @@ -119,12 +119,16 @@ void GUIHolder::draw(SkCanvas* canvas, bool skiaAA) { canvas->restore(); } +void GUIHolder::input_paste_callback(const CustomEvents::PasteEventData& paste) { + gui.input_paste_callback(paste); +} + void GUIHolder::input_text_key_callback(const InputManager::KeyCallbackArgs& key) { gui.input_text_key_callback(key); } -void GUIHolder::input_text_callback(const std::string& str) { - gui.input_text_callback(str); +void GUIHolder::input_text_callback(const InputManager::TextCallbackArgs& text) { + gui.input_text_callback(text); } void GUIHolder::input_key_callback(const InputManager::KeyCallbackArgs& key) { diff --git a/src/GUIHolder.hpp b/src/GUIHolder.hpp index 69b33ed..cf50666 100644 --- a/src/GUIHolder.hpp +++ b/src/GUIHolder.hpp @@ -1,5 +1,6 @@ #pragma once +#include "CustomEvents.hpp" #include "GUIStuff/GUIManager.hpp" class MainProgram; @@ -18,8 +19,9 @@ class GUIHolder { void update(); void draw(SkCanvas* canvas, bool skiaAA); + void input_paste_callback(const CustomEvents::PasteEventData& paste); void input_text_key_callback(const InputManager::KeyCallbackArgs& key); - void input_text_callback(const std::string& str); + void input_text_callback(const InputManager::TextCallbackArgs& text); void input_key_callback(const InputManager::KeyCallbackArgs& key); void input_text_key_callback(); void input_text_input_callback(); diff --git a/src/GUIStuff/ElementHelpers/NumberSliderHelpers.hpp b/src/GUIStuff/ElementHelpers/NumberSliderHelpers.hpp index bb40e44..bd5ec84 100644 --- a/src/GUIStuff/ElementHelpers/NumberSliderHelpers.hpp +++ b/src/GUIStuff/ElementHelpers/NumberSliderHelpers.hpp @@ -14,7 +14,11 @@ namespace GUIStuff { namespace ElementHelpers { text_label(gui, name); input_scalar(gui, "textbox", val, min, max, options); }); - gui.element>("slider", val, min, max, options.onEdit); + gui.element>("slider", val, min, max, NumberSliderData{ + .onChange = options.onEdit, + .onHold = options.onSelect, + .onRelease = options.onDeselect + }); }); } }} diff --git a/src/GUIStuff/ElementHelpers/TextBoxHelpers.hpp b/src/GUIStuff/ElementHelpers/TextBoxHelpers.hpp index cf1cf08..c322c3b 100644 --- a/src/GUIStuff/ElementHelpers/TextBoxHelpers.hpp +++ b/src/GUIStuff/ElementHelpers/TextBoxHelpers.hpp @@ -12,6 +12,8 @@ template TextBoxData textbox_options_to_data(cons toRet.onEnter = options.onEnter; toRet.onEdit = options.onEdit; toRet.immutable = options.immutable; + toRet.onSelect = options.onSelect; + toRet.onDeselect = options.onDeselect; return toRet; } @@ -20,6 +22,8 @@ struct TextBoxOptions { bool immutable = false; std::function onEnter; std::function onEdit; + std::function onSelect; + std::function onDeselect; }; struct TextBoxScalarOptions { @@ -28,6 +32,8 @@ struct TextBoxScalarOptions { bool immutable = false; std::function onEnter; std::function onEdit; + std::function onSelect; + std::function onDeselect; }; struct TextBoxPathOptions { @@ -36,6 +42,8 @@ struct TextBoxPathOptions { bool immutable = false; std::function onEnter; std::function onEdit; + std::function onSelect; + std::function onDeselect; }; struct TextBoxHexColorOptions { @@ -44,6 +52,8 @@ struct TextBoxHexColorOptions { bool immutable = false; std::function onEnter; std::function onEdit; + std::function onSelect; + std::function onDeselect; }; void input_color_component_255(GUIManager& gui, const char* id, float* val, const TextBoxOptions& options = {}); diff --git a/src/GUIStuff/Elements/Element.cpp b/src/GUIStuff/Elements/Element.cpp index 9bdbeff..6bd2bb6 100644 --- a/src/GUIStuff/Elements/Element.cpp +++ b/src/GUIStuff/Elements/Element.cpp @@ -6,8 +6,9 @@ namespace GUIStuff { void Element::tick_update() {} + void Element::input_paste_callback(const CustomEvents::PasteEventData& paste) { } void Element::input_text_key_callback(const InputManager::KeyCallbackArgs& key) { } - void Element::input_text_callback(const std::string& str) { } + void Element::input_text_callback(const InputManager::TextCallbackArgs& text) { } void Element::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) { } void Element::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) { } void Element::input_mouse_wheel_callback(const InputManager::MouseWheelCallbackArgs& wheel) { } diff --git a/src/GUIStuff/Elements/Element.hpp b/src/GUIStuff/Elements/Element.hpp index 311b63b..cbf49ad 100644 --- a/src/GUIStuff/Elements/Element.hpp +++ b/src/GUIStuff/Elements/Element.hpp @@ -24,9 +24,9 @@ namespace GUIStuff { virtual void tick_update(); - // Return true when mouse obstructs what's behind it + virtual void input_paste_callback(const CustomEvents::PasteEventData& paste); virtual void input_text_key_callback(const InputManager::KeyCallbackArgs& key); - virtual void input_text_callback(const std::string& str); + virtual void input_text_callback(const InputManager::TextCallbackArgs& text); virtual void input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button); virtual void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion); virtual void input_mouse_wheel_callback(const InputManager::MouseWheelCallbackArgs& wheel); diff --git a/src/GUIStuff/Elements/NumberSlider.hpp b/src/GUIStuff/Elements/NumberSlider.hpp index c3cef08..1f58c0e 100644 --- a/src/GUIStuff/Elements/NumberSlider.hpp +++ b/src/GUIStuff/Elements/NumberSlider.hpp @@ -4,16 +4,23 @@ namespace GUIStuff { +struct NumberSliderData { + std::function onChange; + std::function onHold; + std::function onRelease; +}; + template class NumberSlider : public Element { public: NumberSlider(GUIManager& gui): Element(gui) {} - void layout(const Clay_ElementId& id, T* data, T minData, T maxData, const std::function& onChange) { + + void layout(const Clay_ElementId& id, T* data, T minData, T maxData, const NumberSliderData& config) { this->data = data; this->minData = minData; this->maxData = maxData; - this->onChange = onChange; + this->config = config; CLAY(id, { .layout = { @@ -74,22 +81,29 @@ template class NumberSlider : public Element { canvas->restore(); } virtual void input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) override { + bool oldIsHeld = isHeld; isHeld = mouseHovering && button.button == InputManager::MouseButton::LEFT && button.down; - if(isHeld && boundingBox.has_value()) - update_slider_pos(button.pos); + if(oldIsHeld && !isHeld) { + gui.set_post_callback_func([&] { + if(config.onRelease) config.onRelease(); + }); + } + else if(isHeld && boundingBox.has_value()) + update_slider_pos(button.pos, true); } virtual void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) override { if(isHeld && boundingBox.has_value()) - update_slider_pos(motion.pos); + update_slider_pos(motion.pos, false); } private: - void update_slider_pos(const Vector2f& p) { - gui.set_post_callback_func([&, p] { + void update_slider_pos(const Vector2f& p, bool justHeld) { + gui.set_post_callback_func([&, p, justHeld] { float fracPosOnSlider = (p.x() - boundingBox.value().min.x()) / boundingBox.value().width(); *data = static_cast(std::clamp(std::lerp(minData, maxData, fracPosOnSlider), minData, maxData)); // Clamp as double then cast so that unsigned types dont wrap on clamp - if(onChange) onChange(); + if(justHeld && config.onHold) config.onHold(); + if(config.onChange) config.onChange(); }); } @@ -97,7 +111,7 @@ template class NumberSlider : public Element { T* data = nullptr; T minData = 0.0; T maxData = 1.0; - std::function onChange; + NumberSliderData config; float hoverAnimation = 0.0; float holdAnimation = 0.0; diff --git a/src/GUIStuff/Elements/TextBox.decl.hpp b/src/GUIStuff/Elements/TextBox.decl.hpp index 03c125b..69d4165 100644 --- a/src/GUIStuff/Elements/TextBox.decl.hpp +++ b/src/GUIStuff/Elements/TextBox.decl.hpp @@ -19,13 +19,15 @@ template struct TextBoxData { InputManager::TextInputProperties textInputProps; std::function onEdit; std::function onEnter; + std::function onSelect; + std::function onDeselect; }; struct TextEditData { - TextEditData(unsigned initTextboxInputID, const std::shared_ptr& initTextBox, const std::shared_ptr& initCursor, const std::function& onTextEdit): + TextEditData(unsigned initTextboxInputID, const std::shared_ptr& initTextBox, const std::shared_ptr& initCursor): textboxInputID(initTextboxInputID), - userInput(initTextBox, initCursor, nullptr, onTextEdit) + userInput(initTextBox, initCursor, nullptr) {} unsigned textboxInputID; RichTextUserInput userInput; @@ -37,12 +39,14 @@ template class TextBox : public Element { void layout(const Clay_ElementId& id, const TextBoxData& userInfo); virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override; + virtual void input_paste_callback(const CustomEvents::PasteEventData& paste) override; virtual void input_text_key_callback(const InputManager::KeyCallbackArgs& key) override; - virtual void input_text_callback(const std::string& str) override; + virtual void input_text_callback(const InputManager::TextCallbackArgs& text) override; virtual void input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) override; virtual void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) override; ~TextBox(); private: + void after_text_input_callback(); void init_textbox(UpdateInputData& io); void reset_textbox_text(); bool update_data(); diff --git a/src/GUIStuff/Elements/TextBox.impl.hpp b/src/GUIStuff/Elements/TextBox.impl.hpp index 5de85c2..a79b1f9 100644 --- a/src/GUIStuff/Elements/TextBox.impl.hpp +++ b/src/GUIStuff/Elements/TextBox.impl.hpp @@ -65,6 +65,11 @@ template bool TextBox::is_selected() const { return edit.has_value(); } +template void TextBox::input_paste_callback(const CustomEvents::PasteEventData& paste) { + if(is_selected() && edit.value().userInput.input_paste_callback(paste)) + after_text_input_callback(); +} + template void TextBox::input_text_key_callback(const InputManager::KeyCallbackArgs& key) { if(is_selected()) { if(key.key == InputManager::KEY_GENERIC_ENTER && key.down) { @@ -75,14 +80,27 @@ template void TextBox::input_text_key_callback(const InputManage reset_textbox_text(); }); } - else - edit.value().userInput.input_key_callback(*gui.io.input, key); + else { + if(edit.value().userInput.input_key_callback(*gui.io.input, key).textEdited) + after_text_input_callback(); + } } } -template void TextBox::input_text_callback(const std::string& str) { - if(is_selected()) - edit.value().userInput.add_text_to_textbox(str); +template void TextBox::after_text_input_callback() { + if(userInfo.immutable) + cur->pos = cur->selectionBeginPos = cur->selectionEndPos = textbox->insert({0, 0}, userInfo.toStr(*userInfo.data)); + else { + if(update_data() && userInfo.onEdit) + gui.set_post_callback_func_high_priority(userInfo.onEdit); + } +} + +template void TextBox::input_text_callback(const InputManager::TextCallbackArgs& text) { + if(is_selected()) { + edit.value().userInput.add_text_to_textbox(text.str); + after_text_input_callback(); + } } template void TextBox::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) { @@ -91,22 +109,23 @@ template void TextBox::input_mouse_button_callback(const InputMa if(button.button == InputManager::MouseButton::LEFT && boundingBox.has_value()) { if(button.down) { if(mouseHovering) { - SCollision::AABB rect = {(boundingBox.value().min + io.windowPos) * io.guiScaleMultiplier, (boundingBox.value().max + io.windowPos) * io.guiScaleMultiplier}; - unsigned id = gui.io.input->set_text_box_front(rect, userInfo.textInputProps); + if(!is_selected()) { + SCollision::AABB rect = {(boundingBox.value().min + io.windowPos) * io.guiScaleMultiplier, (boundingBox.value().max + io.windowPos) * io.guiScaleMultiplier}; + unsigned id = gui.io.input->set_text_box_front(rect, userInfo.textInputProps); + edit = TextEditData(id, textbox, cur); + gui.set_post_callback_func_high_priority([&] { + if(userInfo.onSelect) userInfo.onSelect(); + }); + } textbox->process_mouse_left_button(*cur, button.pos - boundingBox.value().min, button.clicks, true, gui.io.input->key(InputManager::KEY_GENERIC_LSHIFT).held); - edit = TextEditData(id, textbox, cur, [&] { - if(userInfo.immutable) - cur->pos = cur->selectionBeginPos = cur->selectionEndPos = textbox->insert({0, 0}, userInfo.toStr(*userInfo.data)); - else { - if(update_data() && userInfo.onEdit) - gui.set_post_callback_func_high_priority(userInfo.onEdit); - } - }); } else if(is_selected()) { gui.io.input->remove_text_box(edit.value().textboxInputID); - if(update_data()) - gui.set_post_callback_func_high_priority(userInfo.onEdit); + gui.set_post_callback_func_high_priority([&] { + if(update_data()) + if(userInfo.onEdit) userInfo.onEdit(); + if(userInfo.onDeselect) userInfo.onDeselect(); + }); reset_textbox_text(); edit = std::nullopt; } diff --git a/src/GUIStuff/GUIManager.cpp b/src/GUIStuff/GUIManager.cpp index 4daa774..a4c0bfb 100644 --- a/src/GUIStuff/GUIManager.cpp +++ b/src/GUIStuff/GUIManager.cpp @@ -344,6 +344,13 @@ bool GUIManager::cursor_obstructed() const { return cursorObstructed; } +void GUIManager::input_paste_callback(const CustomEvents::PasteEventData& paste) { + for(ElementContainer* e : orderedElements) + e->elem->input_paste_callback(paste); + run_post_callback_func(); + layout_if_necessary(); +} + void GUIManager::input_text_key_callback(const InputManager::KeyCallbackArgs& key) { for(ElementContainer* e : orderedElements) e->elem->input_text_key_callback(key); @@ -351,9 +358,9 @@ void GUIManager::input_text_key_callback(const InputManager::KeyCallbackArgs& ke layout_if_necessary(); } -void GUIManager::input_text_callback(const std::string& str) { +void GUIManager::input_text_callback(const InputManager::TextCallbackArgs& text) { for(ElementContainer* e : orderedElements) - e->elem->input_text_callback(str); + e->elem->input_text_callback(text); run_post_callback_func(); layout_if_necessary(); } diff --git a/src/GUIStuff/GUIManager.hpp b/src/GUIStuff/GUIManager.hpp index 4631f9a..e1e830d 100644 --- a/src/GUIStuff/GUIManager.hpp +++ b/src/GUIStuff/GUIManager.hpp @@ -85,8 +85,9 @@ class GUIManager { DefaultStringArena strArena; + void input_paste_callback(const CustomEvents::PasteEventData& paste); void input_text_key_callback(const InputManager::KeyCallbackArgs& key); - void input_text_callback(const std::string& str); + void input_text_callback(const InputManager::TextCallbackArgs& text); void input_key_callback(const InputManager::KeyCallbackArgs& key); void input_mouse_button_callback(InputManager::MouseButtonCallbackArgs button); void input_mouse_motion_callback(InputManager::MouseMotionCallbackArgs motion); diff --git a/src/InputManager.cpp b/src/InputManager.cpp index b63407e..c8294c7 100644 --- a/src/InputManager.cpp +++ b/src/InputManager.cpp @@ -1,4 +1,5 @@ #include "InputManager.hpp" +#include "CustomEvents.hpp" #include #include @@ -11,6 +12,7 @@ #include + #ifdef _WIN32 #include #include @@ -126,6 +128,12 @@ bool InputManager::Text::is_accepting_input() { return !textBoxes.empty(); } +std::optional InputManager::Text::current_textbox_editing_id() { + if(textBoxes.empty()) + return std::nullopt; + return textBoxes.front().id; +} + void InputManager::Text::update_accepting_input(SDL_Window* window) { if(!textBoxes.empty()) { auto& textbox = textBoxes.front(); @@ -354,8 +362,13 @@ uint32_t InputManager::make_generic_key_mod(SDL_Keymod m) { return toRet; } +void InputManager::backend_paste_event() { + main.input_paste_callback(CustomEvents::get_paste_event_data()); + CustomEvents::pop_paste_event_data(); +} + void InputManager::backend_input_text_event(const std::string& str) { - main.input_text_callback(str); + main.input_text_callback(TextCallbackArgs{ .str = str }); } void InputManager::backend_drop_file_event(const SDL_DropEvent& e) { @@ -901,27 +914,35 @@ void InputManager::backend_key_down_update(const SDL_KeyboardEvent& e) { set_key_down(e, f->second); } -void InputManager::call_text_paste(const std::function& pasteCallbackFunc) { +void InputManager::call_paste(CustomEvents::PasteEventDataType type, const std::optional& pastePosition) { // Workaround for not being able to copy richtext to system clipboard, this should at least work within the application itself - pasteCallback = pasteCallbackFunc; #ifdef __EMSCRIPTEN__ - emscripten_browser_clipboard::paste_async([](std::string&& pasteData, void* callbackData){ - InputManager* inMan = (InputManager*)callbackData; - std::string pData = pasteData; - inMan->process_text_paste(pData); - }, this); + if(type == PasteDataType::TEXT) { + emscripten_browser_clipboard::paste_async([](std::string&& pasteData, void* callbackData){ + InputManager* inMan = (InputManager*)callbackData; + std::string pData = pasteData; + inMan->process_text_paste(pData); + }, this); + } + else { + } #else - process_text_paste(get_clipboard_str_SDL()); + switch(type) { + case CustomEvents::PasteEventDataType::TEXT: + process_text_paste(get_clipboard_str_SDL()); + break; + case CustomEvents::PasteEventDataType::IMAGE: + break; + } #endif } void InputManager::process_text_paste(const std::string& pasteStr) { - if(lastCopiedRichText.has_value() && lastCopiedRichText.value().get_plain_text() == remove_carriage_returns_from_str(pasteStr)) { - pasteCallback({ - .text = pasteStr, - .richText = lastCopiedRichText - }); - } + CustomEvents::emit_paste_event({ + .type = CustomEvents::PasteEventDataType::TEXT, + .data = pasteStr, + .richText = lastCopiedRichText.has_value() && lastCopiedRichText.value().get_plain_text() == remove_carriage_returns_from_str(pasteStr) ? lastCopiedRichText : std::nullopt + }); } bool InputManager::ctrl_or_meta_held() { diff --git a/src/InputManager.hpp b/src/InputManager.hpp index 8546462..a46ac23 100644 --- a/src/InputManager.hpp +++ b/src/InputManager.hpp @@ -20,6 +20,8 @@ #include +#include "CustomEvents.hpp" + using namespace Eigen; class MainProgram; @@ -155,6 +157,7 @@ struct InputManager { struct Text { bool is_accepting_input(); + std::optional current_textbox_editing_id(); private: struct TextBoxInfo { @@ -253,6 +256,7 @@ struct InputManager { void touch_finger_do_mouse_up(const SDL_TouchFingerEvent& f); void touch_finger_do_mouse_motion(const SDL_TouchFingerEvent& f); + void backend_paste_event(); void backend_input_text_event(const std::string& str); void backend_drop_file_event(const SDL_DropEvent& e); void backend_drop_text_event(const SDL_DropEvent& e); @@ -277,13 +281,9 @@ struct InputManager { std::string get_clipboard_str_SDL(); void get_clipboard_image_data_SDL(const std::function& callback); - struct TextPasteCallbackArgs { - std::string text; - std::optional richText; - }; - void call_text_paste(const std::function& pasteCallbackFunc); + void call_paste(CustomEvents::PasteEventDataType type, const std::optional& pastePosition = std::nullopt); void process_text_paste(const std::string& pasteStr); - std::function pasteCallback; + std::optional lastCopiedRichText; std::string key_assignment_to_str(const Vector2ui32& k) const; @@ -291,6 +291,10 @@ struct InputManager { const KeyData& key(KeyCode kCode); + struct TextCallbackArgs { + std::string str; + }; + struct KeyCallbackArgs { KeyCode key; bool down; diff --git a/src/MainProgram.cpp b/src/MainProgram.cpp index e590aa1..c3b8a2c 100755 --- a/src/MainProgram.cpp +++ b/src/MainProgram.cpp @@ -317,6 +317,12 @@ sk_sp MainProgram::create_native_surface(Vector2i resolution, bool is return nullptr; } +void MainProgram::input_paste_callback(const CustomEvents::PasteEventData& paste) { + g.input_paste_callback(paste); + if(world) + world->input_paste_callback(paste); +} + bool MainProgram::input_keybind_callback(const Vector2ui32& newKey) { if(keybindWaiting.has_value()) { unsigned v = keybindWaiting.value(); @@ -374,10 +380,14 @@ void MainProgram::input_key_callback(const InputManager::KeyCallbackArgs& key) { void MainProgram::input_text_key_callback(const InputManager::KeyCallbackArgs& key) { g.input_text_key_callback(key); + if(world) + world->input_text_key_callback(key); } -void MainProgram::input_text_callback(const std::string& str) { - g.input_text_callback(str); +void MainProgram::input_text_callback(const InputManager::TextCallbackArgs& text) { + g.input_text_callback(text); + if(world) + world->input_text_callback(text); } void MainProgram::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) { diff --git a/src/MainProgram.hpp b/src/MainProgram.hpp index fed2936..3c3c166 100644 --- a/src/MainProgram.hpp +++ b/src/MainProgram.hpp @@ -1,4 +1,5 @@ #pragma once +#include "CustomEvents.hpp" #include "DrawData.hpp" #include #include @@ -121,13 +122,13 @@ class MainProgram { GlobalConfig conf; std::optional keybindWaiting; + void input_paste_callback(const CustomEvents::PasteEventData& paste); bool input_keybind_callback(const Vector2ui32& newKey); - void input_drop_file_callback(const InputManager::DropCallbackArgs& drop); void input_drop_text_callback(const InputManager::DropCallbackArgs& drop); void input_key_callback(const InputManager::KeyCallbackArgs& key); void input_text_key_callback(const InputManager::KeyCallbackArgs& key); - void input_text_callback(const std::string& str); + void input_text_callback(const InputManager::TextCallbackArgs& text); void input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button); void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion); void input_mouse_wheel_callback(const InputManager::MouseWheelCallbackArgs& wheel); diff --git a/src/RichText/TextBox.cpp b/src/RichText/TextBox.cpp index b1f0267..636f418 100644 --- a/src/RichText/TextBox.cpp +++ b/src/RichText/TextBox.cpp @@ -169,9 +169,6 @@ void TextBox::process_key_input(Cursor& cur, InputKey in, bool ctrl, bool shift, if(in != InputKey::UP && in != InputKey::DOWN) cur.previousX = std::nullopt; - - if(onChange) onChange(); - inputChangedTextBox = true; } void TextBox::process_mouse_left_button(Cursor& cur, const Vector2f& pos, int clickCount, bool held, bool shift) { @@ -224,9 +221,6 @@ void TextBox::process_mouse_left_button(Cursor& cur, const Vector2f& pos, int cl } cur.previousX = std::nullopt; - - if((oldCursor != cur) && onChange) onChange(); - inputChangedTextBox |= (oldCursor != cur); } else cur.selectionEndPosBeforeHeld = std::nullopt; @@ -241,8 +235,6 @@ std::pair TextBox::process_cut(Cursor& cur) { if(cur.selectionBeginPos != cur.selectionEndPos) { cur.selectionEndPos = cur.selectionBeginPos = cur.pos = remove(cur.selectionBeginPos, cur.selectionEndPos); cur.previousX = std::nullopt; - if(onChange) onChange(); - inputChangedTextBox = true; } return toRet; } @@ -253,8 +245,6 @@ void TextBox::process_text_input(Cursor& cur, const std::string& in, const std:: cur.selectionEndPos = cur.selectionBeginPos = cur.pos = remove(cur.selectionBeginPos, cur.selectionEndPos); cur.selectionEndPos = cur.selectionBeginPos = cur.pos = insert(cur.pos, in, inputModMap); cur.previousX = std::nullopt; - if(onChange) onChange(); - inputChangedTextBox = true; } } @@ -264,8 +254,6 @@ void TextBox::process_rich_text_input(Cursor& cur, const TextData& richText) { cur.selectionEndPos = cur.selectionBeginPos = cur.pos = remove(cur.selectionBeginPos, cur.selectionEndPos); cur.selectionEndPos = cur.selectionBeginPos = cur.pos = insert_rich_text(cur.pos, richText); cur.previousX = std::nullopt; - if(onChange) onChange(); - inputChangedTextBox = true; } } @@ -461,8 +449,6 @@ TextPosition TextBox::insert_rich_text(TextPosition p, const TextData& richText) paragraphs[pIndex].pStyleData = richText.paragraphs[pIndex - p.fParagraphIndex].pStyleData; } - if(onChange) onChange(); - inputChangedTextBox = true; needsRebuild = true; return toRet; @@ -490,8 +476,6 @@ void TextBox::set_rich_text_data(const TextData& richText) { if(richText.paragraphs.empty()) paragraphs.emplace_back(); tStyleMods = richText.tStyleMods; - if(onChange) onChange(); - inputChangedTextBox = true; needsRebuild = true; } @@ -526,8 +510,6 @@ std::string TextBox::get_text_between(TextPosition p1, TextPosition p2) { void TextBox::set_initial_text_style(const skia::textlayout::TextStyle& tStyle) { if(!tStyle.equals(initialTStyle)) { initialTStyle = tStyle; - if(onChange) onChange(); - inputChangedTextBox = true; needsRebuild = true; } } @@ -598,8 +580,6 @@ void TextBox::set_text_style_modifier_between(TextPosition p1, TextPosition p2, insert_style_at_pos(start, modifier); insert_style_at_pos(end, lastModOfThisTypeBeforeEnd); // Even if the end is the literal end of the text (which wont be seen), the end style must still be placed at the end so that it can merge with and delete the start style when the styled text is erased remove_duplicate_text_style_mods(); - if(onChange) onChange(); - inputChangedTextBox = true; needsRebuild = true; } } @@ -614,8 +594,6 @@ void TextBox::set_text_alignment_between(size_t paragraphIndex1, size_t paragrap } } if(anythingChanged) { - if(onChange) onChange(); - inputChangedTextBox = true; needsRebuild = true; } } @@ -630,8 +608,6 @@ void TextBox::set_text_direction_between(size_t paragraphIndex1, size_t paragrap } } if(anythingChanged) { - if(onChange) onChange(); - inputChangedTextBox = true; needsRebuild = true; } } @@ -867,8 +843,6 @@ int TextBox::get_line_number_at_from_byte_text_pos(TextPosition pos) { void TextBox::set_width(float newWidth) { if(width != newWidth) { width = std::max(newWidth, 4.0f); - if(onChange) onChange(); - inputChangedTextBox = true; needsRebuild = true; } } @@ -885,8 +859,6 @@ void TextBox::set_allow_newlines(bool allow) { void TextBox::set_font_data(const std::shared_ptr& fD) { if(fontData != fD) { fontData = fD; - if(onChange) onChange(); - inputChangedTextBox = true; needsRebuild = true; } } @@ -1055,8 +1027,6 @@ TextPosition TextBox::insert(TextPosition pos, std::string_view textToInsert, co for(const auto& [modType, modifier] : inputModMap.value()) set_text_style_modifier_between(oldPos, pos, modifier); } - if(onChange) onChange(); - inputChangedTextBox = true; needsRebuild = true; } @@ -1105,8 +1075,6 @@ TextPosition TextBox::remove(TextPosition p1, TextPosition p2) { } remove_duplicate_text_style_mods(); - if(onChange) onChange(); - inputChangedTextBox = true; needsRebuild = true; return start; diff --git a/src/RichText/TextBox.hpp b/src/RichText/TextBox.hpp index a558116..86a9dcf 100644 --- a/src/RichText/TextBox.hpp +++ b/src/RichText/TextBox.hpp @@ -66,9 +66,6 @@ class TextBox { public: TextBox(); - bool inputChangedTextBox = false; - std::function onChange; - enum class Movement { NOWHERE, LEFT, diff --git a/src/RichTextUserInput.cpp b/src/RichTextUserInput.cpp index 2339329..559d76c 100644 --- a/src/RichTextUserInput.cpp +++ b/src/RichTextUserInput.cpp @@ -1,4 +1,5 @@ #include "RichTextUserInput.hpp" +#include "CustomEvents.hpp" template std::optional shared_ptr_to_opt(const std::shared_ptr o) { if(o) @@ -7,18 +8,29 @@ template std::optional shared_ptr_to_opt(const std::shared_ptr& initTextBox, const std::shared_ptr& initCursor, const std::shared_ptr& initModMap, const std::function& initOnTextEdit): +RichTextUserInput::RichTextUserInput(const std::shared_ptr& initTextBox, const std::shared_ptr& initCursor, const std::shared_ptr& initModMap): textBox(initTextBox), cursor(initCursor), - modMap(initModMap), - onTextEdit(initOnTextEdit) + modMap(initModMap) {} +bool RichTextUserInput::input_paste_callback(const CustomEvents::PasteEventData& paste) { + if(paste.type == CustomEvents::PasteEventDataType::TEXT) { + do_textbox_operation_with_undo([&]() { + if(paste.richText.has_value()) + textBox->process_rich_text_input(*cursor, paste.richText.value()); + else + textBox->process_text_input(*cursor, paste.data, shared_ptr_to_opt(modMap)); + }); + return true; + } + return false; +} + void RichTextUserInput::add_text_to_textbox(const std::string& inputText) { do_textbox_operation_with_undo([&]() { textBox->process_text_input(*cursor, inputText, shared_ptr_to_opt(modMap)); }); - onTextEdit(); } void RichTextUserInput::add_textbox_undo(const RichText::TextBox::Cursor& prevCursor, const RichText::TextData& prevRichText) { @@ -26,14 +38,12 @@ void RichTextUserInput::add_textbox_undo(const RichText::TextBox::Cursor& prevCu textBox->set_rich_text_data_for_undo_redo(prevRichText); cursor->selectionBeginPos = cursor->selectionEndPos = cursor->pos = std::max(prevCursor.selectionEndPos, prevCursor.selectionBeginPos); cursor->previousX = std::nullopt; - onTextEdit(); return true; }, [&, currentCursor = *cursor, currentRichText = textBox->get_rich_text_data()]() { textBox->set_rich_text_data_for_undo_redo(currentRichText); cursor->selectionBeginPos = cursor->selectionEndPos = cursor->pos = std::max(currentCursor.selectionEndPos, currentCursor.selectionBeginPos); cursor->previousX = std::nullopt; - onTextEdit(); return true; }}); } @@ -43,13 +53,16 @@ void RichTextUserInput::do_textbox_operation_with_undo(const std::function modMapOpt = shared_ptr_to_opt(modMap); + Changes toRet; + if(key.down) { + auto oldCursor = *cursor; + switch(key.key) { case InputManager::KEY_GENERIC_UP: textBox->process_key_input(*cursor, RichText::TextBox::InputKey::UP, input.ctrl_or_meta_held(), input.key(InputManager::KEY_GENERIC_LSHIFT).held, modMapOpt); @@ -67,11 +80,13 @@ void RichTextUserInput::input_key_callback(InputManager& input, const InputManag do_textbox_operation_with_undo([&] { textBox->process_key_input(*cursor, RichText::TextBox::InputKey::BACKSPACE, input.ctrl_or_meta_held(), input.key(InputManager::KEY_GENERIC_LSHIFT).held, modMapOpt); }); + toRet.textEdited = true; break; case InputManager::KEY_TEXT_DELETE: do_textbox_operation_with_undo([&] { textBox->process_key_input(*cursor, RichText::TextBox::InputKey::DEL, input.ctrl_or_meta_held(), input.key(InputManager::KEY_GENERIC_LSHIFT).held, modMapOpt); }); + toRet.textEdited = true; break; case InputManager::KEY_TEXT_HOME: textBox->process_key_input(*cursor, RichText::TextBox::InputKey::HOME, input.ctrl_or_meta_held(), input.key(InputManager::KEY_GENERIC_LSHIFT).held, modMapOpt); @@ -86,38 +101,38 @@ void RichTextUserInput::input_key_callback(InputManager& input, const InputManag do_textbox_operation_with_undo([&] { input.set_clipboard_plain_and_richtext_pair(textBox->process_cut(*cursor)); }); + toRet.textEdited = true; break; case InputManager::KEY_TEXT_PASTE: - do_textbox_operation_with_undo([&]() { - input.call_text_paste([textBox = textBox, cursor = cursor, modMapOpt] (const InputManager::TextPasteCallbackArgs& pasteArgs) { - if(pasteArgs.richText.has_value()) - textBox->process_rich_text_input(*cursor, pasteArgs.richText.value()); - else - textBox->process_text_input(*cursor, pasteArgs.text, modMapOpt); - }); - }); + input.call_paste(CustomEvents::PasteEventDataType::TEXT); break; case InputManager::KEY_TEXT_SELECTALL: textBox->process_key_input(*cursor, RichText::TextBox::InputKey::SELECT_ALL, input.ctrl_or_meta_held(), input.key(InputManager::KEY_GENERIC_LSHIFT).held, modMapOpt); break; case InputManager::KEY_TEXT_UNDO: textboxUndo.undo(); + toRet.textEdited = true; break; case InputManager::KEY_TEXT_REDO: textboxUndo.redo(); + toRet.textEdited = true; break; case InputManager::KEY_GENERIC_ENTER: do_textbox_operation_with_undo([&] { textBox->process_key_input(*cursor, RichText::TextBox::InputKey::ENTER, input.ctrl_or_meta_held(), input.key(InputManager::KEY_GENERIC_LSHIFT).held, modMapOpt); }); + toRet.textEdited = true; break; case InputManager::KEY_TEXT_TAB: do_textbox_operation_with_undo([&] { textBox->process_key_input(*cursor, RichText::TextBox::InputKey::TAB, input.ctrl_or_meta_held(), input.key(InputManager::KEY_GENERIC_LSHIFT).held, modMapOpt); }); + toRet.textEdited = true; break; default: - break; + return toRet; } + toRet.cursorChanged = oldCursor != *cursor; } + return toRet; } diff --git a/src/RichTextUserInput.hpp b/src/RichTextUserInput.hpp index 001ad5c..af78fd2 100644 --- a/src/RichTextUserInput.hpp +++ b/src/RichTextUserInput.hpp @@ -1,19 +1,24 @@ #pragma once +#include "CustomEvents.hpp" #include "RichText/TextBox.hpp" #include "UndoManager.hpp" #include "InputManager.hpp" class RichTextUserInput { public: - RichTextUserInput(const std::shared_ptr& initTextBox, const std::shared_ptr& initCursor, const std::shared_ptr& initModMap, const std::function& initOnTextEdit); - void input_key_callback(InputManager& input, const InputManager::KeyCallbackArgs& key); + RichTextUserInput(const std::shared_ptr& initTextBox, const std::shared_ptr& initCursor, const std::shared_ptr& initModMap); + struct Changes { + bool textEdited = false; + bool cursorChanged = false; + }; + Changes input_key_callback(InputManager& input, const InputManager::KeyCallbackArgs& key); + bool input_paste_callback(const CustomEvents::PasteEventData& paste); void add_text_to_textbox(const std::string& inputText); - private: void do_textbox_operation_with_undo(const std::function& func); void add_textbox_undo(const RichText::TextBox::Cursor& prevCursor, const RichText::TextData& prevRichText); + private: std::shared_ptr textBox; std::shared_ptr cursor; std::shared_ptr modMap; UndoManager textboxUndo; - std::function onTextEdit; }; diff --git a/src/World.cpp b/src/World.cpp index 44d6a8c..541df5b 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -244,6 +244,21 @@ void World::on_tab_out() { rMan.clear_display_cache(); } +void World::input_paste_callback(const CustomEvents::PasteEventData& paste) { + if(!clientStillConnecting) + drawProg.input_paste_callback(paste); +} + +void World::input_text_key_callback(const InputManager::KeyCallbackArgs& key) { + if(!clientStillConnecting) + drawProg.input_text_key_callback(key); +} + +void World::input_text_callback(const InputManager::TextCallbackArgs& text) { + if(!clientStillConnecting) + drawProg.input_text_callback(text); +} + void World::input_drop_file_callback(const InputManager::DropCallbackArgs& drop) { if(!clientStillConnecting) drawProg.input_drop_file_callback(drop); diff --git a/src/World.hpp b/src/World.hpp index a6b3545..3791889 100644 --- a/src/World.hpp +++ b/src/World.hpp @@ -96,8 +96,11 @@ class World { std::shared_ptr netServer; std::shared_ptr netClient; + void input_paste_callback(const CustomEvents::PasteEventData& paste); void input_drop_file_callback(const InputManager::DropCallbackArgs& drop); void input_drop_text_callback(const InputManager::DropCallbackArgs& drop); + void input_text_key_callback(const InputManager::KeyCallbackArgs& key); + void input_text_callback(const InputManager::TextCallbackArgs& text); void input_key_callback(const InputManager::KeyCallbackArgs& key); void input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button); void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion); diff --git a/src/main.cpp b/src/main.cpp index 82a049e..abd60da 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,3 +1,4 @@ +#include "CustomEvents.hpp" #include "Helpers/SCollision.hpp" #include "Helpers/StringHelpers.hpp" #include "Helpers/FileDownloader.hpp" @@ -94,6 +95,7 @@ #include #include "SwitchCWD.hpp" +#include "CustomEvents.hpp" // Use dedicated graphics card on Windows #ifdef _WIN32 @@ -832,8 +834,11 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) { break; case SDL_EVENT_SCREEN_KEYBOARD_HIDDEN: break; - default: + default: { + if(event->type == CustomEvents::PASTE_EVENT) + mS.m->input.backend_paste_event(); break; + } } #ifdef NDEBUG }