/* * JFLAP - Formal Languages and Automata Package * * * Susan H. Rodger * Computer Science Department * Duke University * August 27, 2009 * Copyright (c) 2002-2009 * All rights reserved. * JFLAP is open source software. Please see the LICENSE for terms. * */ package gui.viewer; import automata.State; import automata.Automaton; import java.awt.Graphics; import java.awt.Point; import java.awt.Color; import java.awt.geom.Rectangle2D; /** * The StateDrawer class handles the drawing of individual * states. * * @author Thomas Finley */ public class StateDrawer { /** * The default constructor for a StateDrawer */ public StateDrawer() { this.radius = STATE_RADIUS; } /** * Creates a StateDrawer with states drawn to a particular * radius. * * @param radius * the radius of states drawn by this state drawer */ public StateDrawer(int radius) { this.radius = radius; } /** * Draws an individual state with all the default modes. * * @param g * the graphics object to draw upon * @param automaton * the automaton this state is a part of * @param state * the state to draw */ public void drawState(Graphics g, Automaton automaton, State state) { this.drawState(g, automaton, state, state.getPoint()); } /** * Draws an individual state, but at the point specified rather than at the * point of the state's getPoint() method. * * @param g * the graphics object to draw upon * @param state * the state to draw * @param automaton * the automaton this state is a part of * @param point * the point to draw the state at */ public void drawState(Graphics g, Automaton automaton, State state, Point point) { drawState(g, automaton, state, point, STATE_COLOR); } /** * Draws an individual state at the point specified with the color * specified. * * @param g * the graphics object to draw upon * @param state * the state to draw * @param automaton * the automaton this state is a part of * @param point * the point to draw the state at * @param color * the color of the inner portion of the state */ public void drawState(Graphics g, Automaton automaton, State state, Point point, Color color) { drawArea(g, automaton, state, point, color); return; } /** * @param state */ private void drawArea(Graphics g, Automaton automaton, State state, Point point, Color color) { // Draw the basic background of the state. drawBackground(g, state, point, color); // What about the text label? g.setColor(Color.black); int dx = ((int) g.getFontMetrics().getStringBounds(state.getName(), g) .getWidth()) >> 1; int dy = ((int) g.getFontMetrics().getAscent()) >> 1; g.drawString(state.getName(), point.x - dx, point.y + dy); // Draw the outline. // //System.out.println("State name:" + state.getInternalName()); // if (state.getInternalName() == null) { g.drawOval(point.x - radius, point.y - radius, 2 * radius, 2 * radius); // If this is a final state, draw the little "inner circle." if (automaton.isFinalState(state)) g.drawOval(point.x - radius + 3, point.y - radius + 3, (radius - 3) << 1, (radius - 3) << 1); // If this is the initial state. if (automaton.getInitialState() == state) { int[] x = { point.x - radius, point.x - (radius << 1), point.x - (radius << 1) }; int[] y = { point.y, point.y - radius, point.y + radius }; g.setColor(Color.white); g.fillPolygon(x, y, 3); g.setColor(Color.black); g.drawPolygon(x, y, 3); } // } else { // Double temp = new Double(radius * 1.5); // g.drawRect(point.x - radius, point.y - radius, 2 * radius, // 2 * radius); // // If this is a final state, draw the little "inner rectangle." // if (automaton.isFinalState(state)) // g.drawRect(point.x - radius + 3, point.y - radius + 3, // (radius - 3) << 1, (radius - 3) << 1); // // If this is the initial state. // if (automaton.getInitialState() == state) { // int[] x = { point.x - radius, point.x - (radius << 1), // point.x - (radius << 1) }; // int[] y = { point.y, point.y - radius, point.y + radius }; // g.setColor(Color.white); // g.fillPolygon(x, y, 3); // g.setColor(Color.black); // g.drawPolygon(x, y, 3); // } // } } /** * Draws the state label for a given state. * * @param state * the state whose label we must draw * @param point * the point of the state, which is NOT the same thing as any * point where the label gets drawn * @param color * the background color of the label */ public void drawStateLabel(Graphics g, State state, Point point, Color color) { String[] labels = state.getLabels(); if (labels.length == 0) return; int ascent = g.getFontMetrics().getAscent(); int heights = 0; int textWidth = 0; for (int i = 0; i < labels.length; i++) { Rectangle2D bounds = g.getFontMetrics().getStringBounds(labels[i], g); textWidth = Math.max((int) bounds.getWidth(), textWidth); heights += ascent + STATE_LABEL_PAD; } heights -= STATE_LABEL_PAD; // Width of the box. int width = textWidth + (STATE_LABEL_PAD << 1); int height = heights + (STATE_LABEL_PAD << 1); // Upper corner of the box. int x = point.x - (width >> 1); int y = point.y + STATE_RADIUS - STATE_LABEL_PAD; // Where the y point of the baseline is. int baseline = y; g.setColor(color); g.fillRect(x, y, width, height); g.setColor(Color.black); for (int i = 0; i < labels.length; i++) { baseline += ascent + STATE_LABEL_PAD; g.drawString(labels[i], x + STATE_LABEL_PAD, baseline); } g.drawRect(x, y, width, height); } /** * Draws the background of the state. * * @param g * the graphics object to draw upon * @param state * the state object to draw * @param point * the point where the background should be centered * @param color * the color of the background, if supported by this class * @param bool */ public void drawBackground(Graphics g, State state, Point point, Color color) { g.setColor(color); if(state.isSelected()) g.setColor(new Color(100, 200, 200)); // if (state.getInternalName() == null) g.fillOval(point.x - radius, point.y - radius, 2 * radius, 2 * radius); // else { // g.fillRect(point.x - radius, point.y - radius, 2 * radius, // 2 * radius); // } } /** * Returns the radius of a state as drawn by this state drawer. * * @return the radius of a state */ public int getRadius() { return radius; } /** The radius we should draw states at. */ private int radius = STATE_RADIUS; /** The default radius of a state. */ public static final int STATE_RADIUS = 20; /** The base color for states. */ public static final Color STATE_COLOR = new Color(255, 255, 150); /** The label padding for states. */ public static final int STATE_LABEL_PAD = 3; }