diff options
Diffstat (limited to 'javax/swing/AbstractButton.java')
-rw-r--r-- | javax/swing/AbstractButton.java | 453 |
1 files changed, 398 insertions, 55 deletions
diff --git a/javax/swing/AbstractButton.java b/javax/swing/AbstractButton.java index 49c74dd06..d4e35cfa3 100644 --- a/javax/swing/AbstractButton.java +++ b/javax/swing/AbstractButton.java @@ -45,6 +45,7 @@ import java.awt.Insets; import java.awt.ItemSelectable; import java.awt.Point; import java.awt.Rectangle; +import java.awt.Shape; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; @@ -53,17 +54,26 @@ import java.awt.image.ImageObserver; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.Serializable; +import java.util.Enumeration; +import javax.accessibility.Accessible; import javax.accessibility.AccessibleAction; +import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleIcon; +import javax.accessibility.AccessibleRelation; import javax.accessibility.AccessibleRelationSet; +import javax.accessibility.AccessibleState; import javax.accessibility.AccessibleStateSet; import javax.accessibility.AccessibleText; import javax.accessibility.AccessibleValue; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.plaf.ButtonUI; +import javax.swing.plaf.basic.BasicHTML; import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.Position; +import javax.swing.text.View; /** @@ -277,6 +287,42 @@ public abstract class AbstractButton extends JComponent protected ChangeEvent changeEvent = new ChangeEvent(this); /** + * Indicates if the borderPainted property has been set by a client + * program or by the UI. + * + * @see #setUIProperty(String, Object) + * @see LookAndFeel#installProperty(JComponent, String, Object) + */ + private boolean clientBorderPaintedSet = false; + + /** + * Indicates if the rolloverEnabled property has been set by a client + * program or by the UI. + * + * @see #setUIProperty(String, Object) + * @see LookAndFeel#installProperty(JComponent, String, Object) + */ + private boolean clientRolloverEnabledSet = false; + + /** + * Indicates if the iconTextGap property has been set by a client + * program or by the UI. + * + * @see #setUIProperty(String, Object) + * @see LookAndFeel#installProperty(JComponent, String, Object) + */ + private boolean clientIconTextGapSet = false; + + /** + * Indicates if the contentAreaFilled property has been set by a client + * program or by the UI. + * + * @see #setUIProperty(String, Object) + * @see LookAndFeel#installProperty(JComponent, String, Object) + */ + private boolean clientContentAreaFilledSet = false; + + /** * Fired in a PropertyChangeEvent when the "borderPainted" property changes. */ public static final String BORDER_PAINTED_CHANGED_PROPERTY = "borderPainted"; @@ -390,10 +436,27 @@ public abstract class AbstractButton extends JComponent // Nothing to do here yet. } + /** + * Returns the accessible state set of this object. In addition to the + * superclass's states, the <code>AccessibleAbstractButton</code> + * supports the following states: {@link AccessibleState#ARMED}, + * {@link AccessibleState#FOCUSED}, {@link AccessibleState#PRESSED} and + * {@link AccessibleState#CHECKED}. + * + * @return the curren state of this accessible object + */ public AccessibleStateSet getAccessibleStateSet() - throws NotImplementedException { - return null; // TODO + AccessibleStateSet state = super.getAccessibleStateSet(); + + if (getModel().isArmed()) + state.add(AccessibleState.ARMED); + if (getModel().isPressed()) + state.add(AccessibleState.PRESSED); + if (isSelected()) + state.add(AccessibleState.CHECKED); + + return state; } /** @@ -407,101 +470,300 @@ public abstract class AbstractButton extends JComponent return result; } + /** + * Returns the accessible icons of this object. If the AbstractButton's + * icon is an Accessible, and it's AccessibleContext is an AccessibleIcon, + * then this AccessibleIcon is returned, otherwise <code>null</code>. + * + * @return the accessible icons of this object, or <code>null</code> if + * there is no accessible icon + */ public AccessibleIcon[] getAccessibleIcon() - throws NotImplementedException { - return null; // TODO + AccessibleIcon[] ret = null; + Icon icon = getIcon(); + if (icon instanceof Accessible) + { + AccessibleContext ctx = ((Accessible) icon).getAccessibleContext(); + if (ctx instanceof AccessibleIcon) + { + ret = new AccessibleIcon[]{ (AccessibleIcon) ctx }; + } + } + return ret; } + /** + * Returns the accessible relations of this AccessibleAbstractButton. + * If the AbstractButton is part of a ButtonGroup, then all the buttons + * in this button group are added as targets in a MEMBER_OF relation, + * otherwise an empty relation set is returned (from super). + * + * @return the accessible relations of this AccessibleAbstractButton + */ public AccessibleRelationSet getAccessibleRelationSet() - throws NotImplementedException { - // TODO: What should be modified here? - return super.getAccessibleRelationSet(); + AccessibleRelationSet relations = super.getAccessibleRelationSet(); + ButtonModel model = getModel(); + if (model instanceof DefaultButtonModel) + { + ButtonGroup group = ((DefaultButtonModel) model).getGroup(); + if (group != null) + { + Object[] target = new Object[group.getButtonCount()]; + Enumeration els = group.getElements(); + + for (int index = 0; els.hasMoreElements(); ++index) + { + target[index] = els.nextElement(); + } + + AccessibleRelation rel = + new AccessibleRelation(AccessibleRelation.MEMBER_OF); + rel.setTarget(target); + relations.add(rel); + } + } + return relations; } + /** + * Returns the accessible action associated with this object. For buttons, + * this will be <code>this</code>. + * + * @return <code>this</code> + */ public AccessibleAction getAccessibleAction() - throws NotImplementedException { - return null; // TODO + return this; } + /** + * Returns the accessible value of this AccessibleAbstractButton, which + * is always <code>this</code>. + * + * @return the accessible value of this AccessibleAbstractButton, which + * is always <code>this</code> + */ public AccessibleValue getAccessibleValue() - throws NotImplementedException { - return null; // TODO + return this; } + /** + * Returns the number of accessible actions that are supported by this + * object. Buttons support one action by default ('press button'), so this + * method always returns <code>1</code>. + * + * @return <code>1</code>, the number of supported accessible actions + */ public int getAccessibleActionCount() - throws NotImplementedException { - return 0; // TODO + return 1; } - public String getAccessibleActionDescription(int value0) - throws NotImplementedException + /** + * Returns a description for the action with the specified index or + * <code>null</code> if such action does not exist. + * + * @param actionIndex the zero based index to the actions + * + * @return a description for the action with the specified index or + * <code>null</code> if such action does not exist + */ + public String getAccessibleActionDescription(int actionIndex) { - return null; // TODO + String descr = null; + if (actionIndex == 0) + { + // FIXME: Supply localized descriptions in the UIDefaults. + descr = UIManager.getString("AbstractButton.clickText"); + } + return descr; } - public boolean doAccessibleAction(int value0) - throws NotImplementedException + /** + * Performs the acccessible action with the specified index on this object. + * Since buttons have only one action by default (which is to press the + * button), this method performs a 'press button' when the specified index + * is <code>0</code> and nothing otherwise. + * + * @param actionIndex a zero based index into the actions of this button + * + * @return <code>true</code> if the specified action has been performed + * successfully, <code>false</code> otherwise + */ + public boolean doAccessibleAction(int actionIndex) { - return false; // TODO + boolean retVal = false; + if (actionIndex == 0) + { + doClick(); + retVal = true; + } + return retVal; } + /** + * Returns the current value of this object as a number. This + * implementation returns an <code>Integer(1)</code> if the button is + * selected, <code>Integer(0)</code> if the button is not selected. + * + * @return the current value of this object as a number + */ public Number getCurrentAccessibleValue() - throws NotImplementedException { - return null; // TODO + Integer retVal; + if (isSelected()) + retVal = new Integer(1); + else + retVal = new Integer(0); + return retVal; } - public boolean setCurrentAccessibleValue(Number value0) - throws NotImplementedException + /** + * Sets the current accessible value as object. If the specified number + * is 0 the button will be deselected, otherwise the button will + * be selected. + * + * @param value 0 for deselected button, other for selected button + * + * @return <code>true</code> if the value has been set, <code>false</code> + * otherwise + */ + public boolean setCurrentAccessibleValue(Number value) { - return false; // TODO + boolean retVal = false; + if (value != null) + { + if (value.intValue() == 0) + setSelected(false); + else + setSelected(true); + retVal = true; + } + return retVal; } + /** + * Returns the minimum accessible value for the AccessibleAbstractButton, + * which is <code>0</code>. + * + * @return the maxinimum accessible value for the AccessibleAbstractButton, + * which is <code>1</code> + */ public Number getMinimumAccessibleValue() - throws NotImplementedException { - return null; // TODO + return new Integer(0); } + /** + * Returns the maximum accessible value for the AccessibleAbstractButton, + * which is <code>1</code>. + * + * @return the maximum accessible value for the AccessibleAbstractButton, + * which is <code>1</code> + */ public Number getMaximumAccessibleValue() - throws NotImplementedException { - return null; // TODO + return new Integer(1); } + /** + * Returns the accessible text for this AccessibleAbstractButton. This + * will be <code>null</code> if the button has a non-HTML label, otherwise + * <code>this</code>. + * + * @return the accessible text for this AccessibleAbstractButton + */ public AccessibleText getAccessibleText() - throws NotImplementedException { - return null; // TODO + AccessibleText accessibleText = null; + if (getClientProperty(BasicHTML.propertyKey) != null) + accessibleText = this; + + return accessibleText; } - public int getIndexAtPoint(Point value0) - throws NotImplementedException + /** + * Returns the index of the label's character at the specified point, + * relative to the local bounds of the button. This only works for + * HTML labels. + * + * @param p the point, relative to the buttons local bounds + * + * @return the index of the label's character at the specified point + */ + public int getIndexAtPoint(Point p) { - return 0; // TODO + int index = -1; + View view = (View) getClientProperty(BasicHTML.propertyKey); + if (view != null) + { + Rectangle shape = new Rectangle(0, 0, getWidth(), getHeight()); + index = view.viewToModel(p.x, p.y, shape, new Position.Bias[1]); + } + return index; } - public Rectangle getCharacterBounds(int value0) - throws NotImplementedException + /** + * Returns the bounds of the character at the specified index of the + * button's label. This will only work for HTML labels. + * + * @param i the index of the character of the label + * + * @return the bounds of the character at the specified index of the + * button's label + */ + public Rectangle getCharacterBounds(int i) { - return null; // TODO + Rectangle rect = null; + View view = (View) getClientProperty(BasicHTML.propertyKey); + if (view != null) + { + Rectangle shape = new Rectangle(0, 0, getWidth(), getHeight()); + try + { + Shape s = view.modelToView(i, shape, Position.Bias.Forward); + rect = s.getBounds(); + } + catch (BadLocationException ex) + { + rect = null; + } + } + return rect; } + /** + * Returns the number of characters in the button's label. + * + * @return the bounds of the character at the specified index of the + * button's label + */ public int getCharCount() - throws NotImplementedException { - return 0; // TODO + int charCount; + View view = (View) getClientProperty(BasicHTML.propertyKey); + if (view != null) + { + charCount = view.getDocument().getLength(); + } + else + { + charCount = getAccessibleName().length(); + } + return charCount; } + /** + * This always returns <code>-1</code> since there is no caret in a button. + * + * @return <code>-1</code> since there is no caret in a button + */ public int getCaretPosition() - throws NotImplementedException { - return 0; // TODO + return -1; } public String getAtIndex(int value0, int value1) @@ -522,34 +784,57 @@ public abstract class AbstractButton extends JComponent return null; // TODO } - public AttributeSet getCharacterAttribute(int value0) - throws NotImplementedException + /** + * Returns the text attribute for the character at the specified character + * index. + * + * @param i the character index + * + * @return the character attributes for the specified character or + * <code>null</code> if the character has no attributes + */ + public AttributeSet getCharacterAttribute(int i) { - return null; // TODO + AttributeSet atts = null; + View view = (View) getClientProperty(BasicHTML.propertyKey); + if (view != null) + { + + } + return atts; } + /** + * This always returns <code>-1</code> since + * button labels can't be selected. + * + * @return <code>-1</code>, button labels can't be selected + */ public int getSelectionStart() - throws NotImplementedException { - return 0; // TODO + return -1; } + /** + * This always returns <code>-1</code> since + * button labels can't be selected. + * + * @return <code>-1</code>, button labels can't be selected + */ public int getSelectionEnd() - throws NotImplementedException { - return 0; // TODO + return -1; } + /** + * Returns the selected text. This always returns <code>null</code> since + * button labels can't be selected. + * + * @return <code>null</code>, button labels can't be selected + */ public String getSelectedText() - throws NotImplementedException { - return null; // TODO - } - - private Rectangle getTextRectangle() - throws NotImplementedException - { - return null; // TODO + return null; } } @@ -939,6 +1224,7 @@ public abstract class AbstractButton extends JComponent */ public void setRolloverEnabled(boolean r) { + clientRolloverEnabledSet = true; if (rollOverEnabled != r) { rollOverEnabled = r; @@ -1171,6 +1457,7 @@ public abstract class AbstractButton extends JComponent */ public void setBorderPainted(boolean b) { + clientBorderPaintedSet = true; if (borderPainted == b) return; boolean old = borderPainted; @@ -1321,6 +1608,7 @@ public abstract class AbstractButton extends JComponent */ public void setIconTextGap(int i) { + clientIconTextGapSet = true; if (iconTextGap == i) return; @@ -1954,6 +2242,7 @@ public abstract class AbstractButton extends JComponent */ public void setContentAreaFilled(boolean b) { + clientContentAreaFilledSet = true; if (contentAreaFilled == b) return; @@ -2081,4 +2370,58 @@ public abstract class AbstractButton extends JComponent multiClickThreshhold = threshhold; } + + /** + * Helper method for + * {@link LookAndFeel#installProperty(JComponent, String, Object)}. + * + * @param propertyName the name of the property + * @param value the value of the property + * + * @throws IllegalArgumentException if the specified property cannot be set + * by this method + * @throws ClassCastException if the property value does not match the + * property type + * @throws NullPointerException if <code>c</code> or + * <code>propertyValue</code> is <code>null</code> + */ + void setUIProperty(String propertyName, Object value) + { + if (propertyName.equals("borderPainted")) + { + if (! clientBorderPaintedSet) + { + setBorderPainted(((Boolean) value).booleanValue()); + clientBorderPaintedSet = false; + } + } + else if (propertyName.equals("rolloverEnabled")) + { + if (! clientRolloverEnabledSet) + { + setRolloverEnabled(((Boolean) value).booleanValue()); + clientRolloverEnabledSet = false; + } + } + else if (propertyName.equals("iconTextGap")) + { + if (! clientIconTextGapSet) + { + setIconTextGap(((Integer) value).intValue()); + clientIconTextGapSet = false; + } + } + else if (propertyName.equals("contentAreaFilled")) + { + if (! clientContentAreaFilledSet) + { + setContentAreaFilled(((Boolean) value).booleanValue()); + clientContentAreaFilledSet = false; + } + } + else + { + super.setUIProperty(propertyName, value); + } + } } |