001    /*
002     * Created by IntelliJ IDEA.
003     * User: Wei Wang
004     * Date: 2002-9-6
005     * Time: 15:00:07
006     * To change template for new class use 
007     * Code Style | Class Templates options (Tools | IDE Options).
008     */
009    package EVolve.util.overlappers;
010    
011    import java.awt.Color;
012    import java.awt.Component;
013    import java.awt.event.ActionEvent;
014    import java.awt.event.ActionListener;
015    import java.awt.event.KeyEvent;
016    import java.awt.event.MouseAdapter;
017    import java.awt.event.MouseEvent;
018    import java.awt.event.MouseMotionAdapter;
019    import java.awt.image.BufferedImage;
020    import java.io.File;
021    import java.io.IOException;
022    import java.util.ArrayList;
023    import java.util.HashSet;
024    
025    import javax.imageio.ImageIO;
026    import javax.imageio.ImageWriter;
027    import javax.swing.JDialog;
028    import javax.swing.JFileChooser;
029    import javax.swing.JMenu;
030    import javax.swing.JMenuItem;
031    import javax.swing.JPanel;
032    import javax.swing.JPopupMenu;
033    import javax.swing.JScrollPane;
034    
035    import EVolve.Scene;
036    import EVolve.data.Entity;
037    import EVolve.data.EntityComparator;
038    import EVolve.exceptions.NoDataPlotException;
039    import EVolve.util.Magnifier;
040    import EVolve.visualization.AutoImage;
041    import EVolve.visualization.AxesPanel;
042    import EVolve.visualization.Dimension;
043    import EVolve.visualization.ReferenceDimension;
044    import EVolve.visualization.Visualization;
045    
046    public abstract class OverlapVisualization {
047        protected JDialog dialog;
048        protected JScrollPane panel;
049        protected AxesPanel canvas;
050        protected ArrayList visualizationList;
051        private String xAxisName,yAxisName;
052        protected EVolve.Window window;
053        protected long xMax;
054        protected ArrayList colorList;
055        protected HashSet[] fullEntitySet;
056        protected boolean noEntityAvailable;
057    
058        private JPopupMenu popup;
059        private JMenu menuSort;
060        private JMenuItem[][] itemSort;
061        private JMenu[] menuDimension;
062        private JMenuItem itemSave, itemScale;
063        private ArrayList refLocation;
064        private Magnifier magnifier;
065        private AutoImage overlappedImage;
066        private boolean shift_pressed;
067    
068    
069        public abstract void createDialog();
070    
071        public abstract boolean isOverlapable(Visualization visualToBeOverlapped);
072    
073        public abstract void overlappedVisualize();
074    
075        public OverlapVisualization() {
076            visualizationList = new ArrayList();
077    
078            fullEntitySet = new HashSet[2];
079            fullEntitySet[0] = null;
080            fullEntitySet[1] = null;
081            noEntityAvailable = false;
082            shift_pressed = false;
083    
084            panel = createPanel();
085            addPopupTrigger(canvas);
086        }
087    
088        public void showWindow() {
089            createDialog();
090            Scene.getUIManager().showDialog(dialog, dialog.getWidth(), dialog.getHeight());
091        }
092    
093        public void newOverlappedVisualization(OverlapVisualization oVisual) {
094            Visualization visual = (Visualization)visualizationList.get(0);
095            xAxisName = visual.getDimension()[0].getName();
096            yAxisName = visual.getDimension()[1].getName();
097            window = Scene.getUIManager().addOverlappedVisualization(oVisual);
098            createMenu();
099        }
100    
101        public JPanel getPanel() {
102            return canvas;
103        }
104    
105        private JScrollPane createPanel() {
106            canvas = new AxesPanel(AxesPanel.Axis_Enabled | AxesPanel.Flip_Image | AxesPanel.Scale_Image);
107            JScrollPane returnVal = new JScrollPane(canvas);
108    
109            magnifier = new Magnifier(true);
110            canvas.addMouseMotionListener(new MouseMotionAdapter() {
111                public void mouseMoved(MouseEvent e) {
112                    if (e.isShiftDown()) shift_pressed = true;
113                    else shift_pressed = false;
114    
115                    if (e.isAltDown()) {
116                        int x = canvas.getImageX(e.getX());
117                        int y = canvas.getImageY(e.getY());
118                        magnifier.convertMousePosition(canvas);
119                        magnifier.showWindow(canvas.getSubImage(x,y));
120                        canvas.drawZoomingArea(e.getX(),e.getY());
121                    }
122                    mMoved(e.getX(), e.getY());
123                }
124            });
125    
126            canvas.addMouseMotionListener(new MouseMotionAdapter() {
127                public void mouseDragged(MouseEvent e) {
128                    mMoved(e.getX(), e.getY());
129                }
130            });
131    
132            return returnVal;
133        }
134    
135        private void mMoved(int x, int y) {
136            int xIndex = canvas.getImageX(x);
137            int yIndex = canvas.getImageY(y);
138    
139            if (noEntityAvailable) {
140                Scene.setStatus("No entity information available when temporal viz overlapped.");
141            } else {
142                try {
143                    if (shift_pressed && (getOverlappedSortedColor(xIndex,yIndex)==null)) {
144                        Scene.setStatus("  ");
145                        return;
146                    }
147    
148                    if (fullEntitySet[0].size() == 0) {
149                        String hint = getEntityName(1,yIndex);
150                        if (hint != null) {
151                            Scene.setStatus(hint);
152                        }
153                    } else {
154                        String xHint = getEntityName(0,xIndex), yHint = getEntityName(1, yIndex);
155    
156                        if ((xHint != null) && (yHint != null)) {
157                            Scene.setStatus("X: " + xHint + "   Y: " + yHint);
158                        }
159                    }
160                } catch (Exception e) {
161                    System.out.println("Exception");
162                }
163            }
164        }
165    
166        private void createMenu() {
167            popup = new JPopupMenu();
168    
169            menuSort = new JMenu("Sort");
170            menuSort.setMnemonic(KeyEvent.VK_S);
171            menuSort.setEnabled(false);
172            popup.add(menuSort);
173    
174            ArrayList tempList = new ArrayList();
175            Visualization visual = (Visualization)visualizationList.get(visualizationList.size()-1);
176            EVolve.visualization.Dimension [] dimension = visual.getDimension();
177            refLocation = new ArrayList();
178            for (int i = 0; i < dimension.length; i++) {
179                if (dimension[i] instanceof ReferenceDimension) {
180                    tempList.add(new Integer(i));
181                    refLocation.add(new Integer(i));
182                }
183            }
184    
185            ReferenceDimension[] referenceDimension = new ReferenceDimension[tempList.size()];
186            menuDimension = new JMenu[tempList.size()];
187            itemSort = new JMenuItem[tempList.size()][];
188            for (int i = 0; i < tempList.size(); i++) {
189                int j = ((Integer)(tempList.get(i))).intValue();
190                referenceDimension[i] = (ReferenceDimension)(dimension[j]);
191                menuDimension[i] = new JMenu(visual.getDefinition().getDimensionDefinition()[j].getName());
192                menuSort.add(menuDimension[i]);
193            }
194    
195            for (int i = 0; i < referenceDimension.length; i++) {
196                ArrayList comparatorList = referenceDimension[i].getComparator();
197                itemSort[i] = new JMenuItem[comparatorList.size()];
198                menuDimension[i].removeAll();
199                for (int j = 0; j < itemSort[i].length; j++) {
200                    itemSort[i][j] = new JMenuItem(((EntityComparator)(comparatorList.get(j))).getName());
201                    itemSort[i][j].addActionListener(new ActionListener() {
202                        public void actionPerformed(ActionEvent e) {
203                            selectComparator(e);
204                        }
205                    });
206                    menuDimension[i].add(itemSort[i][j]);
207                }
208            }
209    
210            itemScale = new JMenuItem("Restore");
211            itemScale.setMnemonic(KeyEvent.VK_R);
212            itemScale.addActionListener(new ActionListener() {
213                public void actionPerformed(ActionEvent e) {
214                    if (e.getActionCommand().charAt(0) == 'F') {
215                        canvas.scaleImage(true);
216                        itemScale.setText("Restore");
217                        itemScale.setActionCommand("Restore");
218                        itemScale.setMnemonic(KeyEvent.VK_R);
219                    } else {
220                        canvas.scaleImage(false);
221                        itemScale.setText("Fit Window");
222                        itemScale.setActionCommand("Fit Window");
223                        itemScale.setMnemonic(KeyEvent.VK_F);
224                    }
225                    canvas.repaint();
226                }
227            });
228            itemScale.setSelected(true);
229            popup.add(itemScale);
230    
231            itemSave = new JMenuItem("Save...");
232            itemSave.setMnemonic(KeyEvent.VK_V);
233            itemSave.addActionListener(new ActionListener() {
234                public void actionPerformed(ActionEvent e) {
235                    save();
236                }
237            });
238            popup.add(itemSave);
239        }
240    
241        protected void showPopup(MouseEvent e) {
242            popup.show(e.getComponent(), e.getX(), e.getY());
243        }
244    
245        protected void addPopupTrigger(Component component) {
246            component.addMouseListener(new MouseAdapter() {
247                public void mouseReleased(MouseEvent e) {
248                    if (e.isPopupTrigger()) {
249                        showPopup(e);
250                    }
251                }
252    
253                public void mousePressed(MouseEvent e) {
254                    if (e.isPopupTrigger()) {
255                        showPopup(e);
256                    }
257                }
258            });
259        }
260    
261        protected void enableSortMenu() {
262            menuSort.setEnabled(true);
263            Scene.getUIManager().enableFileMenus();
264        }
265    
266        protected String getColorHex(Color color) {
267            String returnVal = Integer.toHexString(color.getBlue());
268            if (returnVal.length() < 2) {
269                returnVal = "0" + returnVal;
270            }
271            returnVal = Integer.toHexString(color.getGreen()) + returnVal;
272            if (returnVal.length() < 4) {
273                returnVal = "0" + returnVal;
274            }
275            returnVal = Integer.toHexString(color.getRed()) + returnVal;
276            if (returnVal.length() < 6) {
277                returnVal = "0" + returnVal;
278            }
279    
280            return returnVal;
281        }
282    
283        private void save() {
284            BufferedImage image = new BufferedImage(canvas.getWidth(), canvas.getHeight(), BufferedImage.TYPE_INT_RGB);
285            canvas.paint(image.getGraphics());
286            ImageWriter writer = (ImageWriter)(ImageIO.getImageWritersByFormatName("png").next());
287    
288            JFileChooser fc = new JFileChooser(Scene.getUIManager().getLastResultDir());
289    
290            if (fc.showSaveDialog(Scene.getFrame()) == JFileChooser.APPROVE_OPTION) {
291                File file = fc.getSelectedFile();
292                Scene.getUIManager().setLastResultDir(file.getPath());
293                try {
294                    writer.setOutput(ImageIO.createImageOutputStream(file));
295                    writer.write(image);
296                } catch (IOException e) {}
297            }
298    
299        }
300    
301        public AutoImage getSortImage() {
302            Visualization visual = null;
303            overlappedImage = new AutoImage();
304            ReferenceDimension sortedDimension[] = new ReferenceDimension[2];
305    
306            xMax = Integer.MIN_VALUE;
307    
308            for (int i=0; i<visualizationList.size(); i++) {
309                AutoImage image;
310                sortedDimension[0] = null;
311                sortedDimension[1] = null;
312    
313                visual = (Visualization)visualizationList.get(i);
314    
315                for (int j=0; j<2; j++) {
316                    Dimension dim = visual.getDimension()[j];
317                    if (dim instanceof ReferenceDimension)
318                        sortedDimension[j] = (ReferenceDimension)dim;
319                }
320                image = visual.getImage().getSortedImage(sortedDimension[0],sortedDimension[1]);
321                int w = image.getW();
322                int h = image.getH();
323    
324                for (int j=0; j<w; j++) {
325                    for (int k=0; k<h; k++) {
326                        if (image.getColor(j,k) == null) continue;
327    
328                        if (overlappedImage.getColor(j,k) == null )
329                            overlappedImage.setColor(j,k,image.getColor(j,k));
330                        else
331                            overlappedImage.setColor(j,k,new Color(153,0,153));
332                    }
333                }
334                visual.visualize();
335                if (xMax < visual.getxMax()) xMax = visual.getxMax();
336            }
337    
338            String[] comparatorName = new String[2];
339            for (int i=0; i<2; i++) {
340                if (visual.getDimension()[i] instanceof ReferenceDimension) {
341                    comparatorName[i] = ((ReferenceDimension)visual.getDimension()[i]).getSelectedComparatorName();
342                } else {
343                    comparatorName[i] = "";
344                }
345            }
346    
347            visual = (Visualization)visualizationList.get(0);
348    
349            canvas.setName(timeHeader(visual.getDimension()[0]) + xAxisName + " (" + ((fullEntitySet[0].size() == 0) ? xMax : fullEntitySet[0].size())+
350                                       ((comparatorName[0].length()==0) ? "" : ", "+ comparatorName[0]) + ")",
351                                       timeHeader(visual.getDimension()[1]) + yAxisName + " (" + fullEntitySet[1].size() +
352                                       ((comparatorName[1].length()==0) ? "" : ", "+ comparatorName[1]) + ")");
353            return overlappedImage;
354        }
355    
356        public void sort() {
357            try {
358                canvas.setImage(getSortImage().getImage());
359                canvas.repaint();
360            } catch (NoDataPlotException e) {
361                Scene.showErrorMessage(e.getMessage());
362            }
363        }
364    
365        private void selectComparator(ActionEvent e) {
366            for (int i = 0; i < itemSort.length; i++) {
367                for (int j = 0; j < itemSort[i].length; j++) {
368                    if (itemSort[i][j] == e.getSource()) {
369                        if (itemSort[i][j].getText().equals("Temporal")) {
370                            noEntityAvailable = true;
371                        } else {
372                            noEntityAvailable = false;
373                        }
374                        for (int k=0; k<visualizationList.size(); k++) {
375                            Visualization visual = (Visualization)visualizationList.get(k);
376                            ReferenceDimension ref = (ReferenceDimension)visual.getDimension()[((Integer)refLocation.get(i)).intValue()];
377                            ref.selectComparator(j);
378                        }
379                        sort();
380                        return;
381                    }
382                }
383            }
384        }
385    
386        public void unregisterOverlappedVisualization(Visualization visual) {
387            for (int i=0;i<visualizationList.size();i++) {
388                if (((Visualization)visualizationList.get(i)).getVisualizationID() == visual.getVisualizationID()) {
389                    visualizationList.remove(i);
390                }
391            }
392            if (visualizationList.size() ==1) visualizationList.clear();
393        }
394    
395        private String getEntityName(int dim,int index) {
396            Entity entity = null;
397            for (int i=0; i<visualizationList.size(); i++) {
398                Visualization visual = (Visualization)visualizationList.get(i);
399                if (!(visual.getDimension()[dim] instanceof ReferenceDimension)) return null;
400                ReferenceDimension ref = (ReferenceDimension)visual.getDimension()[dim];
401                entity = ref.getEntity(index);
402                if (entity != null) {
403                    break;
404                }
405            }
406    
407            return (entity == null) ? null : entity.getName();
408        }
409    
410        private Color getOverlappedSortedColor(int x, int y) {
411            Color returnVal = null;
412            ReferenceDimension sortedDimension[] = new ReferenceDimension[2];
413            for (int i=0; i<visualizationList.size(); i++) {
414                Visualization visual = (Visualization)visualizationList.get(i);
415                for (int j=0; j<2; j++) {
416                    Dimension dim = visual.getDimension()[j];
417                    if (dim instanceof ReferenceDimension)
418                        sortedDimension[j] = (ReferenceDimension)dim;
419                }
420                returnVal = (Color)visual.getImage().getSortedColor(sortedDimension[0],sortedDimension[1],x,y);
421                if (returnVal != null) break;
422            }
423    
424            return returnVal;
425        }
426    
427        private String timeHeader(Dimension dim) {
428            String property[] = dim.getDataFilter().getProperty();
429    
430            if (property == null) return "";
431    
432            for (int i=0; i<property.length; i++) {
433                if (property[i].equals("time"))
434                    return "Time - ";
435            }
436            return "";
437        }
438    
439        public void cleanup() {
440            fullEntitySet = null;
441            itemSort = null;
442            menuDimension = null;
443            magnifier.cleanup();
444        }
445    }