001    /**
002     * Created by IntelliJ IDEA.
003     * User: Wei Wang
004     * Date: Nov 27, 2002
005     * Time: 3:50:11 PM
006     */
007    
008    package EVolve.visualization;
009    
010    import EVolve.data.*;
011    import EVolve.Scene;
012    import EVolve.util.xmlutils.datastructures.SerializedVisualization;
013    import EVolve.visualization.VizFactory.VisualizationFactory;
014    import javax.swing.*;
015    import javax.imageio.*;
016    import java.awt.event.*;
017    import java.awt.image.BufferedImage;
018    import java.awt.*;
019    import java.util.*;
020    import java.io.*;
021    
022    public abstract class Visualization implements Cloneable{
023        public static final int SELECT_TIME_FRAME = 0x0001;
024        public static final int SELECT_OCCURRED_ENTITIES = 0x0010;
025        public static final int SELECT_ALL_ENTITIES = 0x0100;
026        public static final int SELECT_X_AXIS = 0x1000;
027        public static final int SELECT_Y_AXIS = 0x0100;
028        public static final int SELECT_ALL_X_AXIS = 0x0010;
029        public static final int SELECT_ALL_Y_AXIS = 0x0001;
030        protected String selectionName;
031    
032        protected String name; // name of the visualization
033        protected EVolve.Window window; // window where the visualization is displayed
034    
035        protected VisualizationDefinition definition; // definition of the visualization
036        protected ElementDefinition subjectDefinition; // definition of the subject
037    
038        protected Dimension[] dimension; // dimension of the visualization
039        protected Component panel; // panel to draw the visualization
040    
041        protected JDialog dialog; // configuration dialog
042        protected JPanel panelConfiguration; // configuration panel
043        protected JComboBox comboSubject; // subject selection
044        protected JComboBox[] comboDimension; // dimension selection
045        protected JComboBox[] comboSortSchemes; // dimension sort schemes
046        protected JTextField textName; // name input
047    
048        protected JPopupMenu popup; // popup menu
049        private JMenu menuSort;
050        private JMenu[] menuDimension;
051        protected JMenuItem[][] itemSort;
052        private JMenuItem itemConfigure,itemRename;
053        private JMenuItem itemSelect,itemCurrentSelection,itemSave;
054        private JMenuItem itemClone;
055        private ReferenceDimension[] referenceDimension;
056        private int linkageId;
057        private VisualizationFactory factory = null;
058        private static int vizIDPool = 0;
059        protected int dataSourceId;
060    
061        protected ElementDefinition[] elementDefinition; // definition of elements that can be used as subject
062        protected DataFilter[][][] dataFilter; // data filters that can be used by the dimensions
063        protected int mouseX, mouseY;
064    
065        protected boolean freezed;
066        private JDialog addSelection;
067        private JTextField textSelectionName;
068        private int numberOfSortableDimension;
069    
070        public Visualization() {
071            dimension = createDimension();
072            panel = createPanel();
073            panelConfiguration = null;
074            dialog = null;
075            linkageId = vizIDPool++;
076            addPopupTrigger(panel);
077            freezed = false;
078        }
079    
080        public String getName() {
081            return name;
082        }
083    
084        /**
085         * Sets the name of the visualization.
086         *
087         * @param  name  name of the visualization
088         */
089        public void setName(String name) {
090            this.name = name;
091        }
092    
093        /**
094         * Sets the window of the visualization.
095         *
096         * @param  window  window of the visualization
097         */
098        public void setWindow(EVolve.Window window) {
099            this.window = window;
100        }
101    
102        /**
103         * Gets the panel of the visualization.
104         *
105         * @return  panel of the visualization
106         */
107        public Component getPanel() {
108            return panel;
109        }
110    
111        /**
112         * Gets the additional configuration panel.
113         *
114         * @return  the additional configuration panel, null if not necessary
115         */
116        protected JPanel createConfigurationPanel() {
117            return null; // by default, return null, each visualization can override this
118        }
119    
120        protected void createMenu() {
121            popup = new JPopupMenu();
122    
123            itemConfigure = new JMenuItem("Configure...");
124            itemConfigure.setMnemonic(KeyEvent.VK_C);
125            itemConfigure.addActionListener(new ActionListener() {
126                public void actionPerformed(ActionEvent e) {
127                    configure();
128                }
129            });
130            popup.add(itemConfigure);
131    
132            itemRename = new JMenuItem("Rename...");
133            itemRename.setMnemonic(KeyEvent.VK_R);
134            itemRename.addActionListener(new ActionListener() {
135                public void actionPerformed(ActionEvent e) {
136                    String newName = JOptionPane.showInputDialog(Scene.getFrame(),"Enter a new name:",name);
137                    if (newName != null) {
138                        name = newName;
139                        window.setTitle(name+" - " + subjectDefinition.getName());
140                    }
141                }
142            });
143            popup.add(itemRename);
144    
145            itemSelect = new JMenuItem("Make Selection");
146            itemSelect.setMnemonic(KeyEvent.VK_M);
147            itemSelect.addActionListener(new ActionListener() {
148                public void actionPerformed(ActionEvent e) {
149                    makeSelection();
150                }
151            });
152            popup.add(itemSelect);
153    
154            itemCurrentSelection = new JMenuItem("Current Selection...");
155            itemCurrentSelection.setMnemonic(KeyEvent.VK_C);
156            itemCurrentSelection.addActionListener(new ActionListener() {
157                public void actionPerformed(ActionEvent e) {
158                    Scene.getFilter().load();
159                }
160            });
161            popup.add(itemCurrentSelection);
162    
163            menuSort = new JMenu("Sort");
164            menuSort.setMnemonic(KeyEvent.VK_S);
165            menuSort.setEnabled(false);
166            popup.add(menuSort);
167    
168            ArrayList tempList = new ArrayList();
169            for (int i = 0; i < dimension.length; i++) {
170                if ((dimension[i] instanceof ReferenceDimension)&&((ReferenceDimension)dimension[i]).isSortable()) {
171                    tempList.add(new Integer(i));
172                }
173            }
174    
175            referenceDimension = new ReferenceDimension[tempList.size()];
176            menuDimension = new JMenu[tempList.size()];
177            itemSort = new JMenuItem[tempList.size()][];
178            for (int i = 0; i < tempList.size(); i++) {
179                int j = ((Integer)(tempList.get(i))).intValue();
180                referenceDimension[i] = (ReferenceDimension)(dimension[j]);
181                menuDimension[i] = new JMenu(definition.getDimensionDefinition()[j].getName());
182                menuSort.add(menuDimension[i]);
183            }
184    
185            itemClone = new JMenuItem("Clone");
186            itemClone.setMnemonic(KeyEvent.VK_C);
187            itemClone.addActionListener(new ActionListener() {
188                public void actionPerformed(ActionEvent e) {
189                    Scene.getVisualizationManager().cloneVisualization();
190                }
191            });
192            popup.add(itemClone);
193    
194            itemSave = new JMenuItem("Save Image...");
195            itemSave.setMnemonic(KeyEvent.VK_V);
196            itemSave.addActionListener(new ActionListener() {
197                public void actionPerformed(ActionEvent e) {
198                    save();
199                }
200            });
201            popup.add(itemSave);
202        }
203    
204        private void showPopup(MouseEvent e) {
205            mouseX = e.getX();
206            mouseY = e.getY();
207            Rectangle rect = e.getComponent().getBounds();
208            Rectangle rect2 = popup.getBounds();
209            int posX = mouseX, posY = mouseY;
210            if (mouseY+rect2.height > rect.height)
211                posY = posY - rect2.height;
212            if (mouseX+rect2.width>rect.width)
213                posX = posX - rect2.width;
214                popup.show(e.getComponent(), posX, posY);
215        }
216    
217        /**
218         * Sets the definition of the visualization, called by visualization manager after the visualization is created.
219         *
220         * @param  definition  definition of the visualization
221         */
222        public void setDefinition(VisualizationDefinition definition) {
223            panelConfiguration = createConfigurationPanel();
224    
225            this.definition = definition;
226    
227            elementDefinition = Scene.getDataManager().getElementDefinition(definition);
228    
229            dataFilter = new DataFilter[elementDefinition.length][definition.getDimensionDefinition().length][];
230            for (int i = 0; i < dataFilter.length; i++) {
231                for (int j = 0; j < dataFilter[i].length; j++) {
232                    dataFilter[i][j] = Scene.getDataManager().getDataFilter(elementDefinition[i],definition.getDimensionDefinition()[j].getProperty());
233                    for (int k = 0; k < dataFilter[i][j].length; k++) {
234                        assert (((dataFilter[i][j][k].getTargetType() != -1) && (dimension[j] instanceof ReferenceDimension)) || ((dataFilter[i][j][k].getTargetType() == -1) && (dimension[j] instanceof ValueDimension))) : "Incompatible dimension type.";
235                    }
236                }
237            }
238    
239            subjectDefinition = elementDefinition[0];
240            for (int i = 0; i < dimension.length; i++) {
241                dimension[i].setDataFilter(dataFilter[0][i][0]);
242            }
243    
244            createDialog();
245            updateConfiguration();
246    
247            createMenu();
248        }
249    
250        /**
251         * Gets the definition of the subject.
252         *
253         * @return  definition of the subject
254         */
255        public ElementDefinition getSubjectDefinition() {
256            return subjectDefinition;
257        }
258    
259        /**
260         * Configures the visualization.
261         */
262        public void configure() {
263            if (dialog == null) {
264                createDialog();
265            }
266            dialog.pack();
267            Scene.getUIManager().showDialog(dialog, dialog.getWidth(), dialog.getHeight());
268        }
269    
270        /**
271         * Save visualizations as disk file
272         */
273        public void save() {
274            Component target = panel;
275            if (target instanceof JScrollPane)
276                target = ((JScrollPane)panel).getViewport().getView();
277    
278            BufferedImage image = new BufferedImage(target.getWidth(), target.getHeight(), BufferedImage.TYPE_INT_RGB);
279            target.paint(image.getGraphics());
280            ImageWriter writer = (ImageWriter)(ImageIO.getImageWritersByFormatName("png").next());
281    
282            JFileChooser fc = new JFileChooser(Scene.getUIManager().getLastResultDir());
283            fc.setFileFilter(new javax.swing.filechooser.FileFilter() {
284                public String getDescription() {
285                    return "PNG Files";
286                }
287    
288                public boolean accept(File f) {
289                    return f.getName().substring(f.getName().lastIndexOf('.') + 1).toLowerCase().equals("png");
290                }
291            });
292    
293            if (fc.showSaveDialog(Scene.getFrame()) == JFileChooser.APPROVE_OPTION) {
294                File file = fc.getSelectedFile();
295                Scene.getUIManager().setLastResultDir(file.getPath());
296                try {
297                    writer.setOutput(ImageIO.createImageOutputStream(file));
298                    writer.write(image);
299                } catch (IOException e) {}
300            }
301        }
302    
303        /**
304         * Creates the configuration dialog.
305         */
306        protected void createDialog() {
307            dialog = new JDialog(Scene.getFrame(), "Configure", true);
308    
309            JPanel panelTitle = new JPanel(new FlowLayout());
310            dialog.getContentPane().add(panelTitle, BorderLayout.NORTH);
311    
312            panelTitle.add(new JLabel("Title: "));
313    
314            textName = new JTextField(name, 12);
315            panelTitle.add(textName);
316    
317            JPanel panelMain = new JPanel(new BorderLayout());
318            panelMain.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Choose subject & dimensions"));
319            dialog.getContentPane().add(panelMain, BorderLayout.CENTER);
320    
321            numberOfSortableDimension = 0;
322            for (int i=0; i<dimension.length; i++) {
323                if ((dimension[i] instanceof ReferenceDimension)&&((ReferenceDimension)dimension[i]).isSortable())
324                    numberOfSortableDimension++;
325            }
326    
327            JPanel panelName = new JPanel(new GridLayout(definition.getDimensionDefinition().length + 1 + numberOfSortableDimension, 1, 5, 5));
328            panelMain.add(panelName, BorderLayout.WEST);
329    
330            panelName.add(new JLabel(" Subject:      "));
331            for (int i = 0; i < definition.getDimensionDefinition().length; i++) {
332                panelName.add(new JLabel(" " + definition.getDimensionDefinition()[i].getName() + ":      "));
333                if ((dimension[i] instanceof ReferenceDimension)&&(((ReferenceDimension)dimension[i]).isSortable()))
334                    panelName.add(new JLabel(" Sort "+ definition.getDimensionDefinition()[i].getName() + " By :  "));
335            }
336    
337            JPanel panelCombo = new JPanel(new GridLayout(definition.getDimensionDefinition().length + 1 + numberOfSortableDimension, 1, 5, 5));
338            panelMain.add(panelCombo, BorderLayout.CENTER);
339    
340            comboSubject = new JComboBox();
341            for (int i = 0; i < elementDefinition.length; i++) {
342                comboSubject.addItem(elementDefinition[i].getName());
343            }
344            comboSubject.addActionListener(new ActionListener() {
345                public void actionPerformed(ActionEvent e) {
346                    updateComboSubject();
347                }
348            });
349            panelCombo.add(comboSubject);
350    
351            comboDimension = new JComboBox[definition.getDimensionDefinition().length];
352            int k = 0;
353            comboSortSchemes = new JComboBox[numberOfSortableDimension];
354            for (int i = 0; i < comboDimension.length; i++) {
355                comboDimension[i] = new JComboBox();
356                comboDimension[i].addActionListener(new ActionListener() {
357                    public void actionPerformed(ActionEvent e) {
358                        updateComboDimension();
359                    }
360                });
361                panelCombo.add(comboDimension[i]);
362                if ((dimension[i] instanceof ReferenceDimension)&&(k<numberOfSortableDimension)) {
363                    comboSortSchemes[k] = new JComboBox();
364                    panelCombo.add(comboSortSchemes[k]);
365                    k++;
366                }
367            }
368    
369            updateComboSubject();
370    
371            if (panelConfiguration != null) {
372                panelMain.add(panelConfiguration, BorderLayout.SOUTH);
373            }
374    
375            JPanel panelButton = new JPanel(new FlowLayout());
376            dialog.getContentPane().add(panelButton, BorderLayout.SOUTH);
377    
378            JButton buttonApply = new JButton("Apply");
379            buttonApply.addActionListener(new ActionListener() {
380                public void actionPerformed(ActionEvent e) {
381                    dialogApply();
382                }
383            });
384            panelButton.add(buttonApply);
385    
386            JButton buttonCancel = new JButton("Cancel");
387            buttonCancel.addActionListener(new ActionListener() {
388                public void actionPerformed(ActionEvent e) {
389                    dialogCancel();
390                }
391            });
392            panelButton.add(buttonCancel);
393    
394            //*************
395            for (int i=0; i<comboSubject.getItemCount(); i++) {
396                if ((comboSubject.getItemAt(i)).equals(subjectDefinition.getName())) {
397                    comboSubject.setSelectedIndex(i);
398                    break;
399                }
400            }
401            for (int i=0;i<comboDimension.length;i++) {
402                for (int j =0 ; j<comboDimension[i].getItemCount();j++) {
403                    if (comboDimension[i].getItemAt(j).equals(dimension[i].getDataFilter().getName())) {
404                        comboDimension[i].setSelectedIndex(j);
405                        break;
406                    }
407                }
408            }
409        }
410    
411        /**
412         * Updates the subject combo-box.
413         */
414        protected void updateComboSubject() {
415            comboSubject.setToolTipText(elementDefinition[comboSubject.getSelectedIndex()].getDescription());
416            for (int i = 0; i < comboDimension.length; i++) {
417                comboDimension[i].removeAllItems();
418                for (int j = 0; j < dataFilter[comboSubject.getSelectedIndex()][i].length; j++) {
419                    comboDimension[i].addItem(dataFilter[comboSubject.getSelectedIndex()][i][j].getName());
420                }
421            }
422            updateComboDimension();
423    
424        }
425    
426        /**
427         * Updates the dimension combo-boxes.
428         */
429        protected void updateComboDimension() {
430            for (int i = 0; i < comboDimension.length; i++) {
431                if (comboDimension[i].getSelectedIndex() != -1) {
432                    comboDimension[i].setToolTipText(dataFilter[comboSubject.getSelectedIndex()][i][comboDimension[i].getSelectedIndex()].getDescription());
433                    dimension[i].setDataFilter(dataFilter[comboSubject.getSelectedIndex()][i][comboDimension[i].getSelectedIndex()]);
434                }
435            }
436    
437            if (numberOfSortableDimension == 0)  return;
438    
439            int k=0;
440            for (int i=0; i<dimension.length; i++) {
441                if ((dimension[i] instanceof ReferenceDimension)&&(k<numberOfSortableDimension)) {
442                    ArrayList schemes = ((ReferenceDimension)dimension[i]).getAvailableSortSchemes();
443                    String selected ="";
444                    if (comboSortSchemes[k].getSelectedIndex()!= -1)
445                        selected = comboSortSchemes[k].getSelectedItem().toString();
446                    int selIndex = 0;
447                    comboSortSchemes[k].removeAllItems();
448                    for (int n=0; n<schemes.size(); n++) {
449                        comboSortSchemes[k].addItem(schemes.get(n));
450                        if (schemes.get(n).equals(selected)) {
451                            selIndex = n;
452                        }
453                    }
454                    comboSortSchemes[k].setSelectedIndex(selIndex);
455                    k++;
456                }
457            }
458        }
459    
460        /**
461         * Button "Apply" is clicked.
462         */
463        protected void dialogApply() {
464            dialog.setVisible(false);
465            subjectDefinition = elementDefinition[comboSubject.getSelectedIndex()];
466            name = textName.getText();
467            if (name.indexOf(subjectDefinition.getName()) == -1)
468                window.setTitle(name + " - " + subjectDefinition.getName());
469            else
470                window.setTitle(name);
471            reset();
472            updateConfiguration();
473        }
474    
475        /**
476         * Button "Cancel" is clicked.
477         */
478        protected void dialogCancel() {
479            dialog.setVisible(false);
480        }
481    
482        public void updateMenu() {
483            if (referenceDimension.length == 0) {
484                menuSort.setVisible(false);
485                return;
486            }
487            for (int i = 0; i < referenceDimension.length; i++) {
488                ArrayList comparatorList = referenceDimension[i].getComparator();
489                itemSort[i] = new JMenuItem[comparatorList.size()];
490                menuDimension[i].removeAll();
491                for (int j = 0; j < itemSort[i].length; j++) {
492                    itemSort[i][j] = new JMenuItem(((EntityComparator)(comparatorList.get(j))).getName());
493                    itemSort[i][j].addActionListener(new ActionListener() {
494                        public void actionPerformed(ActionEvent e) {
495                            selectComparator(e);
496                        }
497                    });
498                    menuDimension[i].add(itemSort[i][j]);
499                }
500            }
501    
502            ArrayList menuOptional = createOptionalMenu();
503            if (menuOptional == null ) return;
504            for (int i=0; i<menuOptional.size(); i++)
505                popup.add((JMenuItem)menuOptional.get(i));
506        }
507    
508        protected ArrayList createOptionalMenu() {
509            return null;
510        }
511    
512        public void selectComparator(ActionEvent e) {
513            for (int i = 0; i < itemSort.length; i++) {
514                for (int j = 0; j < itemSort[i].length; j++) {
515                    if (itemSort[i][j] == e.getSource()) {
516                        referenceDimension[i].selectComparator(j);
517                        sort();
518                        i = itemSort.length+1;
519                        break;
520                    }
521                }
522            }
523    
524            //synchronize sort combox here:
525            int k=0;
526            for (int i=0; i<dimension.length; i++) {
527                if ((dimension[i] instanceof ReferenceDimension)&&(k<numberOfSortableDimension)) {
528                    for (int j=0; j<comboSortSchemes[k].getItemCount(); j++) {
529                        if (comboSortSchemes[k].getItemAt(j).equals(((ReferenceDimension)dimension[i]).getSelectedComparatorName())) {
530                            comboSortSchemes[k].setSelectedIndex(j);
531                            break;
532                        }
533                    }
534                    k++;
535                }
536            }
537        }
538    
539        protected void addPopupTrigger(Component component) {
540            Component target = component;
541            if (target instanceof JScrollPane)
542                target = ((JScrollPane)target).getViewport().getView();
543    
544            target.addMouseListener(new MouseAdapter() {
545                public void mouseReleased(MouseEvent e) {
546                    if (e.isPopupTrigger()) {
547                        showPopup(e);
548                    }
549                }
550    
551                public void mousePressed(MouseEvent e) {
552                    if (e.isPopupTrigger()) {
553                        showPopup(e);
554                    }
555                }
556            });
557        }
558    
559        public void enableSortMenu() {
560            menuSort.setEnabled(true);
561        }
562    
563        /**
564         * Creates the dimensions.
565         *
566         * @return  the dimensions
567         */
568        public abstract Dimension[] createDimension();
569    
570        /**
571         * Creates available selection menu items.
572         *
573         * @return  the array of selection option checkboxes
574         */
575        public abstract JCheckBox[] createSelectionOptions();
576    
577        /**
578         * Creates the panel.
579         *
580         * @return  the panel
581         */
582        protected abstract Component createPanel();
583    
584        /**
585         * Updates the configuration.
586         */
587        protected abstract void updateConfiguration();
588    
589        /**
590         * Gets ready for receiving data.
591         */
592        public abstract void preVisualize();
593    
594        /**
595         * Receives data.
596         *
597         * @param  data  the data
598         */
599        protected abstract void receiveElement(Element element);
600    
601        /**
602         * Visualizes after receiving data.
603         */
604        public abstract void visualize();
605    
606        /**
607         * sorting the visualization with selected comparator
608         */
609        public abstract void sort();
610    
611        /**
612         * according to user selectiong, get a data subset
613         */
614        public abstract void makeSelection();
615    
616        /**
617         *
618         * @return a data structure contains all current visualization's configure
619         */
620        public SerializedVisualization getCurrentConfiguration() {
621            SerializedVisualization data = new SerializedVisualization();
622            Rectangle rect = window.getBounds();
623    
624            data.FactoryName = getFactory().getName();
625            data.SubjectName = subjectDefinition.getName();
626            data.VisualizationName = name;
627            data.WindowTitle = window.getTitle();
628            data.WindowX = String.valueOf(rect.x);
629            data.WindowY = String.valueOf(rect.y);
630            data.WindowWidth = String.valueOf(rect.width);
631            data.WindowHeight = String.valueOf(rect.height);
632            data.Interval = "-1";
633    
634            return data;
635        }
636    
637        /**
638         * following are all interfaces needed for predefined viz
639         */
640        public void restoreConfiguration(SerializedVisualization config) {
641            int selectedSubjectId = -1;
642    
643            for (int i=0; i< elementDefinition.length; i++) {
644                if (elementDefinition[i].getName().equals(config.SubjectName)) {
645                    subjectDefinition = elementDefinition[i];
646                    comboSubject.setSelectedIndex(i);
647                    selectedSubjectId = i;
648                    break;
649                }
650            }
651    
652            String dimDefinition[] = new String[3];
653            dimDefinition[0] = config.xAxis;
654            dimDefinition[1] = config.yAxis;
655            dimDefinition[2] = config.zAxis;
656            for (int i=0; i<dimension.length; i++) {
657                for (int j=0; j< dataFilter[selectedSubjectId][i].length;j++) {
658                    if (dataFilter[selectedSubjectId][i][j].getName().equals(dimDefinition[i])) {
659                        dimension[i].setDataFilter(dataFilter[selectedSubjectId][i][j]);
660                        break;
661                    }
662                }
663            }
664    
665            for (int i=0; i<comboDimension.length; i++) {
666                for (int j=0; j<comboDimension[i].getItemCount(); j++) {
667                    if (comboDimension[i].getItemAt(j).equals(dimDefinition[i])) {
668                        comboDimension[i].setSelectedIndex(j);
669                    }
670                }
671            }
672            updateComboDimension();
673    
674            String sortScheme[] = new String[3];
675            sortScheme[0] = config.xAxisSortScheme;
676            sortScheme[1] = config.yAxisSortScheme;
677            sortScheme[2] = config.zAxisSortScheme;
678            int k = 0;
679            for (int i=0; i<dimension.length; i++) {
680                if ((sortScheme[i] != null)&&(sortScheme[i].length() > 0)&&(k<numberOfSortableDimension)) {
681                    for (int j=0; j<comboSortSchemes[k].getItemCount(); j++) {
682                        if (sortScheme[i].equals(comboSortSchemes[k].getItemAt(j).toString())) {
683                            comboSortSchemes[k].setSelectedIndex(j);
684    
685                        }
686                    }
687                    k++;
688                }
689            }
690    
691    
692            window.setTitle(config.WindowTitle);
693            updateConfiguration();
694            menuSort.setEnabled(false);
695        }
696    
697        public EVolve.Window getWindow() {
698            return window;
699        }
700    
701        public void setFactory(VisualizationFactory factory) {
702            this.factory = factory;
703        }
704    
705        public VisualizationFactory getFactory() {
706            return factory;
707        }
708    
709        public void autoSave(String path, String dataFn) {
710            Component target = panel;
711            if (target instanceof JScrollPane)
712                target = ((JScrollPane)panel).getViewport().getView();
713    
714            BufferedImage image = new BufferedImage(target.getWidth(), target.getHeight(), BufferedImage.TYPE_INT_RGB);
715            target.paint(image.getGraphics());
716            ImageWriter writer = (ImageWriter)(ImageIO.getImageWritersByFormatName("png").next());
717    
718            try {
719                RandomAccessFile file = new RandomAccessFile((path+File.separator+
720                        dataFn.substring(dataFn.lastIndexOf(File.separator)+1,dataFn.length()-4)+".png"),"rw");
721                writer.setOutput(ImageIO.createImageOutputStream(file));
722                writer.write(image);
723            } catch (IOException e) {
724                System.out.println("writing file error.");
725            }
726    
727        }
728    
729        /**
730         * following methods are used in unify/overlap viz
731         */
732        public abstract ReferenceDimension getLinkableDimension(int dim);
733    
734        public int getVisualizationID() {
735            return linkageId;
736        }
737    
738        public Dimension[] getDimension() {
739            return dimension;
740        }
741    
742        public VisualizationDefinition getDefinition() {
743            return definition;
744        }
745    
746        public long getxMax() {
747            return -1;
748        }
749    
750        public AutoImage getImage() {
751            return null;
752        }
753    
754        public void setImage(AutoImage image) {
755            return;
756        }
757    
758        public void cleanup() {
759            dimension = null;
760            comboDimension = null;
761            menuDimension = null;
762            itemSort = null;
763            referenceDimension = null;
764            elementDefinition = null;
765            dataFilter = null;
766        }
767    
768        public int switchOption(boolean turn_on, int option, int add_on_option) {
769            int returnVal;
770            if (turn_on)
771                returnVal = option | add_on_option;
772            else
773                returnVal = option & ~add_on_option;
774            return returnVal;
775        }
776    
777        public void setDataSourceId(int dataSourceId) {
778            this.dataSourceId = dataSourceId;
779        }
780    
781        public int getDataSourceId() {
782            return dataSourceId;
783        }
784    
785        protected void reset() {
786            for (int i = 0; i < dimension.length; i++) {
787                int selected = comboDimension[i].getSelectedIndex();
788                if (selected < dataFilter[comboSubject.getSelectedIndex()][i].length)
789                    dimension[i].setDataFilter(dataFilter[comboSubject.getSelectedIndex()][i][selected]);
790                if (dimension[i] instanceof ReferenceDimension) ((ReferenceDimension)dimension[i]).clearEntityMap();
791            }
792            menuSort.setEnabled(false);
793        }
794    
795        public boolean isFreezed() {
796            return freezed;
797        }
798    
799        protected void preMakeSelection() {
800            selectionName = null;
801            addSelection = new JDialog(Scene.getUIManager().getFrame(),"Add Selection",true);
802    
803            JCheckBox[] options = createSelectionOptions();
804    
805            JPanel panelMain = new JPanel(new BorderLayout());
806            addSelection.getContentPane().add(panelMain, BorderLayout.CENTER);
807    
808            JPanel panelOptions = new JPanel(new GridLayout(options.length, 1, 1, 1));
809            JPanel panelName = new JPanel(new GridLayout(2,1,1,1));
810            JPanel panelButton = new JPanel(new FlowLayout());
811    
812            for (int i=0; i<options.length; i++)
813                panelOptions.add(options[i]);
814            panelMain.add(panelOptions,BorderLayout.NORTH);
815    
816            textSelectionName = new JTextField("Selection"+Selection.total);
817            panelName.add(new JLabel("Input selection name:"));
818            panelName.add(textSelectionName);
819            panelMain.add(panelName,BorderLayout.CENTER);
820    
821            JButton buttonOk = new JButton("Ok");
822            buttonOk.addActionListener(new ActionListener() {
823                public void actionPerformed(ActionEvent e) {
824                    selectionName = textSelectionName.getText();
825                    if (selectionName.length()==0) {
826                        Scene.showErrorMessage("You must name this selection.");
827                        return;
828                    }
829                    addSelection.setVisible(false);
830                    addSelection.dispose();
831                }
832            });
833            panelButton.add(buttonOk);
834    
835            JButton buttonCancel = new JButton("Cancel");
836            buttonCancel.addActionListener(new ActionListener() {
837                public void actionPerformed(ActionEvent e) {
838                    selectionName = null;
839                    addSelection.setVisible(false);
840                    addSelection.dispose();
841                }
842            });
843            panelButton.add(buttonCancel);
844            panelMain.add(panelButton,BorderLayout.SOUTH);
845    
846            addSelection.pack();
847            Scene.getUIManager().showDialog(addSelection, addSelection.getWidth(), addSelection.getHeight());
848        }
849    
850        public int getInterval() {
851            return -1;
852        }
853    
854        public Object clone() {
855           Visualization o = null;
856    
857           try {
858               o = (Visualization)super.clone();
859           } catch (CloneNotSupportedException e) {
860               e.printStackTrace();
861               return null;
862           }
863    
864           o.name = name + "- cloned";
865           o.definition = (VisualizationDefinition)definition.clone();
866           o.subjectDefinition = (ElementDefinition) subjectDefinition.clone();
867           o.dimension = new Dimension[dimension.length];
868           o.factory = (VisualizationFactory)factory.clone();
869           o.elementDefinition = new ElementDefinition[elementDefinition.length];
870           for (int i=0; i<elementDefinition.length; i++)
871               o.elementDefinition[i] = (ElementDefinition)elementDefinition[i].clone();
872           o.dataFilter = new DataFilter[dataFilter.length][][];
873           o.linkageId = vizIDPool++;
874           for (int i=0; i<dataFilter.length; i++) {
875               o.dataFilter[i] = new DataFilter[dataFilter[i].length][];
876               for (int j=0; j<dataFilter[i].length; j++) {
877                   o.dataFilter[i][j] = new DataFilter[dataFilter[i][j].length];
878                   for (int k=0; k<dataFilter[i][j].length; k++)
879                       o.dataFilter[i][j][k] = (DataFilter)dataFilter[i][j][k].clone();
880               }
881           }
882           return o;
883       }
884    }