1 package devisor2.grid.backend.undo;
2 
3 
4 import devisor2.grid.options.*;
5 import devisor2.grid.GUI.framework.*;
6 import devisor2.grid.GUI.event.*;
7 import devisor2.grid.GUI.dialogs.*;
8 import devisor2.foundation.*;
9 import devisor2.foundation.elements.*;
10 import devisor2.foundation.boundary.*;
11 import devisor2.foundation.base.*;
12 import devisor2.grid.backend.*;
13 
14 import java.util.*;
15 import java.awt.geom.*;
16 
17 /**
18  *  This class is responsible for managing all UNDO information. It basically
19  *  provides three core methods:<br>
20  *  <code>notifyUndo()<\code> is used whenever an undoable operation takes
21  *  place. All information neccessary to take back the operation is passed
22  *  to this method, and an UndoContainer object is created and pushed on the
23  *  UndoStack.<br>
24  *  <code>performUndo()<\code> is called whenever the UNDO operation is
25  *  called. This method is a bit lengthy to implement, scroll down and you
26  *  will see why. <br>
27  *  <code>performRedo()<\code> is called whenever the REDO operation is
28  *  called. Note that only the undos can be redone that took place BEFORE the
29  *  last regular operation. <br>
30  *  Additionally, this class provides constants for all undoable operations.
31  *
32  *  Take a look at the technical paper about UNDO if you want to learn more
33  *  about the full undo implementation.
34  *
35  *  @see UndoStack, UndoContainer
36  *  @author Dominik Goeddeke
37  *
38  */
39 public class UndoManager
40 {
41 
42     /**
43      *  The all important ControlCenter reference linking to the rest of the
44      *  application
45      */
46     private ControlCenter cc;
47 
48     /**
49      *  The equally important MainFrame reference
50      */
51     private MainFrame parent;
52 
53     /**
54      *  The UndoStack reference used to store undoable operations
55      */
56     private UndoStack stack;
57 
58     /**
59      *  a stack of the same type is used for redoing
60      */
61     private UndoStack redostack;
62 
63     /**
64      *  The constructor is used to set references correctly. It also
65      *  initialises an empty UndoStack.
66      */
UndoManager(MainFrame parent)67     public UndoManager (MainFrame parent)
68     {
69 	this.parent = parent;
70 	cc = ControlCenter.getMyself ();
71 	stack = new UndoStack ();
72 	redostack = new UndoStack ();
73     }
74 
75     /**
76      *  This method requires all information used for the operation to be
77      *  added to the UndoManager as they were. It then transforms them if
78      *  neccessary (the idea ist to split the work between the two important
79      *  methods) and pushes them onto the Stack.
80      *
81      *  @param opCode - one of the constants provided in this class
82      *  @param items - a Vector of all affected items
83      *  @param info - additional information needed to take back the given
84      *                operation
85      */
notifyUndo(int opCode, Vector items, Object info)86     public void notifyUndo (int opCode, Vector items, Object info)
87     {
88 	boolean clearredo = false;
89 	switch (opCode)
90 	{
91 	case UNDO_ADDNODE :
92 	case UNDO_ADDTRI :
93 	case UNDO_ADDQUAD :
94 	case UNDO_ADDMACRO :
95 	case UNDO_ADDLINE :
96 	case UNDO_ADDCIRCLE :
97 	case UNDO_PASTE :
98 	case UNDO_DELETE :
99 	case UNDO_CUT :
100 	    {
101 		stack.push (new UndoContainer (opCode, items, info));
102 		clearredo = true;
103 		break;
104 	    }
105 	case UNDO_SCALE :
106 	case UNDO_ROTATE :
107 	case UNDO_MIRROR :
108 	case UNDO_TRANSLATE :
109 	    {
110 		stack.push (new UndoContainer (opCode, items, info));
111 		clearredo = false;
112 		break;
113 	    }
114 	case UNDO_PROPERTYNODE :
115 	case UNDO_PROPERTYBNODE :
116 	case UNDO_PROPERTYLINE :
117 	case UNDO_PROPERTYCIRC :
118 	    {
119 		stack.push (new UndoContainer (opCode, items, info));
120 		clearredo = false;
121 		break;
122 	    }
123 	default :
124 	    {
125 		//		System.out.println ("This operation is not yet supported.");
126 		break;
127 	    }
128 	}
129 	if (clearredo)
130 	    redostack = new UndoStack ();
131     }
132 
133 
134     /**
135      *  This method takes the top element from the Stack and performs
136      *  the corresponding undo operation.
137      *
138      *  @return true if hotspots need to be repainted
139      */
performUndo()140     public boolean performUndo ()
141     {
142 	UndoContainer container;
143 	try
144 	{
145 	    container = stack.popp ();
146 	}
147 	catch (EmptyStackException ex)
148 	{
149 	    //	    System.out.println ("UndoStack is empty! No operation is taken back.");
150 	    return false;
151 	}
152 	switch (container.getOpCode())
153 	{
154 	case UNDO_ADDNODE :
155 	    {
156 		cc.d.delNode ((Node)container.getItems().firstElement ());
157 		redostack.push (container);
158 		break;
159 	    }
160 	case UNDO_ADDTRI :
161 	    {
162 		Tri tri = (Tri)container.getItems().elementAt (3);
163 		cc.d.delCell (tri);
164 		redostack.push (container);
165 		break;
166 	    }
167 	case UNDO_ADDQUAD :
168 	    {
169 		Quad quad = (Quad)container.getItems().elementAt (4);
170 		cc.d.delCell (quad);
171 		redostack.push (container);
172 		break;
173 	    }
174 	case UNDO_ADDMACRO :
175 	    {
176 		Macro macro = (Macro)container.getItems().elementAt (4);
177 		cc.d.delCell (macro);
178 		redostack.push (container);
179 		break;
180 	    }
181 	case UNDO_ADDLINE :
182 	    {
183 		SegmentLine line = (SegmentLine)container.getItems().firstElement ();
184 		cc.d.db.delSegment (line);
185 		cc.gc.gtk.updateBoundaryCombos ();
186 		redostack.push (container);
187 		break;
188 	    }
189 	case UNDO_ADDCIRCLE :
190 	    {
191 		SegmentCircle circle = (SegmentCircle)container.getItems().firstElement ();
192 		cc.d.db.delSegment (circle);
193 		cc.gc.gtk.updateBoundaryCombos ();
194 		redostack.push (container);
195 		break;
196 	    }
197 	case UNDO_DELETE :
198 	    {
199 		undoDelete (container);
200 		redostack.push (container);
201 		return true;
202 	    }
203 	case UNDO_SCALE :
204 	case UNDO_TRANSLATE :
205 	case UNDO_ROTATE :
206 	    {
207 		GridListener gl = parent.getDrawingArea ().getListener ();
208 		// prepare redo
209 		Vector info = new Vector ();
210 		info.add (gl.getSelector ().getHotspotMask ());
211 		Enumeration enum = container.getItemEnum ();
212 		while (enum.hasMoreElements ())
213 		{
214 		    GridItem item = (GridItem)enum.nextElement ();
215 		    Object[] obj = {item, item.getParameters()};
216 		    info.add (obj);
217 		}
218 		redostack.push (new UndoContainer (container.getOpCode(), container.getItems(), info));
219 		// perform undo
220 		gl.clearSelection ();
221   		enum = container.getItemEnum ();
222   		while (enum.hasMoreElements ())
223   		    ((GridItem)enum.nextElement()).setMarker ();
224   		gl.setSelectedItems (container.getItems ());
225 		info = (Vector)container.getInfo();
226   		gl.getSelector().setHotspotMask ((boolean[])info.firstElement());
227 		enum = info.elements ();
228 		enum.nextElement();
229 		while (enum.hasMoreElements ())
230 		{
231 		    Object[] obj = (Object[])enum.nextElement ();
232 		    GridItem item = (GridItem)obj[0];
233 		    double[] params = (double[])obj[1];
234 		    item.setParameters (params);
235 		}
236 		gl.calcPerimeter (false);
237 		return true;
238 	    }
239 	case UNDO_MIRROR :
240 	    {
241 		Object[] info = (Object[])container.getInfo ();
242 		GridListener gl = parent.getDrawingArea ().getListener ();
243 		gl.clearSelection ();
244 		Enumeration enum = container.getItemEnum ();
245 		while (enum.hasMoreElements ())
246 		    ((GridItem)enum.nextElement()).setMarker ();
247 		gl.setSelectedItems (container.getItems ());
248 		gl.getSelector().setHotspotMask ((boolean[])info[1]);
249 		int[] line = (int[])info[0];
250 		cc.gc.gtk.mirror (line[0], line[1], line[2], line[3]);
251 		gl.calcPerimeter (false);
252 		redostack.push (container);
253 		return true;
254 	    }
255 	case UNDO_CUT :
256 	    {
257 		undoDelete (container);
258 		GridCloner cloner = new GridCloner (container.getItems());
259 		parent.getDrawingArea().setCloner (cloner);
260 		cloner.createClone ();
261 		parent.getDrawingArea().getListener().storeCopyPasteAnchor ();
262 		redostack.push (container);
263 
264 		return true;
265 	    }
266 	case UNDO_PASTE :
267 	    {
268 		Enumeration enum = container.getItemEnum ();
269 		while (enum.hasMoreElements ())
270 		{
271 		    cc.d.del ((GridItem)enum.nextElement ());
272 		}
273 		GridCloner cloner = new GridCloner (container.getItems());
274 		parent.getDrawingArea().setCloner (cloner);
275 		cloner.createClone ();
276 		parent.getDrawingArea().getListener().storeCopyPasteAnchor ();
277 		redostack.push (container);
278 		break;
279 	    }
280 	case UNDO_PROPERTYNODE :
281 	    {
282 		Node n = (Node)container.getItems ().firstElement ();
283 		// prepare redo
284 		int[] info = new int[3];
285 		info[0] = n.getCoord (0);
286 		info[1] = n.getCoord (1);
287 		info[2] = n.getNPR ();
288 		redostack.push (new UndoContainer (UNDO_PROPERTYNODE, container.getItems(), info));
289 		// perform undo
290 		info = (int[])container.getInfo ();
291 		n.setCoord (info[0], info[1]);
292 		n.setNPR (info[2]);
293 		BoundaryNodeDialog dialog = (BoundaryNodeDialog)cc.dm.get (cc.dm.BOUNDARYNODEDIALOG);
294 		dialog.setSource (n);
295 		break;
296 	    }
297 	case UNDO_PROPERTYBNODE :
298 	    {
299 		BoundaryNode n = (BoundaryNode)container.getItems ().firstElement ();
300 		// prepare redo
301 		Object[] info = new Object[2];
302 		info[0] = n.getBoundary ();
303 		info[1] = new Double (n.getParaValue ());
304 		redostack.push (new UndoContainer (cc.um.UNDO_PROPERTYBNODE, container.getItems(), info));
305 		// perform undo
306 		info = (Object[])container.getInfo ();
307 		n.setBoundary ((Boundary)info[0]);
308 		n.setParaValue (((Double)info[1]).doubleValue ());
309 		n.updateBoundaryNode ();
310 		cc.d.updateNodeNumbers ();
311 		BoundaryNodeDialog dialog = (BoundaryNodeDialog)cc.dm.get (cc.dm.BOUNDARYNODEDIALOG);
312 		dialog.setSource (n);
313 		break;
314 	    }
315 	case UNDO_PROPERTYLINE :
316 	    {
317 		SegmentLine l = (SegmentLine)container.getItems ().firstElement ();
318 		// prepare redo
319 		int[] info = new int[4];
320 		info[0] = l.getStartPoint ()[0];
321 		info[1] = l.getStartPoint ()[1];
322 		info[2] = l.getEndPoint ()[0];
323 		info[3] = l.getEndPoint ()[1];
324 		redostack.push (new UndoContainer (cc.um.UNDO_PROPERTYLINE, container.getItems(), info));
325 		// perform undo
326 		info = (int[])container.getInfo ();
327 		l.setStartPoint (info[0], info[1]);
328 		l.setEndPoint (info[2], info[3]);
329 		LineDialog dialog = (LineDialog)cc.dm.get (cc.dm.LINEDIALOG);
330 		dialog.setSource (l);
331 		break;
332 	    }
333 	case UNDO_PROPERTYCIRC :
334 	    {
335 		SegmentCircle c = (SegmentCircle)container.getItems ().firstElement ();
336 		// prepare redo
337 		int[] info = new int[5];
338 		info[0] = c.getMidPoint ()[0];
339 		info[1] = c.getMidPoint ()[1];
340 		info[2] = c.getRadius ();
341 		info[3] = (int)c.getStartAngle ();
342 		info[4] = (int)c.getEndAngle ();
343 		redostack.push (new UndoContainer (cc.um.UNDO_PROPERTYCIRC, container.getItems(), info));
344 		// perform undo
345 		info = (int[])container.getInfo ();
346 		c.setMidPoint (info[0],info[1]);
347 		c.setRadius (info[2]);
348 		c.setStartAngle (info[3]);
349 		c.setEndAngle (info[4]);
350 		CircleDialog dialog = (CircleDialog)cc.dm.get (cc.dm.CIRCLEDIALOG);
351 		dialog.setSource (c);
352 		break;
353 	    }
354 	}
355 	return false;
356     }
357 
358 
359     /**
360      *  this method performs a redo step
361      *  @return true if hotspots need to be repainted
362      */
performRedo()363     public boolean performRedo ()
364     {
365 	UndoContainer container;
366 	try
367 	{
368 	    container = redostack.popp ();
369 	}
370 	catch (EmptyStackException ex)
371 	{
372 	    //	    System.out.println ("The RedoStack is empty! Note that the RedoStack is emptied every time an undoable action is performed.");
373 	    return false;
374 	}
375 	switch (container.getOpCode())
376 	{
377 	case UNDO_ADDNODE :
378 	    {
379 		// add node again
380 		cc.d.adjustNode ((Node)container.getItems().firstElement());
381 		stack.push (container);
382 		break;
383 	    }
384 	case UNDO_ADDTRI :
385 	    {
386 		Edge e1 = (Edge)container.getItems().elementAt (0);
387 		Edge e2 = (Edge)container.getItems().elementAt (1);
388 		Edge e3 = (Edge)container.getItems().elementAt (2);
389 		Tri tri = (Tri)container.getItems().elementAt (3);
390 		cc.d.adjustEdge (e1);
391 		cc.d.adjustEdge (e2);
392 		cc.d.adjustEdge (e3);
393 		cc.d.addCell (tri);
394 		stack.push (container);
395 		break;
396 	    }
397 	case UNDO_ADDQUAD :
398 	    {
399 		Edge e1 = (Edge)container.getItems().elementAt (0);
400 		Edge e2 = (Edge)container.getItems().elementAt (1);
401 		Edge e3 = (Edge)container.getItems().elementAt (2);
402 		Edge e4 = (Edge)container.getItems().elementAt (3);
403 		Quad quad = (Quad)container.getItems().elementAt (4);
404 		cc.d.adjustEdge (e1);
405 		cc.d.adjustEdge (e2);
406 		cc.d.adjustEdge (e3);
407 		cc.d.adjustEdge (e4);
408 		cc.d.addCell (quad);
409 		stack.push (container);
410 		break;
411 	    }
412 	case UNDO_ADDMACRO :
413 	    {
414 		Edge e1 = (Edge)container.getItems().elementAt (0);
415 		Edge e2 = (Edge)container.getItems().elementAt (1);
416 		Edge e3 = (Edge)container.getItems().elementAt (2);
417 		Edge e4 = (Edge)container.getItems().elementAt (3);
418 		Macro macro = (Macro)container.getItems().elementAt (4);
419 		cc.d.adjustEdge (e1);
420 		cc.d.adjustEdge (e2);
421 		cc.d.adjustEdge (e3);
422 		cc.d.adjustEdge (e4);
423 		cc.d.addCell (macro);
424 		stack.push (container);
425 		break;
426 	    }
427 	case UNDO_ADDLINE :
428 	    {
429 		SegmentLine line = (SegmentLine)container.getItems().firstElement ();
430 		// perform undo
431 		Boundary b = line.getBoundary ();
432 		if (!cc.d.db.isBoundary (b))
433 		    cc.d.db.addBoundary (b);
434 		cc.d.db.addSegment (b, line);
435 		cc.gc.gtk.updateBoundaryCombos ();
436 		stack.push (container);
437 		break;
438 	    }
439 	case UNDO_ADDCIRCLE :
440 	    {
441 		SegmentCircle circle = (SegmentCircle)container.getItems().firstElement ();
442 		Boundary b = circle.getBoundary ();
443 		if (!cc.d.db.isBoundary (b))
444 		    cc.d.db.addBoundary (b);
445 		cc.d.db.addSegment (b, circle);
446 		cc.gc.gtk.updateBoundaryCombos ();
447 		stack.push (container);
448 		break;
449 	    }
450 	case UNDO_DELETE :
451 	    {
452 		Enumeration enum = container.getItemEnum ();
453 		while (enum.hasMoreElements())
454 		    cc.d.del ((GridItem)enum.nextElement());
455 		stack.push (container);
456 		break;
457 	    }
458 	case UNDO_TRANSLATE :
459 	case UNDO_ROTATE :
460 	case UNDO_SCALE :
461 	    {
462 		GridListener gl = parent.getDrawingArea ().getListener ();
463 		// prepare undo
464 		Vector info = new Vector ();
465 		info.add (gl.getSelector ().getHotspotMask ());
466 		Enumeration enum = container.getItemEnum ();
467 		while (enum.hasMoreElements ())
468 		{
469 		    GridItem item = (GridItem)enum.nextElement ();
470 		    Object[] obj = {item, item.getParameters()};
471 		    info.add (obj);
472 		}
473 		stack.push (new UndoContainer (container.getOpCode(), container.getItems(), info));
474 		// perform redo
475 		gl.clearSelection ();
476   		enum = container.getItemEnum ();
477   		while (enum.hasMoreElements ())
478   		    ((GridItem)enum.nextElement()).setMarker ();
479   		gl.setSelectedItems (container.getItems ());
480 		info = (Vector)container.getInfo();
481   		gl.getSelector().setHotspotMask ((boolean[])info.firstElement());
482 		enum = info.elements ();
483 		enum.nextElement();
484 		while (enum.hasMoreElements ())
485 		{
486 		    Object[] obj = (Object[])enum.nextElement ();
487 		    GridItem item = (GridItem)obj[0];
488 		    double[] params = (double[])obj[1];
489 		    item.setParameters (params);
490 		}
491 		gl.calcPerimeter (false);
492 		return true;
493 	    }
494 	case UNDO_MIRROR :
495 	    {
496 		Object[] info = (Object[])container.getInfo ();
497 		GridListener gl = parent.getDrawingArea ().getListener ();
498 		gl.clearSelection ();
499 		Enumeration enum = container.getItemEnum ();
500 		while (enum.hasMoreElements ())
501 		    ((GridItem)enum.nextElement()).setMarker ();
502 		gl.setSelectedItems (container.getItems ());
503 		gl.getSelector().setHotspotMask ((boolean[])info[1]);
504 		int[] line = (int[])info[0];
505 		cc.gc.gtk.mirror (line[0], line[1], line[2], line[3]);
506 		gl.calcPerimeter (false);
507 		stack.push (container);
508 		return true;
509 	    }
510 	case UNDO_CUT :
511 	    {
512 		GridListener gl = parent.getDrawingArea ().getListener ();
513 		Enumeration enum = container.getItemEnum ();
514 		while (enum.hasMoreElements())
515 		    cc.d.del ((GridItem)enum.nextElement());
516 		stack.push (container);
517 		GridCloner cloner = new GridCloner (container.getItems());
518 		parent.getDrawingArea().setCloner (cloner);
519 		cloner.createClone ();
520 		parent.getDrawingArea().getListener().storeCopyPasteAnchor ();
521 		redostack.push (container);
522 		gl.calcPerimeter (false);
523 		return true;
524 	    }
525 	case UNDO_PASTE :
526 	    {
527 		GridListener gl = parent.getDrawingArea ().getListener ();
528 		undoDelete (container);
529 		GridCloner cloner = new GridCloner (container.getItems());
530 		parent.getDrawingArea().setCloner (cloner);
531 		cloner.createClone ();
532 		parent.getDrawingArea().getListener().storeCopyPasteAnchor ();
533 		redostack.push (container);
534 		stack.push (container);
535 		gl.calcPerimeter (false);
536 		break;
537 	    }
538 	case UNDO_PROPERTYNODE:
539 	    {
540 		Node n = (Node)container.getItems ().firstElement ();
541 		// prepare undo
542 		int[] info = new int[3];
543 		info[0] = n.getCoord (0);
544 		info[1] = n.getCoord (1);
545 		info[2] = n.getNPR ();
546 		stack.push (new UndoContainer (UNDO_PROPERTYNODE, container.getItems(), info));
547 		// perform redo
548 		info = (int[])container.getInfo ();
549 		n.setCoord (info[0], info[1]);
550 		n.setNPR (info[2]);
551 		BoundaryNodeDialog dialog = (BoundaryNodeDialog)cc.dm.get (cc.dm.BOUNDARYNODEDIALOG);
552 		dialog.setSource (n);
553 		break;
554 	    }
555 	case UNDO_PROPERTYBNODE:
556 	    {
557 		BoundaryNode n = (BoundaryNode)container.getItems ().firstElement ();
558 		// prepare undo
559 		Object[] info = new Object[2];
560 		info[0] = n.getBoundary ();
561 		info[1] = new Double (n.getParaValue ());
562 		redostack.push (new UndoContainer (cc.um.UNDO_PROPERTYBNODE, container.getItems(), info));
563 		// perform undo
564 		info = (Object[])container.getInfo ();
565 		n.setBoundary ((Boundary)info[0]);
566 		n.setParaValue (((Double)info[1]).doubleValue ());
567 		n.updateBoundaryNode ();
568 		cc.d.updateNodeNumbers ();
569 		BoundaryNodeDialog dialog = (BoundaryNodeDialog)cc.dm.get (cc.dm.BOUNDARYNODEDIALOG);
570 		dialog.setSource (n);
571 		break;
572 	    }
573 	case UNDO_PROPERTYLINE:
574 	    {
575 		SegmentLine l = (SegmentLine)container.getItems ().firstElement ();
576 		// prepare undo
577 		int[] info = new int[4];
578 		info[0] = l.getStartPoint ()[0];
579 		info[1] = l.getStartPoint ()[1];
580 		info[2] = l.getEndPoint ()[0];
581 		info[3] = l.getEndPoint ()[1];
582 		stack.push (new UndoContainer (cc.um.UNDO_PROPERTYLINE, container.getItems(), info));
583 		// perform redo
584 		info = (int[])container.getInfo ();
585 		l.setStartPoint (info[0], info[1]);
586 		l.setEndPoint (info[2], info[3]);
587 		LineDialog dialog = (LineDialog)cc.dm.get (cc.dm.LINEDIALOG);
588 		dialog.setSource (l);
589 		break;
590 	    }
591 	case UNDO_PROPERTYCIRC:
592 	    {
593 		SegmentCircle c = (SegmentCircle)container.getItems ().firstElement ();
594 		// prepare undo
595 		int[] info = new int[5];
596 		info[0] = c.getMidPoint ()[0];
597 		info[1] = c.getMidPoint ()[1];
598 		info[2] = c.getRadius ();
599 		info[3] = (int)c.getStartAngle ();
600 		info[4] = (int)c.getEndAngle ();
601 		stack.push (new UndoContainer (cc.um.UNDO_PROPERTYCIRC, container.getItems(), info));
602 		// perform redo
603 		info = (int[])container.getInfo ();
604 		c.setMidPoint (info[0],info[1]);
605 		c.setRadius (info[2]);
606 		c.setStartAngle (info[3]);
607 		c.setEndAngle (info[4]);
608 		CircleDialog dialog = (CircleDialog)cc.dm.get (cc.dm.CIRCLEDIALOG);
609 		dialog.setSource (c);
610 		break;
611 	    }
612 	}
613 	return false;
614     }
615 
616 
617     /**
618      *  outsourced because needed for CUT and DELETE
619      */
undoDelete(UndoContainer container)620     private void undoDelete (UndoContainer container)
621     {
622 	//	System.out.println ("undoing delete");
623 	//System.out.println ("separating deleted items into segs, elements, nodes");
624 	Vector nodes = new Vector ();
625 	Vector elems = new Vector ();
626 	Vector segs = new Vector ();
627 	Enumeration enum = container.getItemEnum ();
628 	while (enum.hasMoreElements ())
629 	{
630 	    GridItem next = (GridItem)enum.nextElement ();
631 	    if (next instanceof Node || next instanceof BoundaryNode)
632 		nodes.add (next);
633 	    if (next instanceof Cell2D)
634 		elems.add (next);
635 	    if (next instanceof Segment)
636 		segs.add (next);
637 	}
638 	//	System.out.println ("adding segs first");
639 	enum = segs.elements ();
640 	while (enum.hasMoreElements ())
641 	{
642 	    Segment s = (Segment)enum.nextElement ();
643 	    Boundary b = s.getBoundary ();
644 	    if (!cc.d.db.isBoundary (b))
645 		cc.d.db.addBoundary (b);
646 	    cc.d.db.addSegment (b, s);
647 	}
648 	//	System.out.println ("adding nodes next");
649 	enum = nodes.elements ();
650 	while (enum.hasMoreElements ())
651 	{
652 	    Node n = (Node)enum.nextElement ();
653 	    cc.d.adjustNode (n);
654 	}
655 	//	System.out.println ("adding edges extracted from elements");
656 	enum = elems.elements ();
657 	while (enum.hasMoreElements ())
658 	{
659 	    Cell2D elem = (Cell2D)enum.nextElement ();
660 	    Edge[] edges = elem.getEdges ();
661 	    for (int i=0; i<edges.length; i++)
662 		cc.d.adjustEdge (edges[i]);
663 	}
664 	//	System.out.println ("adding elements and finish");
665 	enum = elems.elements ();
666 	while (enum.hasMoreElements ())
667 	{
668 	    Cell2D elem = (Cell2D)enum.nextElement ();
669 	    cc.d.addCell (elem);
670 	}
671 	//	System.out.println ("done");
672 	// the newly added items become selected
673 	Object[] info = (Object[])container.getInfo ();
674 	GridListener gl = parent.getDrawingArea ().getListener ();
675 	gl.clearSelection ();
676 	enum = container.getItemEnum ();
677 	while (enum.hasMoreElements ())
678 	    ((GridItem)enum.nextElement()).setMarker();
679 	// and the GUI is repaired
680 	gl.setSelectedItems (container.getItems());
681 	gl.getSelector().setHotspotMask ((boolean[])info[0]);
682 	gl.calcPerimeter (false);
683 	cc.gc.workingBoundary = (Boundary)info[1];
684 	cc.gc.gtk.updateBoundaryCombos ();
685     }
686 
687 
688 
689     public static final int UNDO_ADDNODE       = 100000;
690     public static final int UNDO_ADDTRI        = 100010;
691     public static final int UNDO_ADDQUAD       = 100020;
692     public static final int UNDO_ADDMACRO      = 100030;
693     public static final int UNDO_ADDLINE       = 100040;
694     public static final int UNDO_ADDCIRCLE     = 100050;
695     public static final int UNDO_DELETE        = 100060;
696     public static final int UNDO_TRANSLATE     = 100070;
697     public static final int UNDO_ROTATE        = 100080;
698     public static final int UNDO_SCALE         = 100090;
699     public static final int UNDO_MIRROR        = 100100;
700     public static final int UNDO_CUT           = 100110;
701     public static final int UNDO_PASTE         = 100120;
702     public static final int UNDO_PROPERTYNODE  = 100130;
703     public static final int UNDO_PROPERTYBNODE = 100140;
704     public static final int UNDO_PROPERTYLINE  = 100150;
705     public static final int UNDO_PROPERTYCIRC  = 100160;
706 
707 
708 
709 
710 }
711 
712 
713 
714 
715