Can undo placed images, and textbox insert only creates one undo action

This commit is contained in:
Yousef Khadadeh 2026-01-06 12:55:44 +03:00
parent c15a21e488
commit ffde2a3284
5 changed files with 57 additions and 47 deletions

View file

@ -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<float>(), 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);
}
}

View file

@ -154,8 +154,7 @@ void DrawingProgramLayerManager::add_undo_place_component(CanvasComponentContain
using namespace NetworkingObjects;
class AddCanvasComponentWorldUndoAction : public WorldUndoAction {
public:
AddCanvasComponentWorldUndoAction(std::unique_ptr<CanvasComponentContainer::CopyData> 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<NetObjOrderedList<CanvasComponentContainer>>(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<AddCanvasComponentWorldUndoAction>(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<AddCanvasComponentWorldUndoAction>(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<DrawingProgramLayerListItem*, std::vector<CanvasComponentContainer::ObjInfoIterator>>& eraseMap) {

View file

@ -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<CanvasComponent> initOldData, std::unique_ptr<CanvasComponent> 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<NetworkingObjects::NetObjID> toEditID = undoMan.get_netid_from_undoid(undoID);
if(!toEditID.has_value())
return false;
auto objPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<CanvasComponentContainer>(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<NetworkingObjects::NetObjID> toEditID = undoMan.get_netid_from_undoid(undoID);
if(!toEditID.has_value())
return false;
auto objPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<CanvasComponentContainer>(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<CanvasComponent> oldData;
std::unique_ptr<CanvasComponent> newData;
WorldUndoManager::UndoObjectID undoID;
};
drawP.world.undo.push(std::make_unique<EditCanvasComponentWorldUndoAction>(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<CanvasComponent> 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<NetworkingObjects::NetObjID> toEditID = undoMan.get_netid_from_undoid(undoID);
if(!toEditID.has_value())
return false;
auto objPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<CanvasComponentContainer>(toEditID.value());
std::unique_ptr<CanvasComponent> 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<NetworkingObjects::NetObjID> toEditID = undoMan.get_netid_from_undoid(undoID);
if(!toEditID.has_value())
return false;
auto objPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id<CanvasComponentContainer>(toEditID.value());
std::unique_ptr<CanvasComponent> 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<CanvasComponent> data;
WorldUndoManager::UndoObjectID undoID;
};
drawP.world.undo.push(std::make_unique<EditCanvasComponentWorldUndoAction>(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);
}
}

View file

@ -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<DrawingProgramEditToolBase> compEditTool;
@ -36,6 +36,7 @@ class EditTool : public DrawingProgramToolBase {
CanvasComponentContainer::ObjInfo* objInfoBeingEdited = nullptr;
HandleData* pointDragging = nullptr;
std::any prevData;
bool undoAfterEditDone;
std::unique_ptr<CanvasComponent> oldData;
};

View file

@ -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<EditTool>(drawP);
editTool->edit_start(objInfoBeingEdited);
editTool->edit_start(objInfoBeingEdited, false);
drawP.toolToSwitchToAfterUpdate = std::move(editTool);
return;
}