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}