/* File: GridPanel.java - May 2011 */ package l25; import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * Main panel for the random grid graph GUI. * * @author Michael Albert * */ public class GridPanel extends JPanel { private static final int BUTTON_WIDTH = 300; private static final int BUTTON_HEIGHT = 50; private static final int DISPLAY_WIDTH = 300; private static final int DISPLAY_HEIGHT = 300; private static final int DELAY = 1; // ms private int width; private int height; private boolean showWeights = false; private ButtonPanel buttonPanel; private DisplayPanel displayPanel; private int rows; private int cols; private RandomGridGraph graph; Edge[] edges; int edgeCount = 0; public GridPanel(RandomGridGraph graph, int width, int height) { this.graph = graph; this.rows = graph.rows; this.cols = graph.cols; this.width = width; this.height = height; this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); displayPanel = new DisplayPanel(); buttonPanel = new ButtonPanel(); add( displayPanel ); add( buttonPanel ); } public GridPanel(RandomGridGraph g) { this(g, DISPLAY_WIDTH, DISPLAY_HEIGHT); } class ButtonPanel extends JPanel { private ButtonListener buttonListener = new ButtonListener(); private JButton initialise = new JButton("Initialise"); private JButton start = new JButton("Start"); private JButton stop = new JButton("Stop"); private JButton step = new JButton("Step"); private JButton reset = new JButton("Reset"); private JButton weights = new JButton("Show weights"); private JButton [ ] buttons = { initialise, start, stop, step, reset, weights }; private JRadioButton shortestPath = new JRadioButton("Shortest path", true); private JRadioButton minSpanningTree = new JRadioButton("Minimum Spanning Tree", false); private ButtonGroup algorithm; public ButtonPanel() { setSize(new Dimension(width, BUTTON_HEIGHT)); setBackground (Color.white); for (JButton button: buttons) { button.addActionListener(buttonListener); button.setBackground(Color.white); add(button); } algorithm = new ButtonGroup(); algorithm.add(shortestPath); algorithm.add(minSpanningTree); add(shortestPath); add(minSpanningTree); } class ButtonListener implements ActionListener { public void actionPerformed(ActionEvent ae) { JButton source = (JButton) ae.getSource(); if (source == initialise) initialise(); else if (source == start) start(); else if (source == stop) displayPanel.timer.stop(); else if (source == step) step(); else if (source == reset) reset(); else if (source == weights) updateWeights(); } private void initialise() { displayPanel.timer.stop(); graph.initialise(); shortestPath.setEnabled(true); minSpanningTree.setEnabled(true); edges = null; edgeCount = 0; displayPanel.repaint(); } private void start() { shortestPath.setEnabled(false); minSpanningTree.setEnabled(false); if (shortestPath.isSelected()) { edges = graph.dijkstra(0); } else { edges = graph.prim(0); } displayPanel.timer.start(); } private void step() { displayPanel.timer.stop(); shortestPath.setEnabled(false); minSpanningTree.setEnabled(false); if (edges == null && shortestPath.isSelected()) { edges = graph.dijkstra(0); } else if (edges == null) { edges = graph.prim(0); } displayPanel.step(); } private void reset() { displayPanel.timer.stop(); edgeCount = 0; shortestPath.setEnabled(true); minSpanningTree.setEnabled(true); edges = null; displayPanel.repaint(); } private void updateWeights() { if (showWeights) { weights.setText("Show weights"); } else { weights.setText("Hide weights"); } showWeights = !showWeights; displayPanel.repaint(); } } } class DisplayPanel extends JPanel{ private Timer timer = new Timer(DELAY, new TimeListener()); public DisplayPanel() { setBackground(Color.black); setPreferredSize( new Dimension(width, height)); } public void step() { edgeCount++; repaint(); } public void paint(Graphics g) { super.paint(g); g.setColor(Color.black); g.fillRect(0, 0, displayPanel.getWidth(), displayPanel.getHeight()); int dx = getWidth()/(2*cols-1); int dy = getHeight()/(2*rows-1); int xOffset = (getWidth() - (2*cols-1)*dx)/2; int yOffset = (getHeight() - (2*rows-1)*dy)/2; g.setFont(new Font(Font.SANS_SERIF,Font.PLAIN, (dy)/3)); g.setColor(Color.white); if (showWeights) showWeights(g, dx, dy, xOffset, yOffset); for(int i = 0; i < edgeCount && i < edges.length; i++) { showEdge(g, edges[i], dx, dy, xOffset, yOffset); } } public void showEdge(Graphics g, Edge e, int dx, int dy, int xOffset, int yOffset) { int x1 = (e.start % cols)*2*dx; int y1 = (e.start/cols)*2*dy; int x2 = (e.finish % cols)*2*dx; int y2 = (e.finish/cols)*2*dy; int x = ((x1 <= x2) ? x1 : x2); int y = ((y1 <= y2) ? y1 : y2); int width = Math.abs(x1-x2) + dx; int height = Math.abs(y1-y2) + dy; g.fillRect(x+xOffset,y+yOffset,width,height); if (showWeights) { g.setColor(Color.red); String w = ""+e.weight; int wLength = g.getFontMetrics().stringWidth(w); g.drawString(w, x+xOffset+width/2-wLength/2, y+yOffset+height/2); g.setColor(Color.white); } } } public void showWeights( Graphics g, int dx, int dy, int xOffset, int yOffset ) { for(Edge e: graph.edges) { int x1 = (e.start % cols)*2*dx; int y1 = (e.start/cols)*2*dy; int x2 = (e.finish % cols)*2*dx; int y2 = (e.finish/cols)*2*dy; int x = ((x1 <= x2) ? x1 : x2); int y = ((y1 <= y2) ? y1 : y2); int width = Math.abs(x1-x2) + dx; int height = Math.abs(y1-y2) + dy; String w = ""+e.weight; int wLength = g.getFontMetrics().stringWidth(w); g.drawString(w, x+xOffset+width/2-wLength/2, y+yOffset+height/2); } } class TimeListener implements ActionListener { public void actionPerformed(ActionEvent ae) { displayPanel.step(); } } }