home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-03-18 | 23.9 KB | 774 lines |
- package symantec.itools.awt;
-
- import java.awt.Rectangle;
- import java.awt.Dimension;
- import java.awt.Color;
- import java.awt.Graphics;
- import java.beans.PropertyVetoException;
- import java.beans.PropertyChangeListener;
- import java.beans.VetoableChangeListener;
- import java.beans.PropertyChangeEvent;
- import java.lang.IllegalArgumentException;
- import symantec.itools.awt.util.ColorUtils;
- import java.util.ResourceBundle;
-
- // 01/29/97 TWB Integrated changes from Windows
- // 05/23/97 LAB Updated to support Java 1.1
- // 06/27/97 LAB Changed the way the button is drawn. Now it uses the offscreen
- // Image. Cleaned up the drawing code to be more universal.
- // Added the ArrowColor property to allow the arrow to have a
- // user definable color. The disabled color is derived from this color.
- // 07/02/97 LAB Constrained the Arrow Indent Property, so the arrow wouldn't draw strangely
- // if the inset was set to a large value.
- // 07/08/97 LAB Changed the preferedSize() method to return a button whose arrow is 20 by 20.
- // 07/13/97 RKM Fixed misspelling of prefered
- // 07/19/97 LAB Replaced updatePolygon with fillTriangle and changed the drawing method from
- // using a polygon to using lines because polygons were problematic. Changed
- // getPreferredSize to return the smallest size which the button looks good and
- // changed getMinimumSize to return the smallest possible size for the button and
- // still be recognized as a DirectionButton.
- // 07/25/97 CAR marked fields transient as needed
- // innerclasses implement java.io.Serializable
- // 10/05/97 LAB Changed names of strings in PropertyChangeEvent handling to follow Bean Spec
- // naming conventions. Added mechanism for internally constrained properties
- // to be validated after the component is added to the form to avoid code-gen
- // order specific dependencies.
- // 10/06/97 LAB Initialized tempIndent to indent which resolves shrinkTriangle
- // and setArrowIndent conflicts (Addresses Mac Bug #9014). Changed
- // addNotify to call it's super after listeners are hooked up so
- // verifyContstrainedPropertyValues will be called after the listeners
- // are hooked up. Changed setArrowIndent to set the temp value to the
- // current value when changing the current value. Changed
- // getBevelHeight to return the temp value if the component is not
- // added. This fixes a problem at design time where the component would
- // revert to it's default state after a back run
-
- /**
- * The DirectionButton is a button component that has an arrow drawn in it that
- * points one of four ways (left, up, right, or down). At runtime, the button has
- * a raised look and a pressed look.
- * <p>
- * This component is usually used in conjunction with a combo or list box to
- * indicate a list that the user can view by clicking the arrow, or with spinners
- * to let the user scroll through available values.
- * <p>
- * @version 1.1, June 27, 1997
- * @author Symantec
- */
- public class DirectionButton extends ButtonBase implements java.io.Serializable
- {
- /**
- * The point LEFT style constant.
- */
- public static final int LEFT = 0;
-
- /**
- * The point RIGHT style constant.
- */
- public static final int RIGHT = 1;
-
- /**
- * The point UP style constant.
- */
- public static final int UP = 2;
-
- /**
- * The point DOWN style constant.
- */
- public static final int DOWN = 3;
-
- /**
- * Constructs a default DirectionButton, which will point left.
- */
- public DirectionButton()
- {
- this(LEFT);
- }
-
- /**
- * Constructs a DirectionButton pointing the specified direction.
- * @param d a style constant indicating which direction to point the button
- * @see #LEFT
- * @see #UP
- * @see #RIGHT
- * @see #DOWN
- */
- public DirectionButton(int d)
- {
- direction = d;
- left = 0;
- right = 0;
- bottom = 0;
- indent = 0;
- tempIndent = indent;
- try { setArrowColor(Color.black); } catch (PropertyVetoException exc) {}
-
- }
-
- /**
- * Sets the direction of the arrow after construction.
- * @param d constant indicating direction to point button
- * @exception PropertyVetoException
- * if the specified property value is unacceptable
- * @see #getDirection
- * @see #LEFT
- * @see #UP
- * @see #RIGHT
- * @see #DOWN
- */
- public void setDirection(int d) throws PropertyVetoException
- {
- if(direction != d)
- {
- Integer oldValue = new Integer(direction);
- Integer newValue = new Integer(d);
-
- vetos.fireVetoableChange("direction", oldValue, newValue);
-
- direction = d;
- repaint();
-
- changes.firePropertyChange("direction", oldValue, newValue);
- }
- }
-
- /**
- * Returns the direction the button is currently pointing.
- * @see #setDirection
- * @see #LEFT
- * @see #UP
- * @see #RIGHT
- * @see #DOWN
- */
- public int getDirection()
- {
- return direction;
- }
-
- /**
- * Sets the amount of blank space between the arrow and the button
- * border in pixels.
- * @param ai the margin around the arrow in pixels. 0=arrow takes up entire button
- * @exception PropertyVetoException
- * if the specified property value is unacceptable
- * @see #getArrowIndent
- */
- public void setArrowIndent(int ai) throws PropertyVetoException
- {
- if(isAdded)
- {
- if(indent != ai)
- {
- Integer oldValue = new Integer(indent);
- Integer newValue = new Integer(ai);
-
- vetos.fireVetoableChange("arrowIndent", oldValue, newValue);
-
- indent = ai;
- tempIndent = ai;
- //Make sure that changes to indent don't make changes to shrinkTriangle
- //give us a bad triangle.
- shrinkTriangle(left, right, top, bottom);
- repaint();
-
- changes.firePropertyChange("arrowIndent", oldValue, newValue);
- }
- }
- //We store the value until we are added then set the value to avoid code-gen order dependencies.
- else
- {
- tempIndent = ai;
- }
- }
-
- /**
- * Sets the color of the direction arrow.
- * @param newValue the new arrow color.
- * @exception PropertyVetoException
- * if the specified property value is unacceptable
- * @see #getArrowColor
- */
- public void setArrowColor(Color newValue) throws PropertyVetoException
- {
- if (!symantec.itools.util.GeneralUtils.objectsEqual(arrowColor, newValue))
- {
- Color oldValue = arrowColor;
-
- vetos.fireVetoableChange("arrowColor", oldValue, newValue);
-
- arrowColor = newValue;
- try
- {
- disabledArrowColor = ColorUtils.fade(arrowColor, Color.lightGray, 0.50);
- }
- catch (IllegalArgumentException exc) {}
-
- repaint();
-
- changes.firePropertyChange("arrowColor", oldValue, newValue);
- }
- }
-
- /**
- * Gets the current color of the direction arrow.
- * @return the current arrow color
- * @see #setArrowColor
- */
- public Color getArrowColor()
- {
- return arrowColor;
- }
-
- /**
- * Returns the amount of blank space between the arrow and the button
- * border in pixels.
- * @see #setArrowIndent
- */
- public int getArrowIndent()
- {
- return isAdded ? indent : tempIndent;
- }
-
- /**
- * Sets the extra amount, in pixels, to shrink the arrow triangle.
- * Constrains the values such that the arrow will never be less than
- * three pixels. If a value is entered that would exceed this limit,
- * the limit will be used instead.
- * @param left pixels to shrink from left side
- * @param right pixels to shrink from right side
- * @param top pixels to shrink from top
- * @param bottom pixels to shrink from bottom
- */
- public void shrinkTriangle(int l, int r, int t, int b)
- {
- if(isAdded)
- {
- Dimension s = getSize();
- int maxWidth = s.width - bevel - bevel - 2;
- int maxHeight = s.height - bevel - bevel - 2;
-
- if(maxWidth - (l + r + indent + indent) >= 3)
- {
- left = l;
- right = r;
- }
- else
- {
- left = (maxWidth - indent - indent - 3) / 2;
- right = left;
- }
-
- if(maxHeight - (t + b + indent + indent) >= 3)
- {
- top = t;
- bottom = b;
- }
- else
- {
- top = (maxHeight - indent - indent - 3) / 2;
- bottom = top;
- }
- }
- }
-
- /**
- * Returns the recommended dimensions to properly display this component.
- * This is a standard Java AWT method which gets called to determine
- * the recommended size of this component.
- *
- * @return a button that has a content area of 7 by 7 pixels.
- * @see java.awt.Component#getMinimumSize
- */
- public Dimension getPreferredSize()
- {
- Dimension defaultSize = super.getPreferredSize();
-
- return new Dimension(defaultSize.width + 7, defaultSize.height + 7);
- }
-
- /**
- * Returns the minimum dimensions to properly display this component.
- * This is a standard Java AWT method which gets called to determine
- * the minimum size of this component.
- *
- * @return a button that has a content area of 3 by 3 pixels.
- * @see java.awt.Component#getMinimumSize
- */
- public Dimension getMinimumSize()
- {
- Dimension defaultSize = super.getPreferredSize();
-
- return new Dimension(defaultSize.width + 3, defaultSize.height + 3);
- }
-
- /**
- * Tells this component that it has been added to a container.
- * This is a standard Java AWT method which gets called by the AWT when
- * this component is added to a container. Typically, it is used to
- * create this component's peer.
- *
- * It has been overridden here to hook-up event listeners.
- *
- * @see #removeNotify
- */
- public synchronized void addNotify()
- {
- errors = ResourceBundle.getBundle("symantec.itools.resources.ErrorsBundle");
-
- //Hook up listeners
- if (sizeVeto == null)
- {
- sizeVeto = new SizeVeto();
- addDirectionListener(sizeVeto);
- }
- if (indentVeto == null)
- {
- indentVeto = new IndntVeto();
- addArrowIndentListener(indentVeto);
- }
-
- //Add after the listeners are hooked up
- super.addNotify();
- }
-
- /**
- * Tells this component that it is being removed from a container.
- * This is a standard Java AWT method which gets called by the AWT when
- * this component is removed from a container. Typically, it is used to
- * destroy the peers of this component and all its subcomponents.
- *
- * It has been overridden here to unhook event listeners.
- *
- * @see #addNotify
- */
- public synchronized void removeNotify()
- {
- //Unhook listeners
- if (sizeVeto != null)
- {
- removeDirectionListener(sizeVeto);
- sizeVeto = null;
- }
- if (indentVeto != null)
- {
- removeArrowIndentListener(indentVeto);
- indentVeto = null;
- }
-
- super.removeNotify();
- }
-
- /**
- * Adds a listener for all event changes.
- * @param listener the listener to add.
- * @see #removePropertyChangeListener
- */
- public synchronized void addPropertyChangeListener(PropertyChangeListener listener)
- {
- super.addPropertyChangeListener(listener);
- changes.addPropertyChangeListener(listener);
- }
-
- /**
- * Removes a listener for all event changes.
- * @param listener the listener to remove.
- * @see #addPropertyChangeListener
- */
- public synchronized void removePropertyChangeListener(PropertyChangeListener listener)
- {
- super.removePropertyChangeListener(listener);
- changes.removePropertyChangeListener(listener);
- }
-
- /**
- * Adds a vetoable listener for all event changes.
- * @param listener the listener to add.
- * @see #removeVetoableChangeListener
- */
- public synchronized void addVetoableChangeListener(VetoableChangeListener listener)
- {
- super.addVetoableChangeListener(listener);
- vetos.addVetoableChangeListener(listener);
- }
-
- /**
- * Removes a vetoable listener for all event changes.
- * @param listener the listener to remove.
- * @see #addVetoableChangeListener
- */
- public synchronized void removeVetoableChangeListener(VetoableChangeListener listener)
- {
- super.removeVetoableChangeListener(listener);
- vetos.removeVetoableChangeListener(listener);
- }
-
- /**
- * Adds a listener for the Direction property changes.
- * @param listener the listener to add.
- * @see #removeDirectionListener
- */
- public synchronized void addDirectionListener(PropertyChangeListener listener)
- {
- changes.addPropertyChangeListener("direction", listener);
- }
-
- /**
- * Removes a listener for the Direction property changes.
- * @param listener the listener to remove.
- * @see #addDirectionListener
- */
- public synchronized void removeDirectionListener(PropertyChangeListener listener)
- {
- changes.removePropertyChangeListener("direction", listener);
- }
-
- /**
- * Adds a vetoable listener for the Direction property changes.
- * @param listener the listener to add.
- * @see #removeDirectionListener
- */
- public synchronized void addDirectionListener(VetoableChangeListener listener)
- {
- vetos.addVetoableChangeListener("direction", listener);
- }
-
- /**
- * Removes a vetoable listener for the Direction property changes.
- * @param listener the listener to remove.
- * @see #addDirectionListener
- */
- public synchronized void removeDirectionListener(VetoableChangeListener listener)
- {
- vetos.removeVetoableChangeListener("direction", listener);
- }
-
- /**
- * Adds a listener for the ArrowIndent property changes.
- * @param listener the listener to add.
- * @see #removeArrowIndentListener
- */
- public synchronized void addArrowIndentListener(PropertyChangeListener listener)
- {
- changes.addPropertyChangeListener("arrowIndent", listener);
- }
-
- /**
- * Removes a listener for the ArrowIndent property changes.
- * @param listener the listener to remove.
- * @see #addArrowIndentListener
- */
- public synchronized void removeArrowIndentListener(PropertyChangeListener listener)
- {
- changes.removePropertyChangeListener("arrowIndent", listener);
- }
-
- /**
- * Adds a vetoable listener for the ArrowIndent property changes.
- * @param listener the listener to add.
- * @see #removeArrowIndentListener
- */
- public synchronized void addArrowIndentListener(VetoableChangeListener listener)
- {
- vetos.addVetoableChangeListener("arrowIndent", listener);
- }
-
- /**
- * Removes a vetoable listener for the ArrowIndent property changes.
- * @param listener the listener to remove.
- * @see #addArrowIndentListener
- */
- public synchronized void removeArrowIndentListener(VetoableChangeListener listener)
- {
- vetos.removeVetoableChangeListener("arrowIndent", listener);
- }
-
- /**
- * This is the PropertyChangeEvent handling inner class for the constrained Direction property.
- * Handles vetoing Directions that are not valid.
- */
- class SizeVeto implements java.beans.VetoableChangeListener, java.io.Serializable
- {
- /**
- * This method gets called when an attempt to change the constrained Direction property is made.
- * Ensures the given direction size is valid for this button.
- *
- * @param e a <code>PropertyChangeEvent</code> object describing the
- * event source and the property that has changed.
- * @exception PropertyVetoException if the recipient wishes the property
- * change to be rolled back.
- */
- public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException
- {
- int i = ((Integer)e.getNewValue()).intValue();
- if (!isValidDirection(i))
- {
- throw new PropertyVetoException(errors.getString("InvalidDirection") + i, e);
- }
- }
- }
-
- /**
- * This is the PropertyChangeEvent handling inner class for the constrained ArrowIndent property.
- * Handles vetoing ArrowIndents that are not valid.
- */
- class IndntVeto implements java.beans.VetoableChangeListener, java.io.Serializable
- {
- /**
- * This method gets called when an attempt to change the constrained ArrowIndent property is made.
- * Ensures the given arrow indent size is valid for this button.
- *
- * @param e a <code>PropertyChangeEvent</code> object describing the
- * event source and the property that has changed.
- * @exception PropertyVetoException if the recipient wishes the property
- * change to be rolled back.
- */
- public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException
- {
- int i = ((Integer)e.getNewValue()).intValue();
- if (!isValidArrowIndent(i))
- {
- throw new PropertyVetoException(errors.getString("InvalidArrowIndent") + i, e);
- }
- }
- }
-
-
- /**
- * Maintains the buttonImage size and draws the
- * button in the buttonImage offscreen image.
- * @see symantec.itools.awt.ButtonBase#updateButtonImage
- */
- protected void updateButtonImage()
- {
- super.updateButtonImage();
- Graphics g = buttonImage.getGraphics();
- Dimension s = size();;
- int trueBevel = bevel + 1;
- int centerHorizontal;
- int centerVertical;
- int topSide;
- int bottomSide;
- int leftSide;
- int rightSide;
-
- if(isEnabled())
- {
- g.setColor(arrowColor);
- }
- else
- {
- g.setColor(disabledArrowColor);
- }
-
- centerHorizontal = ((s.width - 1) / 2) + pressedAdjustment;
- centerVertical = ((s.height - 1) / 2) + pressedAdjustment;
- topSide = (top + trueBevel - 1) + pressedAdjustment + indent;
- bottomSide = (s.height - 1 - bottom - trueBevel) + pressedAdjustment - indent;
- leftSide = (left + trueBevel - 1) + pressedAdjustment + indent;
- rightSide = (s.width - 1 - right - trueBevel) + pressedAdjustment - indent;
-
- if (symantec.itools.lang.OS.isMacintosh())
- {
- leftSide += 1;
- topSide += 1;
- }
-
- switch (direction)
- {
- case UP:
- {
- fillTriangle(g, centerHorizontal, topSide, leftSide, bottomSide, rightSide, bottomSide, direction);
- break;
- }
- case DOWN:
- {
- fillTriangle(g, centerHorizontal, bottomSide, leftSide, topSide, rightSide, topSide, direction);
- break;
- }
-
- case LEFT:
- {
- fillTriangle(g, leftSide, centerVertical, rightSide, bottomSide, rightSide, topSide, direction);
- break;
- }
-
- case RIGHT:
- {
- fillTriangle(g, rightSide, centerVertical, leftSide, bottomSide, leftSide, topSide, direction);
- break;
- }
- }
- if (g != null)
- g.dispose();
- }
-
- /**
- * Fills a triangle which has at least one side that is straight up and down or left and right.
- * @param g the Graphics to use to draw with.
- * @param tipX the horizontal coordinate of the point opposite a straight side.
- * @param tipY the vertical coordinate of the point opposite a straight side.
- * @param aX the horizontal coordinate of one of the two points defining the straight side.
- * @param aY the vertical coordinate of one of the two points defining the straight side.
- * @param bX the horizontal coordinate of one of the two points defining the straight side.
- * @param bY the vertical coordinate of one of the two points defining the straight side.
- * @param direction the direction of the straight line UP, DOWN, or LEFT, RIGHT.
- *
- * aX and bX should be the same for UP or Down. aY and bY should be the same for LEFT or RIGHT.
- * If not, then the a coordinates are used.
- *
- * @see #UP
- * @see #DOWN
- * @see #LEFT
- * @see #RIGHT
- */
- protected void fillTriangle(Graphics g, int tipX, int tipY, int aX, int aY, int bX, int bY, int direction)
- {
- int dist, max, min;
-
- switch(direction)
- {
- case UP:
- case DOWN:
- dist = Math.abs(aX - bX);
- max = Math.max(aX, bX);
- min = Math.min(aX, bX);
- for(int i = min; i <= max; ++i)
- {
- g.drawLine(tipX, tipY, i, aY);
- }
- break;
- case RIGHT:
- case LEFT:
- dist = Math.abs(aY - bY);
- max = Math.max(aY, bY);
- min = Math.min(aY, bY);
- for(int i = min; i <= max; ++i)
- {
- g.drawLine(tipX, tipY, aX, i);
- }
- break;
- }
- }
-
- /**
- * Is the given bevel size valid for this button.
- * @param i the given bevel size
- * @return true if the given bevel size is acceptable, false if not.
- */
- protected boolean isValidBevelSize(int i)
- {
- Dimension s = size();
-
- int temp = i * 2 + 4;
-
- if (i < 0 || s.width < temp || s.height < temp)
- return false;
- else
- return true;
- }
-
- /**
- * Is the given direction valid for this button.
- * @param i the given bevel size
- * @return true if the given direction is acceptable, false if not.
- */
- protected boolean isValidDirection(int i)
- {
- switch(i)
- {
- case LEFT:
- case RIGHT:
- case UP:
- case DOWN:
- return true;
- default:
- return false;
- }
- }
-
- /**
- * Is the given arrow indent is valid for this button.
- * @param i the given bevel size
- * @return true if the given indent size is acceptable, false if not.
- */
- protected boolean isValidArrowIndent(int i)
- {
- Dimension s = size();
-
- int temp = (i * 2) + (bevel + 1) * 2 + 4;
-
- if(i < 0 || s.width < temp || s.height < temp)
- return false;
- else
- return true;
- }
-
- /**
- * Called after addNotify to set the internally constrined properties to their
- * temporary values to validate them now that the component has been added to the form.
- * This is used to avoid code-gen order dependencies, since VC generates all property
- * manipulating code before adding the component to its container.
- * Subclasses should override this function for any internally constrained properties,
- * and call the super version in the overridden version.
- */
- protected void verifyContstrainedPropertyValues()
- {
- super.verifyContstrainedPropertyValues();
- try { setArrowIndent(tempIndent); } catch (PropertyVetoException exc) { /*Silently verify.*/ }
- }
-
- /**
- * The color of the arrow in the button.
- */
- protected Color arrowColor = null;
- /**
- * The color of the arrow when the button is disabled.
- */
- protected Color disabledArrowColor = null;
- /**
- * The direction the arrow points.
- * One of: LEFT, UP, RIGHT, or DOWN.
- * @see #LEFT
- * @see #UP
- * @see #RIGHT
- * @see #DOWN
- */
- protected int direction;
- /**
- * The number of pixels to shrink the arrow from the left side of the button.
- */
- protected int left;
- /**
- * The number of pixels to shrink the arrow from the right side of the button.
- */
- protected int right;
- /**
- * The number of pixels to shrink the arrow from the top side of the button.
- */
- protected int top;
- /**
- * The number of pixels to shrink the arrow from the bottom side of the button.
- */
- protected int bottom;
- /**
- * The margin around the arrow in pixels. 0 = arrow takes up entire button.
- */
- protected int indent;
- /**
- * Internal use.
- * Indent value stored until this component is added to a container.
- * It is then used to set the real indent value.
- * This avoids code-gen order dependencies.
- */
- protected int tempIndent;
- /**
- * Error strings.
- */
- transient protected ResourceBundle errors;
-
- private SizeVeto sizeVeto = null;
- private IndntVeto indentVeto = null;
- private symantec.itools.beans.VetoableChangeSupport vetos = new symantec.itools.beans.VetoableChangeSupport(this);
- private symantec.itools.beans.PropertyChangeSupport changes = new symantec.itools.beans.PropertyChangeSupport(this);
- }
-