From ffde2a328495f97a7babad9df15d4f80d126d7b0 Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Tue, 6 Jan 2026 12:55:44 +0300 Subject: [PATCH] Can undo placed images, and textbox insert only creates one undo action --- src/DrawingProgram/DrawingProgram.cpp | 7 +- .../Layers/DrawingProgramLayerManager.cpp | 9 +- src/DrawingProgram/Tools/EditTool.cpp | 83 ++++++++++--------- src/DrawingProgram/Tools/EditTool.hpp | 3 +- src/DrawingProgram/Tools/TextBoxTool.cpp | 2 +- 5 files changed, 57 insertions(+), 47 deletions(-) diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index 909fc70..c9796f7 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -454,6 +454,7 @@ void DrawingProgram::drag_drop_update() { img.d.p2 = droppedItem.pos + imDim; img.d.imageID = {0, 0}; auto newObjInfo = layerMan.add_component_to_layer_being_edited(newContainer); + layerMan.add_undo_place_component(newObjInfo); droppedDownloadingFiles.emplace_back(newObjInfo, world.main.window.size.cast(), FileDownloader::download_data_from_url(droppedItem.dataText.value())); } } @@ -529,7 +530,8 @@ void DrawingProgram::add_file_to_canvas_by_path_execute(const std::filesystem::p img.d.p1 = dropPos - imDim; img.d.p2 = dropPos + imDim; img.d.imageID = imageID; - layerMan.add_component_to_layer_being_edited(newContainer); + auto newObjInfo = layerMan.add_component_to_layer_being_edited(newContainer); + layerMan.add_undo_place_component(newObjInfo); } } } @@ -551,7 +553,8 @@ void DrawingProgram::add_file_to_canvas_by_data(const std::string& fileName, std img.d.p1 = dropPos - imDim; img.d.p2 = dropPos + imDim; img.d.imageID = imageID; - layerMan.add_component_to_layer_being_edited(newContainer); + auto newObjInfo = layerMan.add_component_to_layer_being_edited(newContainer); + layerMan.add_undo_place_component(newObjInfo); } } diff --git a/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp b/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp index c8e0fe0..2edf5b8 100644 --- a/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp +++ b/src/DrawingProgram/Layers/DrawingProgramLayerManager.cpp @@ -154,8 +154,7 @@ void DrawingProgramLayerManager::add_undo_place_component(CanvasComponentContain using namespace NetworkingObjects; class AddCanvasComponentWorldUndoAction : public WorldUndoAction { public: - AddCanvasComponentWorldUndoAction(std::unique_ptr initCopyData, uint32_t newPos, WorldUndoManager::UndoObjectID initUndoID, WorldUndoManager::UndoObjectID initComponentListUndoID): - copyData(std::move(initCopyData)), + AddCanvasComponentWorldUndoAction(uint32_t newPos, WorldUndoManager::UndoObjectID initUndoID, WorldUndoManager::UndoObjectID initComponentListUndoID): pos(newPos), undoID(initUndoID), componentListUndoID(initComponentListUndoID) @@ -171,7 +170,9 @@ void DrawingProgramLayerManager::add_undo_place_component(CanvasComponentContain if(!toEraseCompListID.has_value()) return false; auto compList = undoMan.world.netObjMan.get_obj_temporary_ref_from_id>(toEraseCompListID.value()); - compList->erase(compList, compList->get(toEraseID.value())); + auto toEraseIt = compList->get(toEraseID.value()); + copyData = toEraseIt->obj->get_data_copy(); + compList->erase(compList, toEraseIt); return true; } bool redo(WorldUndoManager& undoMan) override { @@ -197,7 +198,7 @@ void DrawingProgramLayerManager::add_undo_place_component(CanvasComponentContain WorldUndoManager::UndoObjectID componentListUndoID; }; - drawP.world.undo.push(std::make_unique(objInfo->obj->get_data_copy(), objInfo->pos, drawP.world.undo.get_undoid_from_netid(objInfo->obj.get_net_id()), drawP.world.undo.get_undoid_from_netid(objInfo->obj->parentLayer->get_layer().components.get_net_id()))); + drawP.world.undo.push(std::make_unique(objInfo->pos, drawP.world.undo.get_undoid_from_netid(objInfo->obj.get_net_id()), drawP.world.undo.get_undoid_from_netid(objInfo->obj->parentLayer->get_layer().components.get_net_id()))); } void DrawingProgramLayerManager::erase_component_map(const std::unordered_map>& eraseMap) { diff --git a/src/DrawingProgram/Tools/EditTool.cpp b/src/DrawingProgram/Tools/EditTool.cpp index cf70afc..9542418 100644 --- a/src/DrawingProgram/Tools/EditTool.cpp +++ b/src/DrawingProgram/Tools/EditTool.cpp @@ -58,44 +58,48 @@ void EditTool::switch_tool(DrawingProgramToolType newTool) { objInfoBeingEdited->obj->commit_update(drawP); objInfoBeingEdited->obj->send_comp_update(drawP, true); - class EditCanvasComponentWorldUndoAction : public WorldUndoAction { - public: - EditCanvasComponentWorldUndoAction(std::unique_ptr initOldData, std::unique_ptr initNewData, WorldUndoManager::UndoObjectID initUndoID): - oldData(std::move(initOldData)), - newData(std::move(initNewData)), - undoID(initUndoID) - {} - std::string get_name() const override { - return "Edit Canvas Component"; - } - bool undo(WorldUndoManager& undoMan) override { - std::optional toEditID = undoMan.get_netid_from_undoid(undoID); - if(!toEditID.has_value()) - return false; - auto objPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id(toEditID.value()); - objPtr->get_comp().set_data_from(*oldData); - objPtr->commit_update(undoMan.world.drawProg); - objPtr->send_comp_update(undoMan.world.drawProg, true); - return true; - } - bool redo(WorldUndoManager& undoMan) override { - std::optional toEditID = undoMan.get_netid_from_undoid(undoID); - if(!toEditID.has_value()) - return false; - auto objPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id(toEditID.value()); - objPtr->get_comp().set_data_from(*newData); - objPtr->commit_update(undoMan.world.drawProg); - objPtr->send_comp_update(undoMan.world.drawProg, true); - return true; - } - ~EditCanvasComponentWorldUndoAction() {} - - std::unique_ptr oldData; - std::unique_ptr newData; - WorldUndoManager::UndoObjectID undoID; - }; - - drawP.world.undo.push(std::make_unique(std::move(oldData), objInfoBeingEdited->obj->get_comp().get_data_copy(), drawP.world.undo.get_undoid_from_netid(objInfoBeingEdited->obj.get_net_id()))); + if(undoAfterEditDone) { + class EditCanvasComponentWorldUndoAction : public WorldUndoAction { + public: + EditCanvasComponentWorldUndoAction(std::unique_ptr initData, WorldUndoManager::UndoObjectID initUndoID): + data(std::move(initData)), + undoID(initUndoID) + {} + std::string get_name() const override { + return "Edit Canvas Component"; + } + bool undo(WorldUndoManager& undoMan) override { + std::optional toEditID = undoMan.get_netid_from_undoid(undoID); + if(!toEditID.has_value()) + return false; + auto objPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id(toEditID.value()); + std::unique_ptr newData = objPtr->get_comp().get_data_copy(); + objPtr->get_comp().set_data_from(*data); + data = std::move(newData); + objPtr->commit_update(undoMan.world.drawProg); + objPtr->send_comp_update(undoMan.world.drawProg, true); + return true; + } + bool redo(WorldUndoManager& undoMan) override { + std::optional toEditID = undoMan.get_netid_from_undoid(undoID); + if(!toEditID.has_value()) + return false; + auto objPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id(toEditID.value()); + std::unique_ptr newData = objPtr->get_comp().get_data_copy(); + objPtr->get_comp().set_data_from(*data); + data = std::move(newData); + objPtr->commit_update(undoMan.world.drawProg); + objPtr->send_comp_update(undoMan.world.drawProg, true); + return true; + } + ~EditCanvasComponentWorldUndoAction() {} + + std::unique_ptr data; + WorldUndoManager::UndoObjectID undoID; + }; + + drawP.world.undo.push(std::make_unique(std::move(oldData), drawP.world.undo.get_undoid_from_netid(objInfoBeingEdited->obj.get_net_id()))); + } oldData = nullptr; objInfoBeingEdited = nullptr; @@ -107,7 +111,7 @@ void EditTool::switch_tool(DrawingProgramToolType newTool) { drawP.selection.deselect_all(); } -void EditTool::edit_start(CanvasComponentContainer::ObjInfo* comp) { +void EditTool::edit_start(CanvasComponentContainer::ObjInfo* comp, bool initUndoAfterEditDone) { bool isEditing = true; switch(comp->obj->get_comp().get_type()) { case CanvasComponentType::TEXTBOX: { @@ -134,6 +138,7 @@ void EditTool::edit_start(CanvasComponentContainer::ObjInfo* comp) { if(isEditing) { objInfoBeingEdited = comp; oldData = comp->obj->get_comp().get_data_copy(); + undoAfterEditDone = initUndoAfterEditDone; compEditTool->edit_start(*this, objInfoBeingEdited, prevData); } } diff --git a/src/DrawingProgram/Tools/EditTool.hpp b/src/DrawingProgram/Tools/EditTool.hpp index a964bca..f197e0d 100644 --- a/src/DrawingProgram/Tools/EditTool.hpp +++ b/src/DrawingProgram/Tools/EditTool.hpp @@ -28,7 +28,7 @@ class EditTool : public DrawingProgramToolBase { ~EditTool(); void add_point_handle(const HandleData& handle); - void edit_start(CanvasComponentContainer::ObjInfo* comp); + void edit_start(CanvasComponentContainer::ObjInfo* comp, bool initUndoAfterEditDone = true); bool is_editable(CanvasComponentContainer::ObjInfo* comp); std::unique_ptr compEditTool; @@ -36,6 +36,7 @@ class EditTool : public DrawingProgramToolBase { CanvasComponentContainer::ObjInfo* objInfoBeingEdited = nullptr; HandleData* pointDragging = nullptr; std::any prevData; + bool undoAfterEditDone; std::unique_ptr oldData; }; diff --git a/src/DrawingProgram/Tools/TextBoxTool.cpp b/src/DrawingProgram/Tools/TextBoxTool.cpp index b4222f7..6236a82 100644 --- a/src/DrawingProgram/Tools/TextBoxTool.cpp +++ b/src/DrawingProgram/Tools/TextBoxTool.cpp @@ -72,7 +72,7 @@ void TextBoxTool::tool_update() { textBox.d.p2 = ensure_points_have_distance(textBox.d.p1, textBox.d.p2, MINIMUM_DISTANCE_BETWEEN_BOUNDS); if(!drawP.controls.leftClickHeld) { auto editTool = std::make_unique(drawP); - editTool->edit_start(objInfoBeingEdited); + editTool->edit_start(objInfoBeingEdited, false); drawP.toolToSwitchToAfterUpdate = std::move(editTool); return; }