001/* Copyright (C) 2013 TU Dortmund
002 * This file is part of AutomataLib, http://www.automatalib.net/.
003 * 
004 * AutomataLib is free software; you can redistribute it and/or
005 * modify it under the terms of the GNU Lesser General Public
006 * License version 3.0 as published by the Free Software Foundation.
007 * 
008 * AutomataLib is distributed in the hope that it will be useful,
009 * but WITHOUT ANY WARRANTY; without even the implied warranty of
010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
011 * Lesser General Public License for more details.
012 * 
013 * You should have received a copy of the GNU Lesser General Public
014 * License along with AutomataLib; if not, see
015 * http://www.gnu.de/documents/lgpl.en.html.
016 */
017package net.automatalib.commons.dotutil;
018
019import java.awt.GridBagConstraints;
020import java.awt.GridBagLayout;
021import java.awt.event.ActionEvent;
022import java.io.File;
023import java.io.IOException;
024import java.io.Reader;
025import java.io.StringReader;
026import java.io.StringWriter;
027import java.io.Writer;
028
029import javax.swing.AbstractAction;
030import javax.swing.Action;
031import javax.swing.DefaultListModel;
032import javax.swing.JButton;
033import javax.swing.JFileChooser;
034import javax.swing.JList;
035import javax.swing.JOptionPane;
036import javax.swing.JPanel;
037import javax.swing.JScrollPane;
038import javax.swing.event.ListSelectionEvent;
039import javax.swing.event.ListSelectionListener;
040
041public class DOTPanel extends JPanel {
042        
043        private static final long serialVersionUID = 1L;
044
045        
046        private final class DotWriter extends StringWriter {
047
048                private final String name;
049                
050                public DotWriter(String name) {
051                        this.name = name;
052                }
053                
054                @Override
055                public void close() throws IOException {
056                        addGraph(name, getBuffer().toString());
057                        super.close();
058                }
059        }
060        
061        private final ImageComponent imgComponent;
062        
063        private final JList<PlottedGraph> listBox;
064        private final DefaultListModel<PlottedGraph> graphs;
065        
066        
067        private final Action saveDotAction = new AbstractAction() {
068                private static final long serialVersionUID = -1L;
069                {
070                        putValue(NAME, "Save DOT");
071                        setEnabled(false);
072                }
073                @Override
074                public void actionPerformed(ActionEvent e) {
075                        saveDOT();
076                }
077        };
078        
079        private final Action savePngAction = new AbstractAction() {
080                private static final long serialVersionUID = -1L;
081                {
082                        putValue(NAME, "Save PNG");
083                        setEnabled(false);
084                }
085                @Override
086                public void actionPerformed(ActionEvent e) {
087                        savePNG();
088                }
089        };
090        
091        private final Action renameAction = new AbstractAction() {
092                private static final long serialVersionUID = -1L;
093                {
094                        putValue(NAME, "Rename");
095                        setEnabled(false);
096                }
097                @Override
098                public void actionPerformed(ActionEvent e) {
099                        rename();
100                }
101        };
102        
103        
104        private final Action clearAction = new AbstractAction() {
105                private static final long serialVersionUID = -1L;
106                {
107                        putValue(NAME, "Clear");
108                }
109                @Override
110                public void actionPerformed(ActionEvent e) {
111                        clear();
112                }
113        };
114        
115        
116        public Action getSaveDotAction() {
117                return saveDotAction;
118        }
119        
120        public Action getSavePngAction() {
121                return savePngAction;
122        }
123        
124        public Action getRenameAction() {
125                return renameAction;
126        }
127        
128        public Action getClearAction() {
129                return clearAction;
130        }
131        
132        public DOTPanel() {
133                setLayout(new GridBagLayout());
134                
135                GridBagConstraints c = new GridBagConstraints();
136                c.gridx = 0;
137                c.gridy = 0;
138                c.gridwidth = 1;
139                c.gridheight = 3;
140                c.fill = GridBagConstraints.BOTH;
141                c.weightx = 1.0;
142                c.weighty = 1.0;
143                this.imgComponent = new ImageComponent();
144                final JScrollPane scrollPane = new JScrollPane(imgComponent);
145                add(scrollPane, c);
146                
147                
148                c.gridx = 1;
149                c.weightx = 0.0;
150                c.gridheight = 1;
151                this.graphs = new DefaultListModel<>();
152                listBox = new JList<>(graphs);
153                listBox.addListSelectionListener(new ListSelectionListener() {
154                        @Override
155                        public void valueChanged(ListSelectionEvent e) {
156                                int idx = listBox.getSelectedIndex();
157                                boolean activeSelection = (idx != -1);
158                                if(!activeSelection)
159                                        imgComponent.setImage(null);
160                                else {
161                                        PlottedGraph pg = graphs.get(idx);
162                                        imgComponent.setImage(pg.getImage());
163                                }
164                                saveDotAction.setEnabled(activeSelection);
165                                savePngAction.setEnabled(activeSelection);
166                                renameAction.setEnabled(activeSelection);
167                                scrollPane.validate();
168                        }
169                });
170                add(new JScrollPane(listBox), c);
171                
172                c.gridy = 1;
173                c.weighty = 0.0;
174                JButton savePngBtn = new JButton(savePngAction) ;
175                add(savePngBtn, c);
176                
177                c.gridy = 2;
178                JButton saveDotBtn = new JButton(saveDotAction);
179                add(saveDotBtn, c);
180        }
181        
182        public void saveDOT() {
183                PlottedGraph pg = listBox.getSelectedValue();
184                if(pg == null) {
185                        JOptionPane.showMessageDialog(this, "Cannot save DOT: No active graph!", "Cannot save DOT", JOptionPane.ERROR_MESSAGE);
186                        return;
187                }
188                JFileChooser saveDlg = new JFileChooser();
189                saveDlg.setFileFilter(DOTMisc.DOT_FILTER);
190                int result = saveDlg.showSaveDialog(this);
191                if(result != JFileChooser.APPROVE_OPTION)
192                        return;
193                try {
194                        pg.saveDot(saveDlg.getSelectedFile());
195                }
196                catch(IOException e) {
197                        JOptionPane.showMessageDialog(this, "Could not save DOT file: " + e.getMessage(), "Cannot save DOT", JOptionPane.ERROR_MESSAGE);
198                }
199        }
200        
201        public void savePNG() {
202                PlottedGraph pg = listBox.getSelectedValue();
203                if(pg == null) {
204                        JOptionPane.showMessageDialog(this, "Cannot save PNG: No active graph!", "Cannot save PNG", JOptionPane.ERROR_MESSAGE);
205                        return;
206                }
207                JFileChooser saveDlg = new JFileChooser();
208                saveDlg.setFileFilter(DOTMisc.PNG_FILTER);
209                File f = new File(saveDlg.getCurrentDirectory(), pg.getName() + ".png");
210                saveDlg.setSelectedFile(f);
211                int result = saveDlg.showSaveDialog(this);
212                if(result != JFileChooser.APPROVE_OPTION)
213                        return;
214                
215                
216                try {
217                        pg.savePng(saveDlg.getSelectedFile());
218                }
219                catch(IOException e) {
220                        JOptionPane.showMessageDialog(this, "Could not save PNG file: " + e.getMessage(), "Cannot save PNG", JOptionPane.ERROR_MESSAGE);
221                }
222        }
223        
224        
225        public void addGraph(String name, Reader dotText) throws IOException {
226                PlottedGraph pg = new PlottedGraph(name, dotText);
227                graphs.addElement(pg);
228        }
229        
230        public void addGraph(String name, String dotText) {
231                try {
232                        addGraph(name, new StringReader(dotText));
233                }
234                catch(IOException e) {}
235        }
236        
237        public void clear() {
238                graphs.clear();
239        }
240        
241        public void rename() {
242                PlottedGraph pg = listBox.getSelectedValue();
243                if(pg == null) {
244                        JOptionPane.showMessageDialog(this, "Cannot rename: No active graph!", "Cannot rename", JOptionPane.ERROR_MESSAGE);
245                        return;
246                }
247                
248                String input = JOptionPane.showInputDialog(this, "Enter new name: ", "Enter name");
249                if(input == null)
250                        return;
251                pg.setName(input);
252        }
253        
254        public Writer createDotWriter(String name) {
255                return new DotWriter(name);
256        }
257}