View Javadoc

1   /*
2    *  nextobjects Copyright (C) 2001-2005 Emmanuel Florent
3    *  This program is free software; you can redistribute it and/or modify
4    *  it under the terms of the GNU General Public License as published by the
5    *  Free Software Foundation; either version 2 of the License, or (at your
6    *  option) any later version.
7    *  This program is distributed in the hope that it will
8    *  be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
9    *  of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10   *  PURPOSE. See the GNU General Public License for more details.
11   *  You should have received a copy of the GNU General Public License along
12   *  with this program; if not, write to the Free Software Foundation, Inc., 59
13   *  Temple Place - Suite 330, Boston, MA 02111-1307, USA.
14   */
15  package org.devaki.nextobjects.util;
16  
17  import java.util.Stack;
18  import org.devaki.nextobjects.workspace.models.objects.BaseObject;
19  import org.devaki.nextobjects.workspace.models.objects.Entity;
20  import org.devaki.nextobjects.workspace.models.objects.Association;
21  import org.devaki.nextobjects.workspace.models.objects.AssociationLink;
22  import org.devaki.nextobjects.workspace.models.ConceptualModel;
23  import org.devaki.nextobjects.workspace.models.PhysicalModel;
24  import org.devaki.nextobjects.workspace.models.objects.Table;
25  import org.devaki.nextobjects.workspace.models.objects.Constraint;
26  import java.awt.Dimension;
27  
28  /***
29   *  This class is in charge of most of the Undo/Redo stuff. The model was
30   *  inspired from the gimp dual stack system. There is a redo stack and an undo
31   *  stack. Undoing activate the redo stack while doing something activate the
32   *  undo stack.
33   *
34   * @author     : efloretnt@devaki.org
35   * @created    December 27, 2003
36   */
37  
38  public class NORedoLog
39  {
40  
41      /***  Actions Delete */
42      public final static int ACTION_DELETE = 0;
43      /***  Actions Move */
44      public final static int ACTION_MOVE = 1;
45      /***  Actions Resize */
46      public final static int ACTION_RESIZE = 2;
47      /***  Actions Create */
48      public final static int ACTION_CREATE = 3;
49      /***  Log Type descriptorfor the undo stack */
50      public final static int LOG_UNDOLOG = 0;
51      /***  Log Type Descriptor for redo stack */
52      public final static int LOG_REDOLOG = 1;
53      /***  Log Size */
54      public final static int REDOLOG_SIZE = 25;
55      /***  The redo stack */
56      private Stack redoLog = new Stack();
57      /***  The undo stack */
58      private Stack undoLog = new Stack();
59      /***  A flag to know the current stack */
60      private static int currentStack = LOG_UNDOLOG;
61      /***  a redo item */
62      private static NORedoItem redoItem = null;
63  
64  
65      /***  Dummy constructor. Should never be used. */
66      public NORedoLog() { }
67  
68  
69      /***  Description of the Method */
70      public void clear()
71      {
72          redoLog.clear();
73          undoLog.clear();
74      }
75  
76  
77      /***
78       *  Log all possible action coming from ModelMan.java
79       *
80       * @param  pAction  flag describing the action
81       * @param  pTarget  the object
82       * @param  pX       optional X coordinate parameter
83       * @param  pY       optional Y coordinate parameter
84       */
85      public void log(int pAction, BaseObject pTarget, int pX, int pY)
86      {
87      NORedoItem redoItem = new NORedoItem(pAction, pTarget, pX, pY);
88  
89          switch (currentStack)
90          {
91              case LOG_REDOLOG:
92                  redoLog.push(redoItem);
93                  currentStack = LOG_UNDOLOG;
94                  if (redoLog.size() > REDOLOG_SIZE)
95                  {
96                      redoLog.removeElementAt(0);
97                  }
98                  break;
99              default:
100                 undoLog.push(redoItem);
101                 if (undoLog.size() > REDOLOG_SIZE)
102                 {
103                     undoLog.removeElementAt(0);
104                 }
105                 break;
106         }
107     }
108 
109 
110     /***
111      *  An <code>undo</code> call switch the current stack and call each of the
112      *  action executers for the last action of the undo stack
113      */
114     public void undo()
115     {
116         currentStack = LOG_REDOLOG;
117 
118         if (undoLog.size() > 0)
119         {
120             redoItem = (NORedoItem) undoLog.pop();
121         }
122         if (redoItem != null)
123         {
124 
125             ModelMan.setCurrentObject(redoItem.target);
126             switch (redoItem.action)
127             {
128                 case ACTION_DELETE:
129                     redoDelete(redoItem);
130                     break;
131                 case ACTION_MOVE:
132                     redoMove(redoItem);
133                     break;
134                 case ACTION_RESIZE:
135                     redoResize(redoItem);
136                     break;
137                 case ACTION_CREATE:
138                     redoCreate();
139                     break;
140                 default:
141                     //logger.debug("undoing unknow action!");
142                     break;
143             }
144         }
145         // else {
146         //   logger.warn("Nothing to undo!");
147         //}
148         ModelMan.getCurrentModel().getModelView().setFullRefresh(true);
149         ModelMan.getCurrentModel().getModelView().repaint();
150     }
151 
152 
153     /***
154      *  An <code>redo</code> call switch the current stack and call each of the
155      *  action executers for the last action of the redo stack
156      */
157     public void redo()
158     {
159     NORedoItem redoItem = null;
160 
161         if (redoLog.size() > 0)
162         {
163             redoItem = (NORedoItem) redoLog.pop();
164         }
165         else
166             if (redoItem != null)
167         {
168             ModelMan.setCurrentObject(redoItem.target);
169             switch (redoItem.action)
170             {
171                 case ACTION_DELETE:
172                     redoDelete(redoItem);
173                     break;
174                 case ACTION_MOVE:
175                     redoMove(redoItem);
176                     break;
177                 case ACTION_RESIZE:
178                     redoResize(redoItem);
179                     break;
180                 case ACTION_CREATE:
181                     redoCreate();
182                     break;
183                 default:
184                     //logger.debug("redoing unknow action!");
185                     break;
186             }
187         }
188         ModelMan.getCurrentModel().getModelView().setFullRefresh(true);
189         ModelMan.getCurrentModel().getModelView().repaint();
190     }
191 
192 
193     /***
194      *  Redo Move action
195      *
196      * @param  redoItem  the item to redo
197      */
198     private void redoMove(NORedoItem redoItem)
199     {
200         ModelMan.moveCurrentObjects(redoItem.x * (-1), redoItem.y * (-1));
201     }
202 
203 
204     /***
205      *  Redo Resize action
206      *
207      * @param  redoItem  the item to redo
208      */
209     private static void redoResize(NORedoItem redoItem)
210     {
211         redoItem.target.getObjectView().setSize(
212             new Dimension(redoItem.x, redoItem.y));
213     }
214 
215 
216     /***  Redo Create action */
217     private static void redoCreate()
218     {
219         ModelMan.delete();
220     }
221 
222 
223     /***
224      *  Redo Delete action
225      *
226      * @param  redoItem  the item to redo
227      */
228     private static void redoDelete(NORedoItem redoItem)
229     {
230         if (ModelMan.getCurrentModel() instanceof ConceptualModel)
231         {
232             if (redoItem.target instanceof Entity)
233             {
234                 ModelMan.addEntity(
235                     (ConceptualModel) ModelMan.getCurrentModel(),
236                     (Entity) redoItem.target);
237             }
238             if (redoItem.target instanceof Association)
239             {
240                 ModelMan.addAssociation(
241                     (ConceptualModel) ModelMan.getCurrentModel(),
242                     (Association) redoItem.target);
243             }
244             if (redoItem.target instanceof AssociationLink)
245             {
246                 ModelMan.addAssociationLink(
247                     (ConceptualModel) ModelMan.getCurrentModel(),
248                     (AssociationLink) redoItem.target);
249             }
250         }
251         else if (ModelMan.getCurrentModel() instanceof PhysicalModel)
252         {
253             if (redoItem.target instanceof Table)
254             {
255                 ModelMan.addTable(
256                     (PhysicalModel) ModelMan.getCurrentModel(),
257                     (Table) redoItem.target);
258             }
259             if (redoItem.target instanceof Constraint)
260             {
261                 ModelMan.addConstraint(
262                     (PhysicalModel) ModelMan.getCurrentModel(),
263                     (Constraint) redoItem.target);
264             }
265         }
266     }
267 
268 
269     /***
270      *  This class represent a singe item to be redoed. an action item which is
271      *  made of :
272      *
273      * @author          Emmanuel Florent
274      * @created         December 27, 2003
275      * @param  pTarget  flag describing the action
276      * @param  pTarget  the object
277      * @param  pX       optional X coordinate parameter
278      * @para            pY optional Y coordinate parameter
279      */
280     class NORedoItem
281     {
282 
283         /***  a flag describing the action */
284         public int action;
285 
286         /***  the object */
287         public BaseObject target;
288 
289         /***  optional X coordinate */
290         public int x;
291 
292         /***  optional Y coordiante */
293         public int y;
294 
295 
296         /***
297          *  standard constructor
298          *
299          * @param  pAction  the action kind flag
300          * @param  pTarget  the changed object
301          * @param  pX       optional x param
302          * @param  pY       optional y param
303          */
304         public NORedoItem(int pAction, BaseObject pTarget, int pX, int pY)
305         {
306             action = pAction;
307             target = pTarget;
308             x = pX;
309             y = pY;
310         }
311 
312         /*
313          *  this function is used for debuging purpose.
314          *  @ return debug string
315          *
316          *  public String toString()
317          *  {
318          *  String actionName;
319          *  switch (action)
320          *  {
321          *  case NORedoLog.ACTION_CREATE :
322          *  actionName = "ACTION_CREATE";
323          *  break;
324          *  case NORedoLog.ACTION_DELETE :
325          *  actionName = "ACTION_DELETE";
326          *  break;
327          *  case NORedoLog.ACTION_MOVE :
328          *  actionName = "ACTION_MOVE";
329          *  break;
330          *  case NORedoLog.ACTION_RESIZE :
331          *  actionName = "ACTION_RESIZE";
332          *  break;
333          *  default :
334          *  actionName = "unknow action";
335          *  break;
336          *  }
337          *  return new StringBuffer(actionName)
338          *  .append(" ")
339          *  .append(target)
340          *  .append(" ")
341          *  .append(x)
342          *  .append("-")
343          *  .append(y)
344          *  .toString();
345          *  }
346          */
347     }
348     // end of class RedoItem
349 
350 }