package whackamole; import javax.swing.*; import java.awt.*; import java.beans.*; import java.util.*; /** This class can draw a rectangle within a specified area of an outer {@link JPanel}. * The rectagle changes color based on the signals and colors provided. *

You must make this class thread-safe without obtaining any lcoks */ public class RectViz implements Scribbler { private JPanel outer; private Color color; private PropertyChangeSupport pcs; private boolean visible; /** Constructor with parameters as follows * @param pcs This class must register as a {@link PropertyChangeListener} for each signal provided * @param dx fraction of outer.getWidth() for x coordinate * @param dy fraction of outer.getHeight() for y coordinate * @param dwidth fraction of outer.getWidth() for width * @param dheight fraction of outer.getHeight() for height * @param signals array of Strings, names of signals to be received * @param colors array of Colors, one for each signal, the color to set the rectagle * @param initColor the starting Color for the rectangle */ public RectViz(PropertyChangeSupport pcs, double dx, double dy, double dwidth, double dheight, JPanel outer, String[] signals, Color[] colors, Color initColor) { this(pcs, dx, dy, dwidth, dheight, outer, makeMap(signals, colors), initColor); } private static Map makeMap(String[] signals, Color[] colors) { Map ans = new HashMap(); for(int i=0; i < Math.min(signals.length, colors.length); ++i) { ans.put(signals[i], colors[i]); } return ans; } /** Constructor with parameters as follows * @param pcs This class must register as a {@link PropertyChangeListener} for each signal provided * @param dx fraction of outer.getWidth() for x coordinate * @param dy fraction of outer.getHeight() for y coordinate * @param dwidth fraction of outer.getWidth() for width * @param dheight fraction of outer.getHeight() for height * @param signalToColor is a mapping from {@link String} to {@link Color} * @param initColor the starting Color for the rectangle */ public RectViz(PropertyChangeSupport pcs, double dx, double dy, double dwidth, double dheight, JPanel outer, Map signalToColor, Color initColor) { this.pcs = pcs; this.color = initColor; this.outer = outer; this.visible = true; // // Capture the params // for (Iterator i = signalToColor.keySet().iterator(); i.hasNext();) { String s = (String) i.next(); Color c = (Color) signalToColor.get(s); register(pcs, s, c); } // Register and be prepared for the "moved" PCS signal // Register and be prepared for the "visible" boolean-valued PCS signal } public PropertyChangeSupport getPCS() { return pcs; } private int mpy(double frac, double n) { return (int)(frac * n); } /** A useful helper method that can be called from an inner class {@link PropertyChangeListener} from * the register method. * Set the instance variable for the color and call outer.repaint(). That in turn will call * draw in this class, because paintComponent is overriden in the outer {@link JPanel}. */ protected void setColor(Color c) { color = c; outer.repaint(); } /** Move within a unit square to the specified coordinates */ public void setLoc(double newdx, double newdy) { // FIX } /** Return the location as a {@link Point} in the unit square */ public Point getLoc() { return null; // FIX } /** Return the size in the unit square, width in [0], height in [1] */ public double[] getSize() { return null; } /** Set the size (in terms of a unit square) according to the parameters */ public void setSize(double newdwidth, double newdheight) { // FIX } /** Modify the size by the scaling factor provided */ public void scale(double frac) { // FIX } /** Can be overriden to change the way the color is chosen */ protected Color getColor() { return color; } /** A very useful helper method. Implement it, thus simplifying registration of PropertyChangeListeners * from the constructor. This method is protected only so it will show up in the JavaDoc. * Using the pcs, add a ProeprtyChangeListener that simply calls setColor(c) (another helper method). */ protected final void register(PropertyChangeSupport pcs, final String s, final Color c) { pcs.addPropertyChangeListener(s, new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent e) { setColor(c); } } ); } /** Given the supplied {@link Graphics} object *

* Do not issue a repaint on the outer panel! That would cause this * code to run indefinitely. **/ public void draw(Graphics g) { } }