2013-07-28 22:08:34 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// The user-visible undo/redo operation; whenever they change something, we
|
|
|
|
// record our state and push it on a stack, and we pop the stack when they
|
|
|
|
// select undo.
|
|
|
|
//
|
|
|
|
// Copyright 2008-2013 Jonathan Westhues.
|
|
|
|
//-----------------------------------------------------------------------------
|
2008-06-04 10:22:30 +00:00
|
|
|
#include "solvespace.h"
|
|
|
|
|
2015-03-23 17:49:04 +00:00
|
|
|
void SolveSpaceUI::UndoRemember(void) {
|
2008-06-30 09:09:17 +00:00
|
|
|
unsaved = true;
|
2008-06-04 10:22:30 +00:00
|
|
|
PushFromCurrentOnto(&undo);
|
|
|
|
UndoClearStack(&redo);
|
|
|
|
UndoEnableMenus();
|
|
|
|
}
|
|
|
|
|
2015-03-23 17:49:04 +00:00
|
|
|
void SolveSpaceUI::UndoUndo(void) {
|
2008-06-04 10:22:30 +00:00
|
|
|
if(undo.cnt <= 0) return;
|
|
|
|
|
|
|
|
PushFromCurrentOnto(&redo);
|
|
|
|
PopOntoCurrentFrom(&undo);
|
|
|
|
UndoEnableMenus();
|
|
|
|
}
|
|
|
|
|
2015-03-23 17:49:04 +00:00
|
|
|
void SolveSpaceUI::UndoRedo(void) {
|
2008-06-04 10:22:30 +00:00
|
|
|
if(redo.cnt <= 0) return;
|
|
|
|
|
|
|
|
PushFromCurrentOnto(&undo);
|
|
|
|
PopOntoCurrentFrom(&redo);
|
|
|
|
UndoEnableMenus();
|
|
|
|
}
|
|
|
|
|
2015-03-23 17:49:04 +00:00
|
|
|
void SolveSpaceUI::UndoEnableMenus(void) {
|
2008-06-04 10:22:30 +00:00
|
|
|
EnableMenuById(GraphicsWindow::MNU_UNDO, undo.cnt > 0);
|
|
|
|
EnableMenuById(GraphicsWindow::MNU_REDO, redo.cnt > 0);
|
|
|
|
}
|
|
|
|
|
2015-03-23 17:49:04 +00:00
|
|
|
void SolveSpaceUI::PushFromCurrentOnto(UndoStack *uk) {
|
2008-06-04 10:22:30 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
if(uk->cnt == MAX_UNDO) {
|
|
|
|
UndoClearState(&(uk->d[uk->write]));
|
|
|
|
// And then write in to this one again
|
|
|
|
} else {
|
|
|
|
(uk->cnt)++;
|
|
|
|
}
|
|
|
|
|
|
|
|
UndoState *ut = &(uk->d[uk->write]);
|
|
|
|
ZERO(ut);
|
2009-04-19 05:53:16 +00:00
|
|
|
for(i = 0; i < SK.group.n; i++) {
|
|
|
|
Group *src = &(SK.group.elem[i]);
|
2008-06-04 10:22:30 +00:00
|
|
|
Group dest = *src;
|
|
|
|
// And then clean up all the stuff that needs to be a deep copy,
|
|
|
|
// and zero out all the dynamic stuff that will get regenerated.
|
|
|
|
dest.clean = false;
|
|
|
|
ZERO(&(dest.solved));
|
2009-10-29 07:16:28 +00:00
|
|
|
ZERO(&(dest.polyLoops));
|
|
|
|
ZERO(&(dest.bezierLoops));
|
|
|
|
ZERO(&(dest.bezierOpens));
|
2008-06-04 10:22:30 +00:00
|
|
|
ZERO(&(dest.polyError));
|
2009-05-21 09:06:26 +00:00
|
|
|
ZERO(&(dest.thisMesh));
|
2008-06-21 10:18:20 +00:00
|
|
|
ZERO(&(dest.runningMesh));
|
2009-01-19 10:37:10 +00:00
|
|
|
ZERO(&(dest.thisShell));
|
|
|
|
ZERO(&(dest.runningShell));
|
2009-05-21 09:06:26 +00:00
|
|
|
ZERO(&(dest.displayMesh));
|
|
|
|
ZERO(&(dest.displayEdges));
|
2008-06-04 10:22:30 +00:00
|
|
|
|
|
|
|
ZERO(&(dest.remap));
|
|
|
|
src->remap.DeepCopyInto(&(dest.remap));
|
|
|
|
|
|
|
|
ZERO(&(dest.impMesh));
|
2009-05-19 07:26:38 +00:00
|
|
|
ZERO(&(dest.impShell));
|
2008-06-04 10:22:30 +00:00
|
|
|
ZERO(&(dest.impEntity));
|
|
|
|
ut->group.Add(&dest);
|
|
|
|
}
|
2009-04-19 05:53:16 +00:00
|
|
|
for(i = 0; i < SK.request.n; i++) {
|
|
|
|
ut->request.Add(&(SK.request.elem[i]));
|
2008-06-04 10:22:30 +00:00
|
|
|
}
|
2009-04-19 05:53:16 +00:00
|
|
|
for(i = 0; i < SK.constraint.n; i++) {
|
|
|
|
Constraint *src = &(SK.constraint.elem[i]);
|
2008-06-04 10:22:30 +00:00
|
|
|
Constraint dest = *src;
|
|
|
|
ZERO(&(dest.dogd));
|
|
|
|
ut->constraint.Add(&dest);
|
|
|
|
}
|
2009-04-19 05:53:16 +00:00
|
|
|
for(i = 0; i < SK.param.n; i++) {
|
|
|
|
ut->param.Add(&(SK.param.elem[i]));
|
2008-06-04 10:22:30 +00:00
|
|
|
}
|
2009-09-17 07:32:36 +00:00
|
|
|
for(i = 0; i < SK.style.n; i++) {
|
|
|
|
ut->style.Add(&(SK.style.elem[i]));
|
|
|
|
}
|
2008-06-04 10:22:30 +00:00
|
|
|
ut->activeGroup = SS.GW.activeGroup;
|
|
|
|
|
|
|
|
uk->write = WRAP(uk->write + 1, MAX_UNDO);
|
|
|
|
}
|
|
|
|
|
2015-03-23 17:49:04 +00:00
|
|
|
void SolveSpaceUI::PopOntoCurrentFrom(UndoStack *uk) {
|
2008-06-04 10:22:30 +00:00
|
|
|
if(uk->cnt <= 0) oops();
|
|
|
|
(uk->cnt)--;
|
|
|
|
uk->write = WRAP(uk->write - 1, MAX_UNDO);
|
|
|
|
|
|
|
|
UndoState *ut = &(uk->d[uk->write]);
|
|
|
|
|
|
|
|
// Free everything in the main copy of the program before replacing it
|
2010-02-28 19:23:01 +00:00
|
|
|
Group *g;
|
|
|
|
for(g = SK.group.First(); g; g = SK.group.NextAfter(g)) {
|
|
|
|
g->Clear();
|
2008-06-04 10:22:30 +00:00
|
|
|
}
|
2009-04-19 05:53:16 +00:00
|
|
|
SK.group.Clear();
|
|
|
|
SK.request.Clear();
|
|
|
|
SK.constraint.Clear();
|
|
|
|
SK.param.Clear();
|
2009-09-17 07:32:36 +00:00
|
|
|
SK.style.Clear();
|
2008-06-04 10:22:30 +00:00
|
|
|
|
|
|
|
// And then do a shallow copy of the state from the undo list
|
2009-04-19 05:53:16 +00:00
|
|
|
ut->group.MoveSelfInto(&(SK.group));
|
|
|
|
ut->request.MoveSelfInto(&(SK.request));
|
|
|
|
ut->constraint.MoveSelfInto(&(SK.constraint));
|
|
|
|
ut->param.MoveSelfInto(&(SK.param));
|
2009-09-17 07:32:36 +00:00
|
|
|
ut->style.MoveSelfInto(&(SK.style));
|
2008-06-04 10:22:30 +00:00
|
|
|
SS.GW.activeGroup = ut->activeGroup;
|
|
|
|
|
|
|
|
// No need to free it, since a shallow copy was made above
|
|
|
|
ZERO(ut);
|
|
|
|
|
|
|
|
// And reset the state everywhere else in the program, since the
|
|
|
|
// sketch just changed a lot.
|
|
|
|
SS.GW.ClearSuper();
|
|
|
|
SS.TW.ClearSuper();
|
|
|
|
SS.ReloadAllImported();
|
|
|
|
SS.GenerateAll(0, INT_MAX);
|
2015-03-18 17:02:11 +00:00
|
|
|
SS.ScheduleShowTW();
|
2015-11-01 16:26:55 +00:00
|
|
|
|
|
|
|
// Activate the group that was active before.
|
|
|
|
Group *activeGroup = SK.group.FindById(SS.GW.activeGroup);
|
|
|
|
activeGroup->Activate();
|
2008-06-04 10:22:30 +00:00
|
|
|
}
|
|
|
|
|
2015-03-23 17:49:04 +00:00
|
|
|
void SolveSpaceUI::UndoClearStack(UndoStack *uk) {
|
2008-06-04 10:22:30 +00:00
|
|
|
while(uk->cnt > 0) {
|
|
|
|
uk->write = WRAP(uk->write - 1, MAX_UNDO);
|
|
|
|
(uk->cnt)--;
|
|
|
|
UndoClearState(&(uk->d[uk->write]));
|
|
|
|
}
|
|
|
|
ZERO(uk); // for good measure
|
|
|
|
}
|
|
|
|
|
2015-03-23 17:49:04 +00:00
|
|
|
void SolveSpaceUI::UndoClearState(UndoState *ut) {
|
2008-06-04 10:22:30 +00:00
|
|
|
int i;
|
|
|
|
for(i = 0; i < ut->group.n; i++) {
|
|
|
|
Group *g = &(ut->group.elem[i]);
|
|
|
|
|
|
|
|
g->remap.Clear();
|
|
|
|
}
|
|
|
|
ut->group.Clear();
|
|
|
|
ut->request.Clear();
|
|
|
|
ut->constraint.Clear();
|
|
|
|
ut->param.Clear();
|
2009-09-17 07:32:36 +00:00
|
|
|
ut->style.Clear();
|
2008-06-04 10:22:30 +00:00
|
|
|
ZERO(ut);
|
|
|
|
}
|
|
|
|
|