001    /**
002     * Created by IntelliJ IDEA.
003     * User: Wei Wang
004     * Date: Nov 27, 2002
005     * Time: 3:50:38 PM
006     */
007    
008    package EVolve.visualization.XYViz;
009    
010    import java.awt.*;
011    import java.awt.event.*;
012    import java.util.*;
013    import javax.swing.*;
014    import EVolve.Scene;
015    import EVolve.data.Entity;
016    import EVolve.data.Selection;
017    import EVolve.util.HelperFuncs;
018    import EVolve.util.Magnifier;
019    import EVolve.util.xmlutils.datastructures.SerializedVisualization;
020    import EVolve.util.painters.DefaultPainter;
021    import EVolve.util.painters.Painter;
022    import EVolve.util.phasedetectors.PhaseDetector;
023    import EVolve.util.sourcebrowser.SourceBrowser;
024    import EVolve.visualization.AutoImage;
025    import EVolve.visualization.AutoShapeImage;
026    import EVolve.visualization.AxesPanel;
027    import EVolve.visualization.ReferenceDimension;
028    import EVolve.visualization.Visualization;
029    import EVolve.visualization.VisualizationDefinition;
030    
031    public abstract class XYVisualization extends Visualization{
032        protected int autoInterval,interval;
033        protected long xMax, xOffset, currentThread;
034        protected boolean shift_pressed, flipMagnifier = true;
035        protected Painter painter;
036        protected Magnifier magnifier;
037        protected JMenuItem itemChangeOrientation,itemScale,itemBrowseSource,itemRecolor;
038        protected JMenuItem itemScaleX, itemScaleY;
039        protected boolean normalOrientation;
040        protected HashMap imageMap,threadDataSet;
041        protected SourceBrowser sourceBrowser;
042        protected AxesPanel canvas;
043        protected AutoImage image; // the image
044        protected ArrayList timeMap;
045        protected PhaseDetector phaseDetector;
046        protected boolean phaseDetectorEnabled;
047    
048        protected abstract String mouseMove(int x, int y);
049    
050        public XYVisualization() {
051            super();
052            shift_pressed = false;
053            autoInterval = -1;
054            interval = -1;
055            normalOrientation = true;
056            currentThread = -1;
057            imageMap = new HashMap();
058            threadDataSet = new HashMap();
059            sourceBrowser = new SourceBrowser();
060            timeMap = new ArrayList();
061            phaseDetectorEnabled = Scene.getVisualizationManager().isPhaseDetectorEnabled();
062        }
063    
064        protected Component createPanel() {
065            canvas = new AxesPanel(AxesPanel.Axis_Enabled | AxesPanel.Flip_Image | AxesPanel.Scale_Image);
066            flipMagnifier = true;
067            addMagnifier(canvas,flipMagnifier);
068            JScrollPane returnVal = new JScrollPane(canvas);
069            canvas.setParent(returnVal);
070    
071            return returnVal;
072        }
073    
074        protected void addMagnifier(Component aPanel, boolean flipImage) {
075            magnifier = new Magnifier(flipImage);
076            aPanel.addMouseMotionListener(new MouseMotionAdapter() {
077                public void mouseMoved(MouseEvent e) {
078    
079                    if (e.isShiftDown()) shift_pressed = true;
080                    else shift_pressed = false;
081    
082                    if (e.isAltDown()) {
083                        int x = e.getX(), y = e.getY();
084                        x = canvas.getImageX(x);
085                        y = canvas.getImageY(y);
086                        magnifier.convertMousePosition(canvas);
087                        magnifier.showWindow(canvas.getSubImage(x,y));
088                        canvas.drawZoomingArea(e.getX(),e.getY());
089                    }
090                    mouseMove(e.getX(), e.getY());
091                }
092    
093                public void mouseDragged(MouseEvent e) {
094                    if (e.isShiftDown()) shift_pressed = true;
095                    else shift_pressed = false;
096                    mouseMove(e.getX(), e.getY());
097                }
098            });
099    
100    
101            aPanel.addMouseListener(new MouseListener() {
102                public void mouseClicked(MouseEvent e) {
103                    mouseX = e.getX();
104                    mouseY = e.getY();
105                    freezed = false;
106                }
107    
108                public void mouseEntered(MouseEvent e) {}
109    
110                public void mouseExited(MouseEvent e) {}
111    
112                public void mousePressed(MouseEvent e) {}
113    
114                public void mouseReleased(MouseEvent e) {}
115            });
116    
117        }
118    
119        protected void updateConfiguration() {
120            if (panel instanceof JScrollPane)
121                ((AxesPanel)(((JScrollPane)panel)).getViewport().getView()).setImage(null);
122            else
123                ((AxesPanel)panel).setImage(null);
124            panel.repaint();
125    
126            normalOrientation = true;
127        }
128    
129        protected void createMenu() {
130            super.createMenu();
131            int flag = canvas.getFlag();
132    
133            if ((flag & 0xff000000) == 0) {
134                itemScale = new JMenuItem("Fit Visualization to Window");
135                itemScale.setMnemonic(KeyEvent.VK_F);
136            } else {
137                itemScale = new JMenuItem("Restore Visualization");
138                itemScale.setMnemonic(KeyEvent.VK_R);
139            }
140            itemScale.addActionListener(new ActionListener() {
141                public void actionPerformed(ActionEvent e) {
142                    if (e.getActionCommand().charAt(0) == 'F') {
143                        canvas.scaleImage(true);
144                        itemScale.setText("Restore Visualization");
145                        itemScale.setActionCommand("Restore Visualization");
146                        itemScale.setMnemonic(KeyEvent.VK_R);
147                    } else {
148                        canvas.scaleImage(false);
149                        itemScale.setText("Fit Visualization to Window");
150                        itemScale.setActionCommand("Fit Visualization to Window");
151                        itemScale.setMnemonic(KeyEvent.VK_F);
152                    }
153                    canvas.repaint();
154                }
155            });
156    
157    
158            if ((flag & 0xf0000000) == AxesPanel.Scale_X) {
159                itemScaleX = new JMenuItem("RestoreX axis");
160            } else {
161                itemScaleX = new JMenuItem("Fit X axis to Window");
162            }
163            itemScaleX.setMnemonic(KeyEvent.VK_X);
164            itemScaleX.addActionListener(new ActionListener() {
165                public void actionPerformed(ActionEvent e) {
166                    if (e.getActionCommand().charAt(0) == 'F') {
167                        int flag = canvas.getFlag();
168                        canvas.setPanelFlag(flag | AxesPanel.Scale_X);
169                        itemScaleX.setText("Restore X axis");
170                        itemScaleX.setActionCommand("Restore X axis");
171                        itemScaleX.setMnemonic(KeyEvent.VK_X);
172                    } else {
173                        int flag = canvas.getFlag();
174                        canvas.setPanelFlag(flag & ~AxesPanel.Scale_X);
175                        itemScaleX.setText("Fit X axis to Window");
176                        itemScaleX.setActionCommand("Fit X axis to Window");
177                        itemScaleX.setMnemonic(KeyEvent.VK_X);
178                    }
179                    canvas.repaint();
180                }
181            });
182    
183            if ((flag & 0x0f000000) == AxesPanel.Scale_Y) {
184                itemScaleY = new JMenuItem("Restore Y axis");
185            } else {
186                itemScaleY = new JMenuItem("Fit Y axis to Window");
187            }
188            itemScaleY.setMnemonic(KeyEvent.VK_Y);
189            itemScaleY.addActionListener(new ActionListener() {
190                public void actionPerformed(ActionEvent e) {
191                    if (e.getActionCommand().charAt(0) == 'F') {
192                        int flag = canvas.getFlag();
193                        canvas.setPanelFlag(flag | AxesPanel.Scale_Y);
194                        itemScaleY.setText("Restore Y axis");
195                        itemScaleY.setActionCommand("Restore Y axis");
196                        itemScaleY.setMnemonic(KeyEvent.VK_X);
197                    } else {
198                        int flag = canvas.getFlag();
199                        canvas.setPanelFlag(flag & ~AxesPanel.Scale_Y);
200                        itemScaleY.setText("Fit Y axis to Window");
201                        itemScaleY.setActionCommand("Fit Y axis to Window");
202                        itemScaleY.setMnemonic(KeyEvent.VK_Y);
203                    }
204                    canvas.repaint();
205                }
206            });
207    
208            itemBrowseSource = new JMenuItem("Browse source code...");
209            itemBrowseSource.setMnemonic(KeyEvent.VK_B);
210            itemBrowseSource.addActionListener(new ActionListener() {
211                public void actionPerformed(ActionEvent e) {
212                    sourceBrowser.showSourceFile(getEntityUnderMouse());
213                }
214            });
215            
216            itemRecolor = new JMenuItem("Recolor");
217            itemRecolor.setMnemonic(KeyEvent.VK_R);
218            itemRecolor.addActionListener(new ActionListener() {
219                public void actionPerformed(ActionEvent e) {
220                    Selection[] selections = Scene.getFilter().getSelection();
221                    boolean found = false;
222                    for (int i=0; i<selections.length; i++) {
223                        if (selections[i].getColor()!=null) {
224                            found = true;
225                            break;
226                        }
227                    }
228                    if (!found) {
229                        Scene.showErrorMessage("No selection is colored, can not recolor current visualization.");
230                        return;
231                    }
232                    Visualization visual = Scene.getVisualizationManager().getActiveVisualization();
233                    if (visual == null) return;
234                    if (image instanceof AutoShapeImage) {
235                        //reColorShapes();
236                        Scene.showErrorMessage("Can not recolor image with shapes.");
237                        return;
238                    } else
239                        reColor();
240                }
241            });
242    
243            popup.add(itemBrowseSource);
244            popup.add(itemScale);
245            popup.add(itemScaleX);
246            popup.add(itemScaleY);
247            popup.add(itemRecolor);
248            itemBrowseSource.setEnabled(false);
249        }
250    
251        public VisualizationDefinition getDefinition() {
252            return definition;
253        }
254    
255        public void restoreConfiguration(SerializedVisualization config) {
256            autoInterval = Integer.parseInt(config.Interval);
257            interval = autoInterval;
258            super.restoreConfiguration(config);
259        }
260    
261        public SerializedVisualization getCurrentConfiguration() {
262            SerializedVisualization data = super.getCurrentConfiguration();
263    
264            data.Interval = String.valueOf(interval);
265    
266            return data;
267        }
268    
269        public long getxMax() {
270            return xMax;
271        }
272    
273        public AutoImage getImage() {
274            return image;
275        }
276    
277        public void setImage(AutoImage image) {
278            this.image = image;
279        }
280    
281        public void disablePopupMenu() {
282            MenuElement[] menus = popup.getSubElements();
283            for (int i=0; i<menus.length; i++) {
284                if (((JMenuItem)menus[i]).getText().equals("Sort") ||
285                    ((JMenuItem)menus[i]).getText().equals("Save...") ||
286                    ((JMenuItem)menus[i]).getText().equals("Restore") ||
287                    ((JMenuItem)menus[i]).getText().equals("Fit Window"))
288                    continue;
289                ((JMenuItem)menus[i]).setEnabled(false);
290            }
291            Scene.getUIManager().disableFunctionMenus();
292        }
293    
294        protected void changeOrientation() {
295            AutoImage newImage = new AutoImage();
296            int wMax = image.getW();
297            int hMax = image.getH();
298            Color color;
299    
300            for (int i=0; i<wMax; i++) {
301                for (int j=0; j<hMax; j++) {
302                    color = (Color)image.getColor(i,j);
303                    if (color != null) {
304                        newImage.setColor(j,i,color);
305                    }
306                }
307            }
308            image = newImage;
309    
310            normalOrientation = ! normalOrientation;
311        }
312    
313        protected void switchThread(long threadId) {
314            if (currentThread != threadId) {
315                currentThread = threadId;
316                image = (AutoImage)imageMap.get(new Long(threadId));
317                if (image == null) {
318                    image = new AutoImage();
319                    imageMap.put(new Long(threadId),image);
320                }
321            }
322        }
323    
324        protected void installPainter() {
325            painter = new DefaultPainter();
326        }
327    
328        protected void enableBrowseSourceMenu() {
329            itemBrowseSource.setEnabled(true);
330        }
331    
332        protected void countEvents(long x) {
333            /*while (x/Math.abs(interval) >= eventCounter.size()) {
334                eventCounter.add(new Long(Scene.getEventCounter()));
335            }
336    
337            while (x/Math.abs(interval) >= timeCounter.size()) {
338                timeCounter.add(new Long(x));
339            }*/
340            long eventNo = Scene.getEventCounter();
341            long[] time2event = new long[2];
342            time2event[0] = x;
343            time2event[1] = eventNo;
344            while (x/Math.abs(interval) - xOffset >= timeMap.size()) {
345                timeMap.add(time2event);
346            }
347        }
348    
349        public void cleanup() {
350            super.cleanup();
351            magnifier.cleanup();
352        }
353    
354        public void enablePhaseDetector(boolean enabled) {
355            phaseDetectorEnabled = enabled;
356        }
357    
358        protected void reset() {
359            super.reset();
360            image = null;
361        }
362    
363        protected void dialogApply() {
364            super.dialogApply();
365            image = null;
366        }
367    
368        public PhaseDetector getPhaseDetector() {
369            return phaseDetector;
370        }
371    
372        public Point getMousePosition() {
373            return new Point(mouseX, mouseY);
374        }
375    
376        public void freeze(boolean flag) {
377            freezed = flag;
378        }
379    
380        public Object clone() {
381            XYVisualization o = null;
382    
383            o = (XYVisualization) super.clone();
384            o.image = (image == null) ? null : (AutoImage)image.clone();
385    
386            o.imageMap = HelperFuncs.cloneHashMap(imageMap);
387            o.itemChangeOrientation = null;
388            o.threadDataSet = HelperFuncs.cloneHashMap(threadDataSet);
389            o.sourceBrowser = (SourceBrowser)sourceBrowser.clone();
390            o.painter = (painter == null) ?null : (Painter)painter.clone();
391            o.itemBrowseSource = null;
392            o.itemChangeOrientation = null;
393            o.canvas = (AxesPanel)canvas.clone();
394            o.panel = new JScrollPane(o.canvas);
395            o.canvas.setParent((JScrollPane)o.panel);
396            o.addMagnifier(o.canvas,flipMagnifier);
397            o.addPopupTrigger(o.panel);
398            o.timeMap = new ArrayList();
399            for (int i=0; i<timeMap.size(); i++) {
400                long[] newValue = new long[2];
401                long[] oldValue = (long[])timeMap.get(i);
402                newValue[0] = oldValue[0];
403                newValue[1] = oldValue[1];
404                o.timeMap.add(newValue);
405            }
406            o.phaseDetector = null;
407            if (phaseDetector != null) {
408                o.phaseDetector = (PhaseDetector)phaseDetector.clone();
409                o.phaseDetector.setPanel((AxesPanel)((JScrollPane)o.getPanel()).getViewport().getView());
410            }
411            return o;
412        }
413        
414        public ArrayList getTimeMap() {
415            return timeMap;    
416        }
417        
418        public int getInterval() {
419            return interval;
420        }
421    
422        private void reColor() {
423            Selection[] selections = Scene.getFilter().getSelection();
424    
425            for (int i=0; i<2; i++) {
426                if (!(dimension[i] instanceof ReferenceDimension)) continue;
427                ReferenceDimension reference = (ReferenceDimension)dimension[i];
428    
429                HashMap entityName2Int = reference.getEntityName2IntMap();
430                for (int j=0; j<selections.length; j++) {
431                    Color color = selections[j].getColor();
432                    if (color == null) continue;
433    
434                    HashSet set = new HashSet();
435                    Entity[] selected = selections[j].getSelected();
436                    for (int k=0; k<selected.length; k++) {
437                        String entityName = selected[k].getName();
438                        if (entityName2Int.containsKey(entityName)) {
439                            set.add(entityName2Int.get(entityName));
440                        }
441                    }
442    
443                    fillColor(image.getW(), image.getH(), set, color, i==0);
444                }
445            }
446            sort();
447        }
448    
449        private void reColorShapes() {
450            Selection[] selections = Scene.getFilter().getSelection();
451            int w = image.getW();
452            int h = image.getH();
453    
454            for (int i=0; i<2; i++) {
455                if (!(dimension[i] instanceof ReferenceDimension)) continue;
456                ReferenceDimension reference = (ReferenceDimension)dimension[i];
457    
458                HashMap entityName2Int = reference.getEntityName2IntMap();
459                for (int j=0; j<selections.length; j++) {
460                    Color color = selections[j].getColor();
461                    if (color == null) continue;
462    
463                    HashSet set = new HashSet();
464                    Entity[] selected = selections[j].getSelected();
465                    for (int k=0; k<selected.length; k++) {
466                        String entityName = selected[k].getName();
467                        if (entityName2Int.containsKey(entityName)) {
468                            set.add(entityName2Int.get(entityName));
469                        }
470                    }
471                    for (int a=0; a<w; a++) {
472                        for (int b=0; b<h; b++) {
473                            ArrayList value = (ArrayList)image.getColor(a,b);
474                            if (value == null) continue;
475                            EVolve.util.painters.shapes.Shape shape = (EVolve.util.painters.shapes.Shape)value.get(0);
476                            if (set.contains(new Integer((int)shape.getEntityID())))
477                                shape.setColor(color);
478                        }
479                    }
480                }
481            }
482    
483            sort();
484        }
485    
486        private void fillColor(int width, int height, HashSet tobeFilled, Color color, boolean fillColumn) {
487            int loop1 = width, loop2 = height;
488            if (!fillColumn) {
489                loop1 = height;
490                loop2 = width;
491            }
492    
493            for (int w = 0; w<loop1; w++) {
494                if (!tobeFilled.contains(new Integer(w))) continue;
495    
496                for (int h = 0; h<loop2; h++) {
497                    if (fillColumn) {
498                        if (image.getColor(w,h)!=null)
499                            image.setColor(w,h,color);
500                    }
501                    else {
502                        if (image.getColor(h,w)!=null)
503                            image.setColor(h,w,color);
504                    }
505                }
506            }
507        }
508    
509        protected abstract String getEntityUnderMouse();
510    }