Solvespace
153 строки · 4.5 Кб
1//-----------------------------------------------------------------------------
2// The user-visible undo/redo operation; whenever they change something, we
3// record our state and push it on a stack, and we pop the stack when they
4// select undo.
5//
6// Copyright 2008-2013 Jonathan Westhues.
7//-----------------------------------------------------------------------------
8#include "solvespace.h"
9
10void SolveSpaceUI::UndoRemember() {
11unsaved = true;
12PushFromCurrentOnto(&undo);
13UndoClearStack(&redo);
14UndoEnableMenus();
15}
16
17void SolveSpaceUI::UndoUndo() {
18if(undo.cnt <= 0) return;
19
20PushFromCurrentOnto(&redo);
21PopOntoCurrentFrom(&undo);
22UndoEnableMenus();
23}
24
25void SolveSpaceUI::UndoRedo() {
26if(redo.cnt <= 0) return;
27
28PushFromCurrentOnto(&undo);
29PopOntoCurrentFrom(&redo);
30UndoEnableMenus();
31}
32
33void SolveSpaceUI::UndoEnableMenus() {
34SS.GW.undoMenuItem->SetEnabled(undo.cnt > 0);
35SS.GW.redoMenuItem->SetEnabled(redo.cnt > 0);
36}
37
38void SolveSpaceUI::PushFromCurrentOnto(UndoStack *uk) {
39if(uk->cnt == MAX_UNDO) {
40UndoClearState(&(uk->d[uk->write]));
41// And then write in to this one again
42} else {
43(uk->cnt)++;
44}
45
46UndoState *ut = &(uk->d[uk->write]);
47*ut = {};
48ut->group.ReserveMore(SK.group.n);
49for(Group &src : SK.group) {
50// Shallow copy
51Group dest(src);
52// And then clean up all the stuff that needs to be a deep copy,
53// and zero out all the dynamic stuff that will get regenerated.
54dest.clean = false;
55dest.solved = {};
56dest.polyLoops = {};
57dest.bezierLoops = {};
58dest.bezierOpens = {};
59dest.polyError = {};
60dest.thisMesh = {};
61dest.runningMesh = {};
62dest.thisShell = {};
63dest.runningShell = {};
64dest.displayMesh = {};
65dest.displayOutlines = {};
66
67dest.remap = src.remap;
68
69dest.impMesh = {};
70dest.impShell = {};
71dest.impEntity = {};
72ut->group.Add(&dest);
73}
74for(auto &src : SK.groupOrder) { ut->groupOrder.Add(&src); }
75ut->request.ReserveMore(SK.request.n);
76for(auto &src : SK.request) { ut->request.Add(&src); }
77ut->constraint.ReserveMore(SK.constraint.n);
78for(auto &src : SK.constraint) {
79// Shallow copy
80Constraint dest(src);
81ut->constraint.Add(&dest);
82}
83ut->param.ReserveMore(SK.param.n);
84for(auto &src : SK.param) { ut->param.Add(&src); }
85ut->style.ReserveMore(SK.style.n);
86for(auto &src : SK.style) { ut->style.Add(&src); }
87ut->activeGroup = SS.GW.activeGroup;
88
89uk->write = WRAP(uk->write + 1, MAX_UNDO);
90}
91
92void SolveSpaceUI::PopOntoCurrentFrom(UndoStack *uk) {
93ssassert(uk->cnt > 0, "Cannot pop from empty undo stack");
94(uk->cnt)--;
95uk->write = WRAP(uk->write - 1, MAX_UNDO);
96
97UndoState *ut = &(uk->d[uk->write]);
98
99// Free everything in the main copy of the program before replacing it
100for(hGroup hg : SK.groupOrder) {
101Group *g = SK.GetGroup(hg);
102g->Clear();
103}
104SK.group.Clear();
105SK.groupOrder.Clear();
106SK.request.Clear();
107SK.constraint.Clear();
108SK.param.Clear();
109SK.style.Clear();
110
111// And then do a shallow copy of the state from the undo list
112ut->group.MoveSelfInto(&(SK.group));
113for(auto &gh : ut->groupOrder) { SK.groupOrder.Add(&gh); }
114ut->request.MoveSelfInto(&(SK.request));
115ut->constraint.MoveSelfInto(&(SK.constraint));
116ut->param.MoveSelfInto(&(SK.param));
117ut->style.MoveSelfInto(&(SK.style));
118SS.GW.activeGroup = ut->activeGroup;
119
120// No need to free it, since a shallow copy was made above
121*ut = {};
122
123// And reset the state everywhere else in the program, since the
124// sketch just changed a lot.
125SS.GW.ClearSuper();
126SS.TW.ClearSuper();
127SS.ReloadAllLinked(SS.saveFile);
128SS.GenerateAll(SolveSpaceUI::Generate::ALL);
129SS.ScheduleShowTW();
130
131// Activate the group that was active before.
132Group *activeGroup = SK.GetGroup(SS.GW.activeGroup);
133activeGroup->Activate();
134}
135
136void SolveSpaceUI::UndoClearStack(UndoStack *uk) {
137while(uk->cnt > 0) {
138uk->write = WRAP(uk->write - 1, MAX_UNDO);
139(uk->cnt)--;
140UndoClearState(&(uk->d[uk->write]));
141}
142*uk = {}; // for good measure
143}
144
145void SolveSpaceUI::UndoClearState(UndoState *ut) {
146for(auto &g : ut->group) { g.remap.clear(); }
147ut->group.Clear();
148ut->request.Clear();
149ut->constraint.Clear();
150ut->param.Clear();
151ut->style.Clear();
152*ut = {};
153}
154
155