Moka controlers
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros
controler-undo-redo.cc
Go to the documentation of this file.
1 /*
2  * lib-controler : Un contrôleur générique de scène 3D.
3  * Copyright (C) 2004, Moka Team, Université de Poitiers, Laboratoire SIC
4  * http://www.sic.sp2mi.univ-poitiers.fr/
5  * Copyright (C) 2009, Guillaume Damiand, CNRS, LIRIS,
6  * guillaume.damiand@liris.cnrs.fr, http://liris.cnrs.fr/
7  *
8  * This file is part of lib-controler
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program. If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 //******************************************************************************
25 #include "controler.hh"
26 using namespace std;
27 //******************************************************************************
29 {
30  return FUndoOnFile;
31 }
32 //******************************************************************************
33 void CControler::setUndoOnFile(bool ABool)
34 {
35  if (ABool!=FUndoOnFile)
36  {
37  emptyUndoRedo();
38  FUndoOnFile = ABool;
39  }
40 }
41 //******************************************************************************
43 {
44  return FNbMaxUndos;
45 
46 }
47 //******************************************************************************
48 void CControler::setNbMaxUndos(int ANumber)
49 {
50  assert(ANumber==-1 || ANumber>=0);
51 
52  if ( ANumber!=-1 && ANumber<FNbMaxUndos )
53  {
54  if (FActu != NULL)
55  {
56  FRedos.push_front(FActu);
58  FActu = NULL;
59  }
60  emptyRedoList();
61 
62  int nbToRemove = FUndos.size()-ANumber;
63  for (int i=0; i<nbToRemove; ++i)
64  {
65  if (FUndoOnFile) remove(FUndos.back()->str().c_str());
66  delete FUndos.back();
67  FUndos.pop_back();
68  }
69  }
70 
71  FNbMaxUndos = ANumber;
73 }
74 //******************************************************************************
75 bool CControler::undo(int AStep)
76 {
78  return false;
79 
80  if (!basicUndo(AStep))
81  return false;
82 
83  setMessage(string("Undo [") + getUndoRedoStatus() + "]");
84  return true;
85 }
86 //******************************************************************************
87 bool CControler::redo(int AStep)
88 {
90  return false;
91 
92  if (!basicRedo(AStep))
93  return false;
94 
95  setMessage(string("Redo [") + getUndoRedoStatus() + "]");
96  return true;
97 }
98 //******************************************************************************
100 {
101  while (!FUndos.empty())
102  {
103  if (FUndoOnFile) remove(FUndos.front()->str().c_str());
104  delete FUndos.front();
105  FUndos.pop_front();
106  }
107 
108  FLastFileIndex = 0;
110 }
111 //******************************************************************************
113 {
114  while (!FRedos.empty())
115  {
116  if (FUndoOnFile) remove(FRedos.front()->str().c_str());
117  delete FRedos.front();
118  FRedos.pop_front();
119  }
120 }
121 //******************************************************************************
123 {
124  if (FActu != NULL)
125  {
126  FRedos.push_front(FActu);
127  FActu = NULL;
128  }
129 
130  emptyRedoList();
131  emptyUndoList();
132 
133  setMessage("Undo/redo stack is now empty");
134  return true;
135 }
136 //******************************************************************************
137 string CControler::getFilename(int AIndex) const
138 {
139  assert(AIndex >= 0);
140 
141  stringstream s;
142  s<<FConfigDirectory<<"/.moka-undo-"<<AIndex;
143  return s.str();
144 }
145 //******************************************************************************
147 {
148  ++FLastFileIndex;
149 
150  if ( FNbMaxUndos!=-1 )
151  {
152  while (FUndos.size() > (unsigned int)FNbMaxUndos)
153  {
154  ostringstream* os = FUndos.back();
155  FUndos.pop_back();
156  if (FUndoOnFile) remove(os->str().c_str());
157  delete os;
158  }
159  }
160 
161  return FLastFileIndex;
162 }
163 //******************************************************************************
164 ostringstream* CControler::saveModel()
165 {
166  return NULL;
167 }
168 //------------------------------------------------------------------------------
169 bool CControler::loadModel(ostringstream * /* AStream */)
170 {
171  return true;
172 }
173 //******************************************************************************
174 bool CControler::basicUndo(int AStep)
175 {
176  if (AStep == 0)
177  return true;
178 
179  if (AStep < 0)
180  return basicRedo(-AStep);
181 
182  if (FUndos.empty())
183  return false;
184 
185  // Premier undo :
186  if (FActu == NULL)
187  FActu = saveModel();
188 
189  // Sauvegarde de l'état actuel dans la pile des redos :
190  FRedos.push_front(FActu);
191 
192  // Déplacement de AStep-1 éléments de la pile des undos vers celle des redos :
193  for (int i = 1; i < AStep && 1 < FUndos.size(); ++i)
194  {
195  FRedos.push_front(FUndos.front());
196  FUndos.pop_front();
197  --FLastFileIndex;
198  }
199 
200  // Lecture de la carte dans la pile des undos :
201  assert(! FUndos.empty());
202  FActu = FUndos.front();
203  FUndos.pop_front();
204  --FLastFileIndex;
205  loadModel(FActu);
206 
208 
209  return true;
210 }
211 //------------------------------------------------------------------------------
212 bool CControler::basicRedo(int AStep)
213 {
214  if (AStep == 0)
215  return true;
216 
217  if (AStep < 0)
218  return basicUndo(-AStep);
219 
220  if (FRedos.empty())
221  return false;
222 
223  assert(FActu != NULL);
224 
225  // Sauvegarde de l'état actuel dans la pile des undos :
226  FUndos.push_front(FActu);
227 
228  // Déplacement de AStep-1 éléments de la pile des redos vers celle des undos :
229  for (int i = 1; i < AStep && 1 < FUndos.size(); ++i)
230  {
231  FUndos.push_front(FRedos.front());
232  ++FLastFileIndex;
233  FRedos.pop_front();
234  }
235 
236  // Lecture de la carte dans la pile des undos :
237  assert(! FRedos.empty());
238  FActu = FRedos.front();
239  FRedos.pop_front();
240  loadModel(FActu);
241  ++FLastFileIndex;
242 
244 
245  return true;
246 }
247 //******************************************************************************
249 {
250  basicPreSave();
251 }
252 //------------------------------------------------------------------------------
254 {
255  basicPostSaveOk();
257 }
258 //------------------------------------------------------------------------------
260 {
262 }
263 //******************************************************************************
265 {
266  if (FNbMaxUndos==0) return;
267 
268  if ( FActu!=NULL )
269  {
270  if (FUndoOnFile) remove(FActu->str().c_str());
271  delete FActu;
272  --FLastFileIndex;
273  }
274 
275  FActu = saveModel();
276 }
277 //------------------------------------------------------------------------------
279 {
280  if (FNbMaxUndos==0) return;
281 
282  assert( FActu!=NULL );
283 
284  // Sauvegarde de FActu :
285  FUndos.push_front(FActu);
286  FActu = NULL;
287 
288  emptyRedoList();
290 }
291 //------------------------------------------------------------------------------
293 {
294  if (FNbMaxUndos==0) return;
295 
296  assert(FActu != NULL);
297 }
298 //******************************************************************************
300 {
301  stringstream s;
302  s<< FUndos.size()<<" * "<<FRedos.size();
303  return s.str();
304 }
305 //******************************************************************************
306 bool CControler::existsFile(const string & AFilename)
307 {
308  FILE * f;
309  f=fopen(AFilename.c_str(), "r");
310 
311  if (f==NULL)
312  return false;
313 
314  fclose(f);
315  return true;
316 }
317 //******************************************************************************
319 {
320  if (!FUndoOnFile) return;
321 
322  stringstream s;
323  s<<FConfigDirectory<<"/.moka-last-undo-file";
324 
325  ofstream os(s.str().c_str());
326  if (os.is_open())
327  {
328  os<<FLastFileIndex<<endl;
329  os.close();
330  }
331 }
332 //******************************************************************************
334 {
335  if (!FUndoOnFile) return;
336 
337  stringstream s;
338  s<<FConfigDirectory<<"/.moka-last-undo-file";
339 
340  ifstream is(s.str().c_str());;
341  if (is.is_open())
342  {
343  is>>FLastFileIndex;
344  is.close();
345  }
346  else
347  {
348  FLastFileIndex = 0;
349  }
350 }
351 //******************************************************************************
353 {
355 
356  if (!FUndoOnFile || FNbMaxUndos==0 || FLastFileIndex==0) return;
357 
358  string filename;
359  int nbFilesRecup = 0;
360 
361  int current = FLastFileIndex;
362  bool undoFull = false;
363  ostringstream * os;
364 
365  filename = getFilename(current);
366  while (existsFile(filename) && !undoFull)
367  {
368  os = new ostringstream;
369  (*os)<<filename.c_str();
370 
371  FUndos.push_back(os);
372 
373  ++nbFilesRecup;
374  if ( nbFilesRecup==FNbMaxUndos )
375  undoFull = true;
376 
377  --current;
378  filename = getFilename(current);
379  }
380 }
381 //******************************************************************************