001    /**
002     * Created by IntelliJ IDEA.
003     * User: Wei Wang
004     * Date: May 7, 2003
005     * Time: 1:09:09 PM
006     */
007    
008    package EVolve.util.phasedetectors;
009    
010    import java.util.ArrayList;
011    import java.util.HashMap;
012    import java.util.HashSet;
013    import java.util.Iterator;
014    import java.util.Stack;
015    
016    import EVolve.Scene;
017    import EVolve.util.HelperFuncs;
018    import EVolve.util.phasedetectors.phasedetectorUI.PhaseDetectorToolBar;
019    import EVolve.visualization.AxesPanel;
020    
021    public class PhaseUndoRedo implements Cloneable{
022        public static final int singlePhase = 0x0, pastedPhases = 0x1;
023        public static final int triggeredPhases = 0x2, detectedPhases = 0x03;
024        public static final int entitySetPhases = 0x4;
025        private Stack undoStack, redoStack;
026        private PhaseFrame currentFrame;
027        private AxesPanel panel;
028    
029        public PhaseUndoRedo(AxesPanel panel) {
030            undoStack = new Stack();
031            redoStack = new Stack();
032            currentFrame = new PhaseFrame();
033            this.panel = panel;
034        }
035    
036        public void undo() {
037            PhaseDetectorToolBar toolbar = Scene.getUIManager().getPhaseDetectorToolBar();
038    
039            if (currentFrame.undoList.isEmpty()) {
040                redoStack.push(currentFrame);
041                currentFrame = (PhaseFrame)undoStack.pop();
042            } else {
043    
044                currentFrame.redoList.push(currentFrame.undoList.pop());
045                currentFrame.redoParams.push(currentFrame.undoParams.pop());
046    
047                if (currentFrame.undoList.isEmpty()&&!undoStack.isEmpty()) {
048                    redoStack.push(currentFrame);
049                    currentFrame = (PhaseFrame)undoStack.pop();
050                }
051            }
052            HashMap state = null;
053            if (!currentFrame.undoParams.isEmpty())
054                state = (HashMap)currentFrame.undoParams.peek();
055    
056            if (state != null)
057                toolbar.setToolbarParams(state);
058            update();
059        }
060    
061        public void redo() {
062            PhaseDetectorToolBar toolbar = Scene.getUIManager().getPhaseDetectorToolBar();
063            if (currentFrame.redoList.isEmpty()) {
064                undoStack.push(currentFrame);
065                currentFrame = (PhaseFrame)redoStack.pop();
066                if (currentFrame.undoList.isEmpty()&&!currentFrame.redoList.isEmpty()) {
067                    currentFrame.undoList.push(currentFrame.redoList.pop());
068                    currentFrame.undoParams.push(currentFrame.redoParams.pop());
069                }
070            } else {
071                currentFrame.undoList.push(currentFrame.redoList.pop());
072                currentFrame.undoParams.push(currentFrame.redoParams.pop());
073            }
074            HashMap state = null;
075            if (!currentFrame.undoParams.isEmpty())
076                state = (HashMap)currentFrame.undoParams.peek();
077    
078            if (state != null)
079                toolbar.setToolbarParams(state);
080            update();
081        }
082    
083        public boolean undoable() {
084            return !(currentFrame.undoList.isEmpty() && undoStack.isEmpty());
085        }
086    
087        public boolean redoable() {
088            return !(currentFrame.redoList.isEmpty() && redoStack.isEmpty());
089        }
090    
091        public void registerAction(Object action, int desc, boolean append) {
092            PhaseDetectorToolBar toolbar = Scene.getUIManager().getPhaseDetectorToolBar();
093            HashMap state = toolbar.getToolbarParams();
094            switch (desc) {
095                case singlePhase:
096                case pastedPhases:
097                    currentFrame.undoList.push(action);
098                    currentFrame.undoParams.push(state);
099                    currentFrame.redoList.clear();
100                    break;
101                case triggeredPhases:
102                case detectedPhases:
103                case entitySetPhases:
104                    if (!append) {
105                        undoStack.push(currentFrame);
106                        currentFrame.redoList.clear();
107                        currentFrame.redoParams.clear();
108                        currentFrame = new PhaseFrame();
109                    } else { // append
110                        currentFrame.redoList.clear();
111                        currentFrame.redoParams.clear();
112                    }
113                    currentFrame.undoParams.push(state);
114                    currentFrame.undoList.push(action);
115                    break;
116                default:
117                    Scene.showErrorMessage("Internal error occurred when register an action to Undo/Redo");
118                    break;
119            }
120            redoStack.clear();
121            Scene.getUIManager().getPhaseDetectorToolBar().enableButton(true);
122        }
123    
124        public void reset() {
125            undoStack.clear();
126            redoStack.clear();
127            currentFrame = new PhaseFrame();
128            panel.setPhases(null);
129        }
130    
131        public void update() {
132            ArrayList phases = getCurrentFramePhases();
133            panel.setPhases(phases);
134            panel.repaint();
135        }
136    
137        public ArrayList getCurrentFramePhases() {
138            HashSet tempPhases = new HashSet();
139            ArrayList phases = new ArrayList();
140    
141            if (currentFrame.undoList.isEmpty()) return phases;
142    
143            for (int i=0; i<currentFrame.undoList.size(); i++) {
144                Object action = currentFrame.undoList.get(i);
145                if (action instanceof ArrayList) {
146                    ArrayList temp = (ArrayList)action;
147                    for (int j=0; j<temp.size(); j++) {
148                        if (!tempPhases.contains(temp.get(j)))
149                            tempPhases.add(temp.get(j));
150                    }
151                } else {
152                    int aPhase = ((Integer)action).intValue();
153                    if (aPhase < 0) {// a removed phase
154                        if (tempPhases.contains(new Integer(-1*aPhase)))
155                            tempPhases.remove(new Integer(-1*aPhase));
156                    } else {
157                        if (!tempPhases.contains(action))
158                            tempPhases.add(action);
159                    }
160                }
161            }
162    
163            int list[] = new int[tempPhases.size()];
164            Iterator it = tempPhases.iterator();
165            int i=0;
166            while (it.hasNext()) {
167                list[i++] = ((Integer)it.next()).intValue();
168            }
169            // sort phases
170            int j=1,temp;
171            boolean done=false;
172            while((j<list.length)&&(!done)) {
173                done=true;
174                for(i=0;i<list.length-j;i++){
175                    if(list[i]>list[i+1]){
176                        done=false;
177                        temp=list[i];
178                        list[i]=list[i+1];
179                        list[i+1]=temp;
180                    }
181                }
182                j++;
183            }
184    
185            for (i=0; i<list.length; i++) {
186                phases.add(new Integer(list[i]));
187            }
188    
189            return phases;
190        }
191    
192        public void setPanel(AxesPanel panel) {
193            this.panel = panel;
194        }
195    
196        public Object clone() {
197            PhaseUndoRedo o = null;
198            try {
199                o = (PhaseUndoRedo)super.clone();
200            } catch (CloneNotSupportedException e) {
201                System.out.println(e.getStackTrace());
202                return o;
203            }
204    
205            o.undoStack = HelperFuncs.cloneStack(undoStack);
206            o.redoStack = HelperFuncs.cloneStack(redoStack);
207            o.currentFrame = (PhaseFrame)currentFrame.clone();
208            return o;
209        }
210    }