home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programming Languages Suite
/
ProgLangD.iso
/
VCAFE.3.0A
/
Main.bin
/
Slider.java
< prev
next >
Wrap
Text File
|
1998-10-15
|
28KB
|
914 lines
package symantec.itools.awt;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.AWTEventMulticaster;
import java.awt.event.ActionEvent;
import java.beans.PropertyVetoException;
import java.beans.PropertyChangeListener;
import java.beans.VetoableChangeListener;
import java.beans.PropertyChangeEvent;
import java.awt.event.ActionListener;
import java.awt.AWTEvent;
import java.util.ResourceBundle;
// 02/15/97 RKM Added change checking on setter before invalidating
// Added range checking in setValue
// 02/27/97 RKM Merged Scott's change to call invalidate in setValue
// 05/11/97 CAR Added a call to validate for all setters.
// 05/30/97 MSH Updated to Java 1.1
// 07/17/97 LAB Added add/removePropertyChangeListener and add/removeVetoableChangeListener event
// registration functions. Added setTickSyle. Moved doMove() from Horizontal and Vertical
// Slider into Slider since they were the same. Moved Action Listener/Event stuff into
// base class since it's the same. In general, moved thigs common in Vertical and Horzontal
// slider into Slider. Made setTickFreq() bound and constrained.
// 07/22/97 LAB Moved SliderTick class from Slider.java into it's own file at
// compiler's request.
// 07/24/97 CAR marked field transient as needed
// 08/12/97 RKM Lower cased property names when firing change and veto stuff
// Remove calls to validate after invalidate (caused D'Arcy problems)
// 08/26/97 CAR setTickFreq will not set the freq greater than the slider's max value -1
// 08/27/97 RKM Changed invalidate calls to repaints, moved code from validate to paint
// Removed reshape override
// 08/27/97 CAR fixed bug re: setValue was inadvertantly dependant on setTickFreq
// 10/05/97 LAB Constrained min and max so max can't be larger than min (Addresses Mac Bug #8844).
// 10/06/97 LAB Made setMaxValue and setMinValue set the temp values to the current
// value when changing the current value. Changed getMinValue and
// getMaxValue 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 (Address Mac Bug #9022).
// 10/17/97 LAB Fixed order dependence with value, and tick frequency (Addresses Mac Bug #9296).
/**
* Components based on this class are used to select
* one value from a continuous range of values. It has a movable thumb in
* front of a gauge with ticks marks on it.
* <p>
* @see symantec.itools.awt.HorizontalSlider
* @see symantec.itools.awt.VerticalSlider
* @version 1.1, July 17, 1997
* @author Symantec
*/
public abstract class Slider extends Canvas
{
/**
* Defines the slider tick style where the tick marks appear to the left of
* the slider thumb.
*/
public static final int TICK_LEFT = 0;
/**
* Defines the slider tick style where the tick marks appear to the right of
* the slider thumb.
*/
public static final int TICK_RIGHT = 1;
/**
* Defines the slider tick style where the tick marks appear below
* the slider thumb.
*/
public static final int TICK_BOTTOM = TICK_LEFT;
/**
* Defines the slider tick style where the tick marks appear above
* the slider thumb.
*/
public static final int TICK_TOP = TICK_RIGHT;
/**
* Defines the slider tick style where the tick marks appear both
* to the left and right of the slider thumb.
*/
public static final int TICK_BOTH = 2;
/**
* Defines the slider tick style where no tick marks are drawn.
*/
public static final int TICK_NONE = 3;
/**
* Constructs the Slider.
*/
protected Slider()
{
this.style = TICK_BOTH;
this.min = 1;
this.max = 10;
this.freq = 1;
prevPos =
curPos = 0;
height = 50;
showBorder = true;
tick = null;
tempMinValue = min;
tempMaxValue = max;
tempTickFreq = this.freq;
tempValue = curPos;
isAdded = false;
}
/**
* Sets the current slider tick mark style.
*
* @param style the new tick mark style, one of TICK_LEFT, TICK_RIGHT, TICK_TOP, TICK_BOTTOM, TICK_BOTH, or TICK_NONE
* @see #getTickStyle
* @see #TICK_LEFT
* @see #TICK_RIGHT
* @see #TICK_TOP
* @see #TICK_BOTTOM
* @see #TICK_BOTH
* @see #TICK_NONE
* @exception PropertyVetoException
* if the specified property value is unacceptable
*/
public void setTickStyle(int style) throws PropertyVetoException
{
if (this.style != style)
{
Integer oldValue = new Integer( this.style );
Integer newValue = new Integer( style );
vetos.fireVetoableChange( "tickStyle", oldValue, newValue );
this.style = style;
changes.firePropertyChange( "tickStyle", oldValue, newValue );
forceCallDoReshape = true;
}
}
/**
* Returns the current slider tick mark style.
* @return one of: TICK_LEFT, TICK_RIGHT, TICK_TOP, TICK_BOTTOM, TICK_BOTH, or TICK_NONE
* @see #TICK_LEFT
* @see #TICK_RIGHT
* @see #TICK_TOP
* @see #TICK_BOTTOM
* @see #TICK_BOTH
* @see #TICK_NONE
*/
public int getTickStyle()
{
return style;
}
/**
* Sets the minimum value of the slider.
* @param min the new minimum slider value
* @see #getMinValue
* @see #setMaxValue
* @exception PropertyVetoException
* if the specified property value is unacceptable
*/
public void setMinValue(int min) throws PropertyVetoException
{
if(isAdded)
{
if (this.min != min)
{
Integer oldValue = new Integer( this.min );
Integer newValue = new Integer( min );
vetos.fireVetoableChange( "minValue", oldValue, newValue );
this.min = min;
tempMinValue = min;
changes.firePropertyChange( "minValue", oldValue, newValue );
forceCallDoReshape = true;
repaint();
}
}
//We store the value until we are added then set the value to avoid code-gen order dependencies.
else
{
tempMinValue = min;
}
}
/**
* Returns the current minimum value of the slider.
* @see #setMinValue
* @see #getMaxValue
*/
public int getMinValue()
{
return isAdded ? min : tempMinValue;
}
/**
* Sets the maximum value of the slider.
* @param max the new maximum slider value
* @see #getMaxValue
* @see #setMinValue
* @exception PropertyVetoException
* if the specified property value is unacceptable
*/
public void setMaxValue(int max) throws PropertyVetoException
{
if(isAdded)
{
if (this.max != max)
{
Integer oldValue = new Integer( this.max );
Integer newValue = new Integer( max );
vetos.fireVetoableChange( "maxValue", oldValue, newValue );
this.max = max;
tempMaxValue = max;
changes.firePropertyChange( "maxValue", oldValue, newValue );
forceCallDoReshape = true;
repaint();
}
}
//We store the value until we are added then set the value to avoid code-gen order dependencies.
else
{
tempMaxValue = max;
}
}
/**
* Returns the current maximum value of the slider.
* @see #setMaxValue
* @see #getMinValue
*/
public int getMaxValue()
{
return isAdded ? max : tempMaxValue;
}
/**
* Sets the tick mark display frequency.
* This is the range in value between each tick mark.
* @param freq the range in value between tick marks
* @exception PropertyVetoException
* if the specified property value is unacceptable
* @see #getTickFreq
*/
public void setTickFreq(int freq) throws PropertyVetoException
{
if(isAdded)
{
if (this.freq != freq)
{
if(freq >= max)
freq = max - 1;
Integer oldValue = new Integer(this.freq);
Integer newValue = new Integer(freq);
vetos.fireVetoableChange( "tickFreq", oldValue, newValue );
int pos = curPos * this.freq + min;
this.freq = freq;
doMove((pos - min) / this.freq, false);
changes.firePropertyChange( "tickFreq", oldValue, newValue );
forceCallDoReshape = true;
repaint();
}
}
tempTickFreq = freq;
}
/**
* Returns the current tick mark display frequency.
* This is the range in value between each tick mark.
* @return the range in value between tick marks
* @see #setTickFreq
*/
public int getTickFreq()
{
if(isAdded)
{
return freq;
}
else
{
return tempTickFreq;
}
}
/**
* Sets the slider value.
* @param pos the new slider value
* @see #getValue
* @exception PropertyVetoException
* if the specified property value is unacceptable
*/
public void setValue(int pos) throws PropertyVetoException
{
if(isAdded)
{
//Do range checking on pos
Integer oldValue = new Integer( curPos * freq + min );
Integer newValue = new Integer( pos );
vetos.fireVetoableChange( "value", oldValue, newValue );
if (pos < getMinValue())
pos = getMinValue();
else if (pos > getMaxValue())
pos = getMaxValue();
doMove((pos - min) / freq, false);
changes.firePropertyChange( "value", oldValue, newValue );
forceCallDoReshape = true;
repaint();
}
tempValue = pos;
}
/**
* Returns the current slider value.
* @see #setValue
*/
public int getValue()
{
if(isAdded)
{
return curPos * freq + min;
}
else
{
return tempValue;
}
}
/**
* Sets the border display flag.
* @param f true for the border to show
* @see #getShowBorder
* @exception PropertyVetoException
* if the specified property value is unacceptable
*/
public void setShowBorder(boolean f) throws PropertyVetoException
{
if (showBorder != f)
{
Boolean oldValue = new Boolean( showBorder );
Boolean newValue = new Boolean( f );
vetos.fireVetoableChange( "showBorder", oldValue, newValue );
showBorder = f;
changes.firePropertyChange( "showBorder", oldValue, newValue );
repaint();
}
}
/**
* @deprecated
* @see #isShowBorder
*/
public boolean getShowBorder()
{
return isShowBorder();
}
/**
* Returns the current border display flag.
* @return true if the border is visible
* @see #setShowBorder
* @see #getShowBorder
*/
public boolean isShowBorder()
{
return showBorder;
}
/**
* Sets the command name of the action event fired by this component.
* @param command The name of the action event command fired by this component
* @exception PropertyVetoException
* if the specified property value is unacceptable
*/
public void setActionCommand(String command) throws PropertyVetoException
{
String oldValue = actionCommand;
vetos.fireVetoableChange("actionCommand", oldValue, command);
actionCommand = command;
changes.firePropertyChange("actionCommand", oldValue, command);
}
/**
* @return the command name of the action event fired by this component.
*/
public String getActionCommand()
{
return actionCommand;
}
/**
* 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.
* It is also used to setup the component, creating the TextField as needed.
*
* @see #removeNotify
*/
public synchronized void addNotify()
{
super.addNotify();
errors = ResourceBundle.getBundle("symantec.itools.resources.ErrorsBundle");
//Hook up listeners
if (maxVeto == null)
{
maxVeto = new MaxVeto();
addMaxValueListener(maxVeto);
}
if (minVeto == null)
{
minVeto = new MinVeto();
addMinValueListener(minVeto);
}
isAdded = true;
verifyContstrainedPropertyValues();
}
/**
* 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 (maxVeto != null)
{
removeMaxValueListener(maxVeto);
maxVeto = null;
}
if (minVeto != null)
{
removeMinValueListener(minVeto);
minVeto = null;
}
super.removeNotify();
isAdded = false;
}
/**
* Adds a listener for the max property changes.
* @param listener the listener to add.
* @see #removeMaxValueListener(java.beans.PropertyChangeListener)
*/
public synchronized void addMaxValueListener(PropertyChangeListener listener)
{
changes.addPropertyChangeListener("maxValue", listener);
}
/**
* Removes a listener for the max property changes.
* @param listener the listener to remove.
* @see #addMaxValueListener(java.beans.PropertyChangeListener)
*/
public synchronized void removeMaxValueListener(PropertyChangeListener listener)
{
changes.removePropertyChangeListener("maxValue", listener);
}
/**
* Adds a vetoable listener for the max property changes.
* @param listener the listener to add.
* @see #removeMaxValueListener(java.beans.VetoableChangeListener)
*/
public synchronized void addMaxValueListener(VetoableChangeListener listener)
{
vetos.addVetoableChangeListener("maxValue", listener);
}
/**
* Removes a vetoable listener for the max property changes.
* @param listener the listener to remove.
* @see #addMaxValueListener(java.beans.VetoableChangeListener)
*/
public synchronized void removeMaxValueListener(VetoableChangeListener listener)
{
vetos.removeVetoableChangeListener("maxValue", listener);
}
/**
* Adds a listener for the min property changes.
* @param listener the listener to add.
* @see #removeMinValueListener(java.beans.PropertyChangeListener)
*/
public synchronized void addMinValueListener(PropertyChangeListener listener)
{
changes.addPropertyChangeListener("minValue", listener);
}
/**
* Removes a listener for the min property changes.
* @param listener the listener to remove.
* @see #addMinValueListener(java.beans.PropertyChangeListener)
*/
public synchronized void removeMinValueListener(PropertyChangeListener listener)
{
changes.removePropertyChangeListener("minValue", listener);
}
/**
* Adds a vetoable listener for the min property changes.
* @param listener the listener to add.
* @see #removeMinValueListener(java.beans.VetoableChangeListener)
*/
public synchronized void addMinValueListener(VetoableChangeListener listener)
{
vetos.addVetoableChangeListener("minValue", listener);
}
/**
* Removes a vetoable listener for the min property changes.
* @param listener the listener to remove.
* @see #addMinValueListener(java.beans.VetoableChangeListener)
*/
public synchronized void removeMinValueListener(VetoableChangeListener listener)
{
vetos.removeVetoableChangeListener("minValue", listener);
}
/**
* This is the PropertyChangeEvent handling inner class for the constrained Max property.
* Handles vetoing Max values that are not valid.
*/
class MaxVeto implements java.beans.VetoableChangeListener, java.io.Serializable
{
/**
* This method gets called when an attempt to change the constrained Current property is made.
* Ensures the given Max value is valid for this component.
*
* @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 (!isValidMaxValue(i))
{
throw new PropertyVetoException(errors.getString("InvalidMaxValue") + i, e);
}
}
}
/**
* This is the PropertyChangeEvent handling inner class for the constrained Min property.
* Handles vetoing Min values that are not valid.
*/
class MinVeto implements java.beans.VetoableChangeListener, java.io.Serializable
{
/**
* This method gets called when an attempt to change the constrained Current property is made.
* Ensures the given Min value is valid for this component.
*
* @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 (!isValidMinValue(i))
{
throw new PropertyVetoException(errors.getString("InvalidMinValue") + i, e);
}
}
}
/**
* Is the given value valid for the Max property .
* @param i the given value
* @return true if the given value is acceptable, false if not.
*/
protected boolean isValidMaxValue(int i)
{
return (i >= min);
}
/**
* Is the given value valid for the Min property .
* @param i the given value
* @return true if the given value is acceptable, false if not.
*/
protected boolean isValidMinValue(int i)
{
return (i <= max);
}
/**
* 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()
{
try { setMinValue(tempMinValue); } catch (PropertyVetoException exc) { /*Silently verify.*/ }
try { setMaxValue(tempMaxValue); } catch (PropertyVetoException exc) { /*Silently verify.*/ }
try { setTickFreq(tempTickFreq); } catch (PropertyVetoException exc) { /*Silently verify.*/ }
try { setValue(tempValue); } catch (PropertyVetoException exc) { /*Silently verify.*/ }
}
/**
* This abstract function is called by reshape. Override it to change the way the Slider
* is reshaped.
*/
protected abstract void do_reshape(int w, int h);
/**
* This routine updates the thumb position, paints the Slider, and
* posts a new action event as needed. If the thumb position has
* changed or the forcePost parameter is true the component will be painted
* and an action event posted.
* @param pos the new thumb position
* @param forcePost true forces painting the slider and posting of an action
* event even if the thumb position hasn't changed
*/
protected void doMove(int pos, boolean forcePost)
{
if (tick == null)
{
prevPos = curPos = pos;
return;
}
if (pos >= tick.length)
pos = tick.length - 1;
if (pos != curPos || forcePost)
{
prevPos = curPos;
curPos = pos;
Graphics g = getGraphics();
paint(g);
if (g != null)
g.dispose();
g = null;
sourceActionEvent();
}
}
public void paint(Graphics g)
{
boolean callDoReshape = false;
//If size of component changes, we want to call do_reshape
Dimension currentSize = getSize();
if (!symantec.itools.util.GeneralUtils.objectsEqual(cachedSize,currentSize))
{
cachedSize = currentSize;
width = cachedSize.width;
height = cachedSize.height;
callDoReshape = true;
}
if (forceCallDoReshape || callDoReshape)
{
do_reshape(width, height);
forceCallDoReshape = false;
}
}
/**
* Handles the mouse pressing or dragging this component's thumb.
* It is not typically called directly.
* @param i the mouse horizontal or vertical position coordinate
* @param forcePost true forces painting the slider and posting of an action
* event even if the thumb position hasn't changed
*/
protected void moveThumb(int i, boolean forcePost)
{
if(tick.length > 1)
{
float tickPixDist = ((float)(tick[tick.length - 1].c - tick[0].c)) / ((float)(tick.length - 1));
if (tickPixDist == 0)
return;
float newPos = ((float)(i - tick[0].c)) / tickPixDist;
if (newPos < 0)
newPos = 0;
doMove(Math.round(newPos), forcePost);
}
}
/**
* Adds the specified action listener to receive action events
* from this component.
* @param l the action listener
*/
public synchronized void addActionListener(ActionListener l)
{
actionListener = AWTEventMulticaster.add(actionListener, l);
}
/**
* Removes the specified action listener so it no longer receives
* action events from this component.
* @param l the action listener
*/
public synchronized void removeActionListener(ActionListener l)
{
actionListener = AWTEventMulticaster.remove(actionListener, l);
}
/**
* Adds a listener for all event changes.
* @param listener the listener to add.
* @see #removePropertyChangeListener
*/
public synchronized void addPropertyChangeListener(PropertyChangeListener 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)
{
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)
{
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)
{
vetos.removeVetoableChangeListener(listener);
}
/**
* Fire an action event to the listeners
*/
protected void sourceActionEvent()
{
if (actionListener != null)
actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, actionCommand));
}
/**
* The current component width.
*/
protected int width;
/**
* The current component height.
*/
protected int height;
/**
* The size of the component, the last time paint was called.
*/
protected Dimension cachedSize = null;
/**
* Set if paint override should call DoReshape, even if the size has not changed.
*/
protected boolean forceCallDoReshape = false;
/**
* The current slider tick mark style.
*/
protected int style;
/**
* The current tick mark display frequency.
*/
protected int freq;
/**
* Internal use.
* Tick frequency value stored until this component is added to a container.
* It is then used to set the real property value.
* This avoids code-gen order dependencies.
*/
protected int tempTickFreq;
/**
* The minimum value of the slider range.
*/
protected int min;
/**
* Internal use.
* Min value stored until this component is added to a container.
* It is then used to set the real property value.
* This avoids code-gen order dependencies.
*/
protected int tempMinValue;
/**
* The maximum value of the slider range.
*/
protected int max;
/**
* Internal use.
* Max value stored until this component is added to a container.
* It is then used to set the real property value.
* This avoids code-gen order dependencies.
*/
protected int tempMaxValue;
/**
* The position of the slider thumb last time control painted.
*/
protected int prevPos;
/**
* The current position of the slider thumb.
*/
protected int curPos;
/**
* Internal use.
* Slider value stored until this component is added to a container.
* It is then used to set the real property value.
* This avoids code-gen order dependencies.
*/
protected int tempValue;
/**
* Flag indicating if border should be drawn.
*/
protected boolean showBorder;
/**
* The action listener to keep track of listeners for our action event.
*/
protected ActionListener actionListener = null;
/**
* The command name of the action event fired by this component.
*/
protected String actionCommand = "Slider Moved";
/**
* is the component added to a container hierarchy?
*/
protected boolean isAdded = false;
/**
* The tick marks for this slider.
*/
transient protected SliderTick tick[];
/**
* Drawing constant for the horizontal axis.
*/
protected static final int BORDER_X = 15;
/**
* Drawing constant for the vertical axis.
*/
protected static final int BORDER_Y = 10;
/**
* Error strings.
*/
transient protected ResourceBundle errors;
private MaxVeto maxVeto = null;
private MinVeto minVeto = 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);
}