[Pydev-cvs] org.python.pydev.refactoring/contrib/ch/hsr/ukistler/astgraph GraphVisitor.java, 1.3,
Brought to you by:
fabioz
Update of /cvsroot/pydev/org.python.pydev.refactoring/contrib/ch/hsr/ukistler/astgraph In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21605/contrib/ch/hsr/ukistler/astgraph Modified Files: GraphVisitor.java ASTGraph.java GraphView.java GraphPrinter.java ImageWriter.java Log Message: Synching to latest changes: Pydev <ul> <li><strong>Editor</strong>: Cursor settings no longer overridden</li> <li><strong>Code-completion</strong>: If __all__ is defined with runtime elements (and not only in a single assign statement), it's ignored for code-completion purposes</li> <li><strong>Debugger</strong>: Pythonpath the same in debug and regular modes (sys.path[0] is the same directory as the file run)</li> <li><strong>Debugger</strong>: Persist choices done in the debugger when files from the debugger are not found</li> <li><strong>Interpreter config</strong>: "email" automatically added to the "forced builtins"</li> <li><strong>Parser</strong>: Correctly recognizing absolute import with 3 or more levels</li> <li><strong>Syntax check</strong>: Option to do only on active editor</li> </ul> Also: tabs changed for spaces Index: GraphVisitor.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev.refactoring/contrib/ch/hsr/ukistler/astgraph/GraphVisitor.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** GraphVisitor.java 20 Oct 2007 19:31:04 -0000 1.3 --- GraphVisitor.java 27 Sep 2008 20:00:48 -0000 1.4 *************** *** 30,152 **** public class GraphVisitor extends VisitorBase { ! private static final int DEPTH_STEP = 30; ! private static final int INDENT_STEP = 40; ! private Color nodeColor; ! private List<DefaultGraphCell> cells; ! private FastStack<DefaultGraphCell> stack; ! int depth; ! int indent; ! public GraphVisitor() throws IOException { ! cells = new ArrayList<DefaultGraphCell>(); ! stack = new FastStack<DefaultGraphCell>(); ! depth = 0; ! indent = 0; ! nodeColor = Color.GRAY; ! } ! private DefaultEdge createConnection(DefaultGraphCell cell) { ! DefaultEdge edge = new DefaultEdge(); ! edge.setSource(stack.peek().getChildAt(0)); ! edge.setTarget(cell); ! // Set Arrow Style for edge ! int arrow = GraphConstants.ARROW_TECHNICAL; ! GraphConstants.setLineEnd(edge.getAttributes(), arrow); ! GraphConstants.setEndFill(edge.getAttributes(), true); ! return edge; ! } ! public DefaultGraphCell createVertex(String name, double x, double y, Color bg, boolean raised) { ! // Create vertex with the given name ! DefaultGraphCell cell = new DefaultGraphCell(name); ! GraphConstants.setBorder(cell.getAttributes(), BorderFactory.createEtchedBorder()); ! GraphConstants.setBounds(cell.getAttributes(), new Rectangle2D.Double(x, y, 10, 10)); ! GraphConstants.setResize(cell.getAttributes(), true); ! GraphConstants.setAutoSize(cell.getAttributes(), true); ! // Set fill color ! if (bg != null) { ! GraphConstants.setOpaque(cell.getAttributes(), true); ! GraphConstants.setGradientColor(cell.getAttributes(), bg); ! } ! // Set raised border ! if (raised) ! GraphConstants.setBorder(cell.getAttributes(), BorderFactory.createRaisedBevelBorder()); ! else ! // Set black border ! GraphConstants.setBorderColor(cell.getAttributes(), Color.black); ! return cell; ! } ! private void decrementPosition() { ! stack.pop(); ! indent -= INDENT_STEP; ! } ! public DefaultGraphCell[] getCells() { ! return cells.toArray(new DefaultGraphCell[0]); ! } ! private void incrementPosition(DefaultGraphCell cell) { ! stack.push(cell); ! indent += INDENT_STEP; ! depth += DEPTH_STEP; ! } ! private void parentAddPort() { ! Point2D point = new Point2D.Double(0, GraphConstants.PERMILLE); ! stack.peek().addPort(point); ! } ! @Override ! public void traverse(SimpleNode node) throws Exception { ! node.traverse(this); ! decrementPosition(); ! } ! @Override ! protected Object unhandled_node(SimpleNode node) throws Exception { ! DefaultGraphCell cell = null; ! String caption = node.toString(); ! parentAddPort(); ! cell = createVertex(caption, indent, depth, nodeColor, false); ! DefaultEdge edge = createConnection(cell); ! cells.add(cell); ! cells.add(edge); ! incrementPosition(cell); ! return null; ! } ! /** ! * Entry point ! */ ! @Override ! public Object visitModule(Module node) throws Exception { ! // String caption = node.toString(); ! DefaultGraphCell moduleCell = createVertex("Module", indent, depth, nodeColor, false); ! cells.add(moduleCell); ! incrementPosition(moduleCell); ! traverse(node); ! return null; ! } } --- 30,152 ---- public class GraphVisitor extends VisitorBase { ! private static final int DEPTH_STEP = 30; ! private static final int INDENT_STEP = 40; ! private Color nodeColor; ! private List<DefaultGraphCell> cells; ! private FastStack<DefaultGraphCell> stack; ! int depth; ! int indent; ! public GraphVisitor() throws IOException { ! cells = new ArrayList<DefaultGraphCell>(); ! stack = new FastStack<DefaultGraphCell>(); ! depth = 0; ! indent = 0; ! nodeColor = Color.GRAY; ! } ! private DefaultEdge createConnection(DefaultGraphCell cell) { ! DefaultEdge edge = new DefaultEdge(); ! edge.setSource(stack.peek().getChildAt(0)); ! edge.setTarget(cell); ! // Set Arrow Style for edge ! int arrow = GraphConstants.ARROW_TECHNICAL; ! GraphConstants.setLineEnd(edge.getAttributes(), arrow); ! GraphConstants.setEndFill(edge.getAttributes(), true); ! return edge; ! } ! public DefaultGraphCell createVertex(String name, double x, double y, Color bg, boolean raised) { ! // Create vertex with the given name ! DefaultGraphCell cell = new DefaultGraphCell(name); ! GraphConstants.setBorder(cell.getAttributes(), BorderFactory.createEtchedBorder()); ! GraphConstants.setBounds(cell.getAttributes(), new Rectangle2D.Double(x, y, 10, 10)); ! GraphConstants.setResize(cell.getAttributes(), true); ! GraphConstants.setAutoSize(cell.getAttributes(), true); ! // Set fill color ! if (bg != null) { ! GraphConstants.setOpaque(cell.getAttributes(), true); ! GraphConstants.setGradientColor(cell.getAttributes(), bg); ! } ! // Set raised border ! if (raised) ! GraphConstants.setBorder(cell.getAttributes(), BorderFactory.createRaisedBevelBorder()); ! else ! // Set black border ! GraphConstants.setBorderColor(cell.getAttributes(), Color.black); ! return cell; ! } ! private void decrementPosition() { ! stack.pop(); ! indent -= INDENT_STEP; ! } ! public DefaultGraphCell[] getCells() { ! return cells.toArray(new DefaultGraphCell[0]); ! } ! private void incrementPosition(DefaultGraphCell cell) { ! stack.push(cell); ! indent += INDENT_STEP; ! depth += DEPTH_STEP; ! } ! private void parentAddPort() { ! Point2D point = new Point2D.Double(0, GraphConstants.PERMILLE); ! stack.peek().addPort(point); ! } ! @Override ! public void traverse(SimpleNode node) throws Exception { ! node.traverse(this); ! decrementPosition(); ! } ! @Override ! protected Object unhandled_node(SimpleNode node) throws Exception { ! DefaultGraphCell cell = null; ! String caption = node.toString(); ! parentAddPort(); ! cell = createVertex(caption, indent, depth, nodeColor, false); ! DefaultEdge edge = createConnection(cell); ! cells.add(cell); ! cells.add(edge); ! incrementPosition(cell); ! return null; ! } ! /** ! * Entry point ! */ ! @Override ! public Object visitModule(Module node) throws Exception { ! // String caption = node.toString(); ! DefaultGraphCell moduleCell = createVertex("Module", indent, depth, nodeColor, false); ! cells.add(moduleCell); ! incrementPosition(moduleCell); ! traverse(node); ! return null; ! } } Index: ASTGraph.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev.refactoring/contrib/ch/hsr/ukistler/astgraph/ASTGraph.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** ASTGraph.java 20 Oct 2007 19:31:05 -0000 1.3 --- ASTGraph.java 27 Sep 2008 20:00:48 -0000 1.4 *************** *** 27,56 **** public class ASTGraph { ! public Tuple<SimpleNode, Throwable> parseFile(String fileName) throws FileNotFoundException, IOException, Throwable { ! File pythonSource = new File(fileName); ! BufferedReader in = new BufferedReader(new FileReader(pythonSource)); ! String line = ""; ! StringBuilder source = new StringBuilder(); ! while ((line = in.readLine()) != null) { ! source.append(line); ! source.append("\n"); ! } ! IDocument doc = new Document(source.toString()); ! Tuple<SimpleNode, Throwable> objects = PyParser.reparseDocument(new PyParser.ParserInfo(doc, false, ! IPythonNature.LATEST_GRAMMAR_VERSION)); ! if (objects.o2 != null) ! throw objects.o2; ! return objects; ! } ! public DefaultGraphCell[] generateTree(SimpleNode node) throws IOException, Exception { ! GraphVisitor visitor = new GraphVisitor(); ! node.accept(visitor); ! DefaultGraphCell[] cells = visitor.getCells(); ! return cells; ! } } --- 27,56 ---- public class ASTGraph { ! public Tuple<SimpleNode, Throwable> parseFile(String fileName) throws FileNotFoundException, IOException, Throwable { ! File pythonSource = new File(fileName); ! BufferedReader in = new BufferedReader(new FileReader(pythonSource)); ! String line = ""; ! StringBuilder source = new StringBuilder(); ! while ((line = in.readLine()) != null) { ! source.append(line); ! source.append("\n"); ! } ! IDocument doc = new Document(source.toString()); ! Tuple<SimpleNode, Throwable> objects = PyParser.reparseDocument(new PyParser.ParserInfo(doc, false, ! IPythonNature.LATEST_GRAMMAR_VERSION)); ! if (objects.o2 != null) ! throw objects.o2; ! return objects; ! } ! public DefaultGraphCell[] generateTree(SimpleNode node) throws IOException, Exception { ! GraphVisitor visitor = new GraphVisitor(); ! node.accept(visitor); ! DefaultGraphCell[] cells = visitor.getCells(); ! return cells; ! } } Index: ImageWriter.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev.refactoring/contrib/ch/hsr/ukistler/astgraph/ImageWriter.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** ImageWriter.java 20 Oct 2007 19:31:04 -0000 1.2 --- ImageWriter.java 27 Sep 2008 20:00:48 -0000 1.3 *************** *** 13,38 **** public class ImageWriter implements Runnable { ! private BufferedImage img; ! private String fileName; ! public ImageWriter(BufferedImage img, String fileName) throws Throwable { ! if (img == null) ! throw new Exception("Image cannot be retrieved"); ! this.img = img; ! this.fileName = fileName; ! } ! public void run() { ! FileOutputStream out; ! try { ! out = new FileOutputStream(new File(fileName)); ! ImageIO.write(img, "png", out); ! out.flush(); ! out.close(); ! } catch (Throwable e) { ! } ! } } --- 13,38 ---- public class ImageWriter implements Runnable { ! private BufferedImage img; ! private String fileName; ! public ImageWriter(BufferedImage img, String fileName) throws Throwable { ! if (img == null) ! throw new Exception("Image cannot be retrieved"); ! this.img = img; ! this.fileName = fileName; ! } ! public void run() { ! FileOutputStream out; ! try { ! out = new FileOutputStream(new File(fileName)); ! ImageIO.write(img, "png", out); ! out.flush(); ! out.close(); ! } catch (Throwable e) { ! } ! } } Index: GraphView.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev.refactoring/contrib/ch/hsr/ukistler/astgraph/GraphView.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** GraphView.java 20 Oct 2007 19:31:05 -0000 1.3 --- GraphView.java 27 Sep 2008 20:00:48 -0000 1.4 *************** *** 32,252 **** public class GraphView extends JFrame { ! /** ! * ! */ ! private static final long serialVersionUID = -3925214828169513991L; ! private JPanel boxPanel = null; ! private JFileChooser fc = null; ! private JGraph graph = null; ! private JScrollPane graphpane = null; ! private JPanel navPane = null; ! private JButton saveImage = null; ! private JButton loadPython = null; ! /** ! * This method initializes ! * ! */ ! public GraphView() { ! super("Python AST Viewer"); ! initialize(); ! } ! /** ! * This method initializes this ! * ! */ ! private void initialize() { ! this.fc = new JFileChooser(); ! this.setContentPane(getBoxPanel()); ! this.setSize(new Dimension(640, 480)); ! this.pack(); ! this.setExtendedState(javax.swing.JFrame.MAXIMIZED_BOTH); ! } ! /** ! * This method initializes boxPanel ! * ! * @return javax.swing.JPanel ! */ ! private JPanel getBoxPanel() { ! if (boxPanel == null) { ! boxPanel = new JPanel(); ! boxPanel.setLayout(new BorderLayout()); ! boxPanel.add(getNavPane(), BorderLayout.NORTH); ! boxPanel.add(getGraphpane(), BorderLayout.CENTER); ! } ! return boxPanel; ! } ! /** ! * This method initializes graphpane ! * ! * @return javax.swing.JScrollPane ! */ ! private JScrollPane getGraphpane() { ! if (graphpane == null) { ! graphpane = new JScrollPane(); ! this.graph = setupGraph(); ! graphpane.setViewportView(this.graph); ! } ! return graphpane; ! } ! /** ! * This method initializes navPane ! * ! * @return javax.swing.JPanel ! */ ! private JPanel getNavPane() { ! if (navPane == null) { ! navPane = new JPanel(); ! navPane.setLayout(new FlowLayout()); ! navPane.add(getSaveImage()); ! navPane.add(getLoadPython()); ! } ! return navPane; ! } ! /** ! * This method initializes saveImage ! * ! * @return javax.swing.JButton ! */ ! private JButton getSaveImage() { ! if (saveImage == null) { ! saveImage = new JButton(); ! saveImage.setText("Save as PNG"); ! saveImage.addActionListener(new java.awt.event.ActionListener() { ! public void actionPerformed(java.awt.event.ActionEvent event) { ! FileFilter filter = new PNGFilter(); ! try { ! fc.addChoosableFileFilter(filter); ! int returnVal = fc.showSaveDialog(GraphView.this); ! if (returnVal == JFileChooser.APPROVE_OPTION) { ! File file = fc.getSelectedFile(); ! createImage(file.getAbsolutePath()); ! } ! } finally { ! fc.removeChoosableFileFilter(filter); ! } ! } ! }); ! } ! return saveImage; ! } ! /** ! * This method initializes loadPython ! * ! * @return javax.swing.JButton ! */ ! private JButton getLoadPython() { ! if (loadPython == null) { ! loadPython = new JButton(); ! loadPython.setText("Load Python source"); ! loadPython.addActionListener(new java.awt.event.ActionListener() { ! public void actionPerformed(java.awt.event.ActionEvent event) { ! FileFilter filter = new PythonFilter(); ! try { ! fc.addChoosableFileFilter(filter); ! int returnVal = fc.showOpenDialog(GraphView.this); ! if (returnVal == JFileChooser.APPROVE_OPTION) { ! File file = fc.getSelectedFile(); ! loadGraph(file.getAbsolutePath()); ! } ! } catch (Throwable e) { ! JOptionPane msgbox = new JOptionPane("Error writing file: " + e.getMessage()); ! msgbox.setVisible(true); ! } finally { ! fc.removeChoosableFileFilter(filter); ! } ! } ! }); ! } ! return loadPython; ! } ! private JGraph setupGraph() { ! // Construct Model and Graph ! GraphModel model = new DefaultGraphModel(); ! JGraph graph = new JGraph(model); ! // Control-drag should clone selection ! graph.setCloneable(true); ! // Enable edit without final RETURN keystroke ! graph.setInvokesStopCellEditing(true); ! // When over a cell, jump to its default port (we only have one, anyway) ! graph.setJumpToDefaultPort(true); ! return graph; ! } ! private void loadGraph(String fileName) throws FileNotFoundException, IOException, Throwable { ! ASTGraph ast = new ASTGraph(); ! Tuple<SimpleNode, Throwable> objects = ast.parseFile(fileName); ! graph.setGraphLayoutCache(new GraphLayoutCache()); ! DefaultGraphCell[] cells = ast.generateTree(objects.o1); ! graph.getGraphLayoutCache().insert(cells); ! graph.clearSelection(); ! } ! private void createImage(String imageName) { ! if (graph == null) { ! return; ! } ! try { ! ImageWriter writer; ! writer = new ImageWriter(graph.getImage(null, GraphConstants.DEFAULTINSET), imageName); ! SwingUtilities.invokeLater(writer); ! } catch (Throwable e) { ! JOptionPane msgbox = new JOptionPane("Error writing file: " + e.getMessage()); ! msgbox.setVisible(true); ! } ! } ! class PNGFilter extends javax.swing.filechooser.FileFilter { ! public boolean accept(File file) { ! if (file.isDirectory()) ! return true; ! String filename = file.getName(); ! return filename.endsWith(".png"); ! } ! public String getDescription() { ! return "PNG image (*.png)"; ! } ! } ! class PythonFilter extends javax.swing.filechooser.FileFilter { ! public boolean accept(File file) { ! if (file.isDirectory()) ! return true; ! String filename = file.getName(); ! return filename.endsWith(".py"); ! } ! public String getDescription() { ! return "Python Source code (*.py)"; ! } ! } } // @jve:decl-index=0:visual-constraint="10,10" --- 32,252 ---- public class GraphView extends JFrame { ! /** ! * ! */ ! private static final long serialVersionUID = -3925214828169513991L; ! private JPanel boxPanel = null; ! private JFileChooser fc = null; ! private JGraph graph = null; ! private JScrollPane graphpane = null; ! private JPanel navPane = null; ! private JButton saveImage = null; ! private JButton loadPython = null; ! /** ! * This method initializes ! * ! */ ! public GraphView() { ! super("Python AST Viewer"); ! initialize(); ! } ! /** ! * This method initializes this ! * ! */ ! private void initialize() { ! this.fc = new JFileChooser(); ! this.setContentPane(getBoxPanel()); ! this.setSize(new Dimension(640, 480)); ! this.pack(); ! this.setExtendedState(javax.swing.JFrame.MAXIMIZED_BOTH); ! } ! /** ! * This method initializes boxPanel ! * ! * @return javax.swing.JPanel ! */ ! private JPanel getBoxPanel() { ! if (boxPanel == null) { ! boxPanel = new JPanel(); ! boxPanel.setLayout(new BorderLayout()); ! boxPanel.add(getNavPane(), BorderLayout.NORTH); ! boxPanel.add(getGraphpane(), BorderLayout.CENTER); ! } ! return boxPanel; ! } ! /** ! * This method initializes graphpane ! * ! * @return javax.swing.JScrollPane ! */ ! private JScrollPane getGraphpane() { ! if (graphpane == null) { ! graphpane = new JScrollPane(); ! this.graph = setupGraph(); ! graphpane.setViewportView(this.graph); ! } ! return graphpane; ! } ! /** ! * This method initializes navPane ! * ! * @return javax.swing.JPanel ! */ ! private JPanel getNavPane() { ! if (navPane == null) { ! navPane = new JPanel(); ! navPane.setLayout(new FlowLayout()); ! navPane.add(getSaveImage()); ! navPane.add(getLoadPython()); ! } ! return navPane; ! } ! /** ! * This method initializes saveImage ! * ! * @return javax.swing.JButton ! */ ! private JButton getSaveImage() { ! if (saveImage == null) { ! saveImage = new JButton(); ! saveImage.setText("Save as PNG"); ! saveImage.addActionListener(new java.awt.event.ActionListener() { ! public void actionPerformed(java.awt.event.ActionEvent event) { ! FileFilter filter = new PNGFilter(); ! try { ! fc.addChoosableFileFilter(filter); ! int returnVal = fc.showSaveDialog(GraphView.this); ! if (returnVal == JFileChooser.APPROVE_OPTION) { ! File file = fc.getSelectedFile(); ! createImage(file.getAbsolutePath()); ! } ! } finally { ! fc.removeChoosableFileFilter(filter); ! } ! } ! }); ! } ! return saveImage; ! } ! /** ! * This method initializes loadPython ! * ! * @return javax.swing.JButton ! */ ! private JButton getLoadPython() { ! if (loadPython == null) { ! loadPython = new JButton(); ! loadPython.setText("Load Python source"); ! loadPython.addActionListener(new java.awt.event.ActionListener() { ! public void actionPerformed(java.awt.event.ActionEvent event) { ! FileFilter filter = new PythonFilter(); ! try { ! fc.addChoosableFileFilter(filter); ! int returnVal = fc.showOpenDialog(GraphView.this); ! if (returnVal == JFileChooser.APPROVE_OPTION) { ! File file = fc.getSelectedFile(); ! loadGraph(file.getAbsolutePath()); ! } ! } catch (Throwable e) { ! JOptionPane msgbox = new JOptionPane("Error writing file: " + e.getMessage()); ! msgbox.setVisible(true); ! } finally { ! fc.removeChoosableFileFilter(filter); ! } ! } ! }); ! } ! return loadPython; ! } ! private JGraph setupGraph() { ! // Construct Model and Graph ! GraphModel model = new DefaultGraphModel(); ! JGraph graph = new JGraph(model); ! // Control-drag should clone selection ! graph.setCloneable(true); ! // Enable edit without final RETURN keystroke ! graph.setInvokesStopCellEditing(true); ! // When over a cell, jump to its default port (we only have one, anyway) ! graph.setJumpToDefaultPort(true); ! return graph; ! } ! private void loadGraph(String fileName) throws FileNotFoundException, IOException, Throwable { ! ASTGraph ast = new ASTGraph(); ! Tuple<SimpleNode, Throwable> objects = ast.parseFile(fileName); ! graph.setGraphLayoutCache(new GraphLayoutCache()); ! DefaultGraphCell[] cells = ast.generateTree(objects.o1); ! graph.getGraphLayoutCache().insert(cells); ! graph.clearSelection(); ! } ! private void createImage(String imageName) { ! if (graph == null) { ! return; ! } ! try { ! ImageWriter writer; ! writer = new ImageWriter(graph.getImage(null, GraphConstants.DEFAULTINSET), imageName); ! SwingUtilities.invokeLater(writer); ! } catch (Throwable e) { ! JOptionPane msgbox = new JOptionPane("Error writing file: " + e.getMessage()); ! msgbox.setVisible(true); ! } ! } ! class PNGFilter extends javax.swing.filechooser.FileFilter { ! public boolean accept(File file) { ! if (file.isDirectory()) ! return true; ! String filename = file.getName(); ! return filename.endsWith(".png"); ! } ! public String getDescription() { ! return "PNG image (*.png)"; ! } ! } ! class PythonFilter extends javax.swing.filechooser.FileFilter { ! public boolean accept(File file) { ! if (file.isDirectory()) ! return true; ! String filename = file.getName(); ! return filename.endsWith(".py"); ! } ! public String getDescription() { ! return "Python Source code (*.py)"; ! } ! } } // @jve:decl-index=0:visual-constraint="10,10" Index: GraphPrinter.java =================================================================== RCS file: /cvsroot/pydev/org.python.pydev.refactoring/contrib/ch/hsr/ukistler/astgraph/GraphPrinter.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** GraphPrinter.java 20 Oct 2007 19:31:04 -0000 1.2 --- GraphPrinter.java 27 Sep 2008 20:00:48 -0000 1.3 *************** *** 7,16 **** public class GraphPrinter { ! public static void main(String[] args) throws Throwable { ! GraphView view = new GraphView(); ! view.setVisible(true); ! } } --- 7,16 ---- public class GraphPrinter { ! public static void main(String[] args) throws Throwable { ! GraphView view = new GraphView(); ! view.setVisible(true); ! } } |