From 480ccb4bfcc622c1ce320c20ce992188187f7573 Mon Sep 17 00:00:00 2001 From: Andrew John Hughes Date: Mon, 1 May 2006 21:45:41 +0000 Subject: 2006-05-01 Andrew John Hughes * Merge HEAD-->generics-branch for the period 2006-04-13 to 2006-05-01. --- javax/accessibility/AccessibleAction.java | 22 ++ javax/accessibility/AccessibleRole.java | 50 ++++ javax/accessibility/AccessibleState.java | 31 ++ javax/net/ssl/HttpsURLConnection.java | 8 +- javax/swing/ActionMap.java | 5 +- javax/swing/DefaultListSelectionModel.java | 13 +- javax/swing/ImageIcon.java | 94 +++--- javax/swing/JButton.java | 66 +++- javax/swing/JComboBox.java | 35 ++- javax/swing/JComponent.java | 45 +-- javax/swing/JDesktopPane.java | 32 +- javax/swing/JInternalFrame.java | 49 +-- javax/swing/JLabel.java | 1 + javax/swing/JList.java | 180 ++++++++--- javax/swing/JMenu.java | 14 +- javax/swing/JMenuItem.java | 34 ++- javax/swing/JPanel.java | 83 ++++- javax/swing/JProgressBar.java | 23 +- javax/swing/JRadioButtonMenuItem.java | 35 ++- javax/swing/JScrollPane.java | 1 - javax/swing/JSeparator.java | 83 +++-- javax/swing/JSlider.java | 30 +- javax/swing/JSpinner.java | 4 + javax/swing/JSplitPane.java | 130 +++++--- javax/swing/JTabbedPane.java | 16 + javax/swing/JTable.java | 28 +- javax/swing/JToolBar.java | 30 +- javax/swing/JToolTip.java | 2 +- javax/swing/JTree.java | 113 ++++--- javax/swing/ProgressMonitor.java | 6 +- javax/swing/RepaintManager.java | 60 ++-- javax/swing/ScrollPaneLayout.java | 2 +- javax/swing/SpinnerDateModel.java | 96 +++--- javax/swing/SpinnerNumberModel.java | 30 +- javax/swing/UIManager.java | 4 +- javax/swing/ViewportLayout.java | 14 +- javax/swing/border/AbstractBorder.java | 55 ++-- javax/swing/border/BevelBorder.java | 18 ++ javax/swing/border/CompoundBorder.java | 4 + javax/swing/border/EtchedBorder.java | 10 + javax/swing/border/LineBorder.java | 16 +- javax/swing/border/MatteBorder.java | 4 + javax/swing/border/TitledBorder.java | 10 +- javax/swing/event/ChangeEvent.java | 33 +- javax/swing/event/ChangeListener.java | 32 +- javax/swing/event/TableColumnModelListener.java | 88 +++--- javax/swing/plaf/basic/BasicComboBoxUI.java | 4 + javax/swing/plaf/basic/BasicComboPopup.java | 4 + javax/swing/plaf/basic/BasicInternalFrameUI.java | 4 + javax/swing/plaf/basic/BasicLabelUI.java | 4 + javax/swing/plaf/basic/BasicListUI.java | 3 + javax/swing/plaf/basic/BasicMenuBarUI.java | 4 + javax/swing/plaf/basic/BasicMenuUI.java | 4 + javax/swing/plaf/basic/BasicOptionPaneUI.java | 4 + javax/swing/plaf/basic/BasicPopupMenuUI.java | 4 + javax/swing/plaf/basic/BasicScrollBarUI.java | 4 + javax/swing/plaf/basic/BasicScrollPaneUI.java | 4 + javax/swing/plaf/basic/BasicSliderUI.java | 169 +++++++++-- javax/swing/plaf/basic/BasicSpinnerUI.java | 9 +- javax/swing/plaf/basic/BasicSplitPaneUI.java | 4 + javax/swing/plaf/basic/BasicTabbedPaneUI.java | 40 ++- javax/swing/plaf/basic/BasicTableHeaderUI.java | 4 + javax/swing/plaf/basic/BasicTableUI.java | 3 + javax/swing/plaf/basic/BasicTextAreaUI.java | 4 +- javax/swing/plaf/basic/BasicTextFieldUI.java | 15 +- javax/swing/plaf/basic/BasicTextUI.java | 12 +- javax/swing/plaf/basic/BasicToolBarUI.java | 4 + javax/swing/plaf/basic/BasicTreeUI.java | 319 ++++++++++++++------ javax/swing/table/DefaultTableCellRenderer.java | 3 +- javax/swing/table/DefaultTableColumnModel.java | 346 +++++++++++++-------- javax/swing/table/TableColumnModel.java | 95 ++++-- javax/swing/text/AbstractDocument.java | 92 +++++- javax/swing/text/AsyncBoxView.java | 2 +- javax/swing/text/CompositeView.java | 98 +++++- javax/swing/text/DefaultCaret.java | 68 +++++ javax/swing/text/DefaultHighlighter.java | 22 +- javax/swing/text/FieldView.java | 7 +- javax/swing/text/FlowView.java | 2 +- javax/swing/text/Utilities.java | 74 +++-- javax/swing/text/View.java | 29 +- javax/swing/text/WrappedPlainView.java | 76 ++++- javax/swing/tree/AbstractLayoutCache.java | 89 ++++-- javax/swing/tree/DefaultMutableTreeNode.java | 2 + javax/swing/tree/DefaultTreeCellEditor.java | 20 +- javax/swing/tree/DefaultTreeCellRenderer.java | 29 +- javax/swing/tree/DefaultTreeModel.java | 68 ++++- javax/swing/tree/DefaultTreeSelectionModel.java | 366 ++++++++++++++++++++--- javax/swing/tree/FixedHeightLayoutCache.java | 239 +++++++++++---- javax/swing/tree/TreePath.java | 14 +- javax/swing/tree/VariableHeightLayoutCache.java | 48 +-- javax/xml/datatype/DatatypeFactory.java | 37 ++- 91 files changed, 3130 insertions(+), 1061 deletions(-) (limited to 'javax') diff --git a/javax/accessibility/AccessibleAction.java b/javax/accessibility/AccessibleAction.java index 2ca683e45..a7cf05e4a 100644 --- a/javax/accessibility/AccessibleAction.java +++ b/javax/accessibility/AccessibleAction.java @@ -55,6 +55,28 @@ package javax.accessibility; */ public interface AccessibleAction { + + /** + * The name of an action which decrements a value. + * + * @since 1.5 + */ + static final String DECREMENT = "decrement"; + + /** + * The name of an action which increments a value. + * + * @since 1.5 + */ + static final String INCREMENT = "increment"; + + /** + * The name of an action which toggles the expansion of a tree node. + * + * @since 1.5 + */ + static final String TOGGLE_EXPAND = "toggle expand"; + /** * Get the number possible actions for this object, with the zeroth * representing the default action. diff --git a/javax/accessibility/AccessibleRole.java b/javax/accessibility/AccessibleRole.java index f386ad0e9..a5396f147 100644 --- a/javax/accessibility/AccessibleRole.java +++ b/javax/accessibility/AccessibleRole.java @@ -466,6 +466,56 @@ public class AccessibleRole extends AccessibleBundle public static final AccessibleRole GROUP_BOX = new AccessibleRole("groupbox"); + /** + * A formula for creating a value. + * + * @since 1.5 + */ + public static final AccessibleRole EDITBAR + = new AccessibleRole("editbar"); + + /** + * A text-based footer. + * + * @since 1.5 + */ + public static final AccessibleRole FOOTER + = new AccessibleRole("footer"); + + /** + * A text-based header. + * + * @since 1.5 + */ + public static final AccessibleRole HEADER + = new AccessibleRole("header"); + + + /** + * A text-based paragraph. + * + * @since 1.5 + */ + public static final AccessibleRole PARAGRAPH + = new AccessibleRole("paragraph"); + + /** + * Represents the current level of progress on a particular task. + * + * @since 1.5 + */ + public static final AccessibleRole PROGRESS_MONITOR + = new AccessibleRole("progress monitor"); + + /** + * A ruler is a method of measuring the distance between two + * points. + * + * @since 1.5 + */ + public static final AccessibleRole RULER + = new AccessibleRole("ruler"); + /** * Create a new constant with a locale independent key. Follow the example, * keep the constructor private and make public constants instead. diff --git a/javax/accessibility/AccessibleState.java b/javax/accessibility/AccessibleState.java index a630354b0..e4d00bd70 100644 --- a/javax/accessibility/AccessibleState.java +++ b/javax/accessibility/AccessibleState.java @@ -176,6 +176,28 @@ public class AccessibleState extends AccessibleBundle public static final AccessibleState ICONIFIED = new AccessibleState("iconified"); + /** + * Indicates that the state of this particular object is + * indeterminate. This commonly occurs when an object is incapable + * of representing the state by a single value. + * + * @since 1.5 + */ + public static final AccessibleState INDETERMINATE + = new AccessibleState("indeterminate"); + + /** + * Indicates that this particular object manages a number of + * subcomponents. This is a common property of structures such as + * trees and tables, which have a number of sub-elements such as + * rows and columns. The subcomponents should be left to the + * object, and not managed by the application. + * + * @since 1.5 + */ + public static final AccessibleState MANAGES_DESCENDANTS + = new AccessibleState("manages descendants"); + /** * Indicates that something must be done in the current object before * interaction is allowed on other windows, usually for dialogs. @@ -249,6 +271,15 @@ public class AccessibleState extends AccessibleBundle public static final AccessibleState SHOWING = new AccessibleState("showing"); + /** + * Indicates that this particular object is truncated when displayed + * visually. + * + * @since 1.5 + */ + public static final AccessibleState TRUNCATED + = new AccessibleState("truncated"); + /** * Indicates that this object intends to be visible. However, if its * parent is invisible, this object is as well. diff --git a/javax/net/ssl/HttpsURLConnection.java b/javax/net/ssl/HttpsURLConnection.java index 4c73edbcd..3f30dc1b8 100644 --- a/javax/net/ssl/HttpsURLConnection.java +++ b/javax/net/ssl/HttpsURLConnection.java @@ -1,5 +1,5 @@ /* HttpsURLConnection.java -- an HTTPS connection. - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,7 +38,6 @@ exception statement from your version. */ package javax.net.ssl; -import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; import java.security.cert.Certificate; @@ -90,9 +89,10 @@ public abstract class HttpsURLConnection extends HttpURLConnection * Creates a new HTTPS URL connection. * * @param url The URL of the connection being established. - * @throws IOException If the connection cannot be established. + * @specnote This was marked as throwing IOException in 1.4, + * but this was removed in 1.5. */ - protected HttpsURLConnection(URL url) throws IOException + protected HttpsURLConnection(URL url) { super(url); } diff --git a/javax/swing/ActionMap.java b/javax/swing/ActionMap.java index 2a8c78d66..0d6706c3b 100644 --- a/javax/swing/ActionMap.java +++ b/javax/swing/ActionMap.java @@ -1,5 +1,5 @@ /* ActionMap.java -- - Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -37,9 +37,6 @@ exception statement from your version. */ package javax.swing; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Arrays; import java.util.HashMap; diff --git a/javax/swing/DefaultListSelectionModel.java b/javax/swing/DefaultListSelectionModel.java index 003513a23..b6d3e079e 100644 --- a/javax/swing/DefaultListSelectionModel.java +++ b/javax/swing/DefaultListSelectionModel.java @@ -162,11 +162,14 @@ public class DefaultListSelectionModel implements Cloneable, /** * Sets the value of the {@link #selectionMode} property. * - * @param a The new value of the property + * @param mode The new value of the property */ - public void setSelectionMode(int a) + public void setSelectionMode(int mode) { - selectionMode = a; + if (mode < ListSelectionModel.SINGLE_SELECTION + || mode > ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) + throw new IllegalArgumentException("Unrecognised mode: " + mode); + selectionMode = mode; } /** @@ -552,9 +555,10 @@ public class DefaultListSelectionModel implements Cloneable, int i; - Up: for (i = from; i>=0; i=sel.nextSetBit(i+1)) + for (i = from; i>=0; i=sel.nextSetBit(i+1)) to = i; + sel.clear(); fireValueChanged(from, to, valueIsAdjusting); } @@ -776,6 +780,7 @@ public class DefaultListSelectionModel implements Cloneable, DefaultListSelectionModel model = (DefaultListSelectionModel) super.clone(); model.sel = (BitSet) sel.clone(); + model.listenerList = new EventListenerList(); return model; } } diff --git a/javax/swing/ImageIcon.java b/javax/swing/ImageIcon.java index 0baaf6f60..7347985eb 100644 --- a/javax/swing/ImageIcon.java +++ b/javax/swing/ImageIcon.java @@ -1,5 +1,5 @@ /* ImageIcon.java -- - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -39,6 +39,7 @@ package javax.swing; import java.awt.Component; import java.awt.Graphics; +import java.awt.IllegalComponentStateException; import java.awt.Image; import java.awt.MediaTracker; import java.awt.Toolkit; @@ -60,7 +61,8 @@ public class ImageIcon implements Icon, Serializable, Accessible { /** - * Accessibility support for ImageIcon. + * Provides the accessibility features for the ImageIcon + * class. */ protected class AccessibleImageIcon extends AccessibleContext @@ -69,7 +71,7 @@ public class ImageIcon private static final long serialVersionUID = 2113430526551336564L; /** - * Creates a new instance of AccessibleImageIcon. + * Creates a new instance of AccessibleImageIcon. */ protected AccessibleImageIcon() { @@ -77,10 +79,9 @@ public class ImageIcon } /** - * Returns the AccessibleRole of ImageIcon, which is - * {@link AccessibleRole#ICON}. + * Returns the accessible role for the ImageIcon. * - * @return {@link AccessibleRole#ICON} + * @return {@link AccessibleRole#ICON}. */ public AccessibleRole getAccessibleRole() { @@ -88,45 +89,47 @@ public class ImageIcon } /** - * Returns the accessible state of this ImageIcon. + * Returns the accessible state for the ImageIcon. To + * match the reference implementation, this method always returns + * null. * - * @return the accessible state of this ImageIcon + * @return null. */ public AccessibleStateSet getAccessibleStateSet() { - // TODO: which state information from ImageIcon is returned here?? - return new AccessibleStateSet(); + // refer to Sun's bug report 4269253 + return null; } /** - * Returns the accessible parent of this object, which is null - * in this case, because ImageIcons have no parent. + * Returns the accessible parent of this object. To match the reference + * implementation, this method always returns null. * - * @return null, because ImageIcons have no parent + * @return null. */ public Accessible getAccessibleParent() { - // TODO: ImageIcons have no parent, have they ?? + // refer to Sun's bug report 4269253 return null; } /** - * Returns the index of this object in its accessible parent, which is - * -1 here, because ImageIcons have no accessible parent. + * Returns the index of this object in its accessible parent. To match + * the reference implementation, this method always returns -1. * - * @return -1 because ImageIcons have no parent + * @return -1. */ public int getAccessibleIndexInParent() { - // TODO: do ImageIcons have parents?? + // refer to Sun's bug report 4269253 return -1; } /** * Returns the number of accessible children of this component, - * which is 0, because ImageIcons have no children. + * which is 0, because an {@link ImageIcon} has no children. * - * @return 0 because ImageIcons have no children + * @return 0. */ public int getAccessibleChildrenCount() { @@ -135,11 +138,12 @@ public class ImageIcon /** * Returns the accessible child at index i, which is - * null in this case because ImageIcons have no children. + * null in this case because an {@link ImageIcon} has no + * children. * * @param i the index of the child to be fetched * - * @return null because ImageIcons have no children + * @return null. */ public Accessible getAccessibleChild(int i) { @@ -147,21 +151,25 @@ public class ImageIcon } /** - * Returns the locale of this object. This returns the default locale - * that is set for the current VM. + * Returns the locale of this object. To match the reference + * implementation, this method always returns null. * - * @return the locale of this object + * @return null. */ - public Locale getLocale() + public Locale getLocale() + throws IllegalComponentStateException { - return Locale.getDefault(); + // refer to Sun's bug report 4269253 + return null; } /** - * Returns the accessible Icon description. This returns the - * actual 'description' property of the ImageIcon. + * Returns the accessible icon description. This returns the + * description property of the underlying {@link ImageIcon}. * - * @return the accessible Icon description + * @return The description (possibly null). + * + * @see #setAccessibleIconDescription(String) */ public String getAccessibleIconDescription() { @@ -169,10 +177,12 @@ public class ImageIcon } /** - * Sets the accessible Icon description. This sets the - * actual 'description' property of the ImageIcon. + * Sets the accessible icon description. This sets the + * description property of the underlying {@link ImageIcon}. * - * @param newDescr the description to be set + * @param newDescr the description (null permitted). + * + * @see #getAccessibleIconDescription() */ public void setAccessibleIconDescription(String newDescr) { @@ -180,10 +190,10 @@ public class ImageIcon } /** - * Returns the icon height. This returns the iconHeight property of - * the underlying Icon. + * Returns the icon height. This returns the iconHeight + * property of the underlying {@link ImageIcon}. * - * @return the icon height + * @return The icon height. */ public int getAccessibleIconHeight() { @@ -191,10 +201,10 @@ public class ImageIcon } /** - * Returns the icon width. This returns the iconWidth property of - * the underlying Icon. + * Returns the icon width. This returns the iconWidth property + * of the underlying {@link ImageIcon}. * - * @return the icon width + * @return The icon width. */ public int getAccessibleIconWidth() { @@ -446,9 +456,11 @@ public class ImageIcon } /** - * Returns the AccessibleContext for this ImageIcon. + * Returns the object that provides accessibility features for this + * ImageIcon instance. * - * @return the AccessibleContext for this ImageIcon + * @return The accessible context (an instance of + * {@link AccessibleImageIcon}). */ public AccessibleContext getAccessibleContext() { diff --git a/javax/swing/JButton.java b/javax/swing/JButton.java index c1340bbc2..787adb87c 100644 --- a/javax/swing/JButton.java +++ b/javax/swing/JButton.java @@ -1,5 +1,5 @@ /* JButton.java -- - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -78,27 +78,57 @@ public class JButton extends AbstractButton */ private boolean defaultCapable; + /** + * Creates a new button with an empty string for the button text and no + * icon. + */ public JButton() { this(null, null); } + /** + * Creates a new button from the specified action. + * + * @param a the action (null permitted). + * + * @see AbstractButton#setAction(Action) + */ public JButton(Action a) { this(); setAction(a); } + /** + * Creates a new button with the specified icon (and an empty string for + * the button text). + * + * @param icon the icon (null permitted). + */ public JButton(Icon icon) { this(null, icon); } + /** + * Creates a new button with the specified text and no icon. + * + * @param text the button text (null permitted, will be + * substituted by an empty string). + */ public JButton(String text) { this(text, null); } + /** + * Creates a new button with the specified text and icon. + * + * @param text the button text (null permitted, will be + * substituted by an empty string). + * @param icon the icon (null permitted). + */ public JButton(String text, Icon icon) { super(); @@ -108,12 +138,16 @@ public class JButton extends AbstractButton } protected void configurePropertiesFromAction(Action a) - { - // Factory method which sets the AbstractButton's properties according to - // values from the Action instance. + { super.configurePropertiesFromAction(a); } + /** + * Returns the object that provides accessibility features for this + * JButton component. + * + * @return The accessible context (an instance of {@link AccessibleJButton}). + */ public AccessibleContext getAccessibleContext() { if (accessibleContext == null) @@ -121,6 +155,13 @@ public class JButton extends AbstractButton return accessibleContext; } + /** + * Returns the suffix ("ButtonUI" in this case) used to + * determine the class name for a UI delegate that can provide the look and + * feel for a JButton. + * + * @return "ButtonUI". + */ public String getUIClassID() { // Returns a string that specifies the name of the L&F class that renders @@ -138,7 +179,7 @@ public class JButton extends AbstractButton * its JRootPane * * @see #isDefaultCapable() - * @see #setDefaultCapable() + * @see #setDefaultCapable(boolean) * @see JRootPane#getDefaultButton() * @see JRootPane#setDefaultButton(JButton) */ @@ -160,7 +201,7 @@ public class JButton extends AbstractButton * * @return true if this button can act as the default button * - * @see #setDefaultCapable() + * @see #setDefaultCapable(boolean) * @see #isDefaultButton() * @see JRootPane#getDefaultButton() * @see JRootPane#setDefaultButton(JButton) @@ -172,6 +213,13 @@ public class JButton extends AbstractButton return defaultCapable; } + /** + * Returns an implementation-dependent string describing the attributes of + * this JButton. + * + * @return A string describing the attributes of this JButton + * (never null). + */ protected String paramString() { String superParam = super.paramString(); @@ -205,7 +253,7 @@ public class JButton extends AbstractButton * @param defaultCapable true if this button can become the * default button in its JRootPane, false otherwise * - * @see #setDefaultCapable() + * @see #setDefaultCapable(boolean) * @see #isDefaultButton() * @see JRootPane#getDefaultButton() * @see JRootPane#setDefaultButton(JButton) @@ -215,6 +263,10 @@ public class JButton extends AbstractButton this.defaultCapable = defaultCapable; } + /** + * Sets this button's UI delegate to the default (obtained from the + * {@link UIManager}) for the current look and feel. + */ public void updateUI() { setUI((ButtonUI) UIManager.getUI(this)); diff --git a/javax/swing/JComboBox.java b/javax/swing/JComboBox.java index f995e114a..17bcf1f99 100644 --- a/javax/swing/JComboBox.java +++ b/javax/swing/JComboBox.java @@ -1,5 +1,5 @@ /* JComboBox.java -- - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -1102,15 +1102,33 @@ public class JComboBox extends JComponent implements ItemSelectable, } /** - * A string that describes this JComboBox. Normally only used for debugging. + * Returns an implementation-dependent string describing the attributes of + * this JComboBox. * - * @return A string describing this JComboBox + * @return A string describing the attributes of this JComboBox + * (never null). */ protected String paramString() { - return "JComboBox"; + String superParamStr = super.paramString(); + StringBuffer sb = new StringBuffer(); + sb.append(",isEditable=").append(isEditable()); + sb.append(",lightWeightPopupEnabled=").append(isLightWeightPopupEnabled()); + sb.append(",maximumRowCount=").append(getMaximumRowCount()); + + sb.append(",selectedItemReminder="); + if (selectedItemReminder != null) + sb.append(selectedItemReminder); + return superParamStr + sb.toString(); } + /** + * Returns the object that provides accessibility features for this + * JComboBox component. + * + * @return The accessible context (an instance of + * {@link AccessibleJComboBox}). + */ public AccessibleContext getAccessibleContext() { if (accessibleContext == null) @@ -1219,6 +1237,10 @@ public class JComboBox extends JComponent implements ItemSelectable, { private static final long serialVersionUID = 8217828307256675666L; + /** + * @specnote This constructor was protected in 1.4, but made public + * in 1.5. + */ public AccessibleJComboBox() { // Nothing to do here. @@ -1254,6 +1276,11 @@ public class JComboBox extends JComponent implements ItemSelectable, return false; } + /** + * Returns the accessible role for the JComboBox component. + * + * @return {@link AccessibleRole#COMBO_BOX}. + */ public AccessibleRole getAccessibleRole() { return AccessibleRole.COMBO_BOX; diff --git a/javax/swing/JComponent.java b/javax/swing/JComponent.java index eba05d03c..8838dda0a 100644 --- a/javax/swing/JComponent.java +++ b/javax/swing/JComponent.java @@ -1862,8 +1862,8 @@ public abstract class JComponent extends Container implements Serializable // Go through children from top to bottom and find out their paint // rectangles. - int index = 0; - while (paintRectangles.size() > 0 && index < children.length) + for (int index = 0; paintRectangles.size() > 0 && + index < children.length; index++) { Component comp = children[index]; if (! comp.isVisible()) @@ -1936,6 +1936,12 @@ public abstract class JComponent extends Container implements Serializable newPaintRects.add(rect); } } + else + { + // Not opaque, need to reuse the current paint rectangles + // for the next component. + newPaintRects.add(r); + } } else @@ -1958,8 +1964,6 @@ public abstract class JComponent extends Container implements Serializable paintRegions.add(componentRectangles); componentRectangles = new ArrayList(); } - - index++; } // paintingTile becomes true just before we start painting the component's @@ -2024,34 +2028,10 @@ public abstract class JComponent extends Container implements Serializable g.clipRect(inner.x, inner.y, inner.width, inner.height); Component[] children = getComponents(); - // Find the bottommost component that needs to be painted. This is the - // component that - together with the rectangles of the components that - // are painted above it - covers the whole clip area. - Rectangle rect = new Rectangle(); - int startIndex = children.length - 1; - for (int i = 0; i < children.length; i++) - { - Rectangle b = children[i].getBounds(); - if (children[i].isOpaque() && children[i].isVisible() - && g.hitClip(b.x, b.y, b.width, b.height)) - { - if (rect.isEmpty()) - rect.setBounds(b); - else - SwingUtilities.computeUnion(b.x, b.y, b.width, b.height, rect); - - if (SwingUtilities.isRectangleContainingRectangle(rect, inner)) - { - startIndex = i; - break; - } - } - } - // paintingTile becomes true just before we start painting the component's // children. paintingTile = true; - for (int i = startIndex; i >= 0; i--) //children.length; i++) + for (int i = children.length - 1; i >= 0; i--) //children.length; i++) { // paintingTile must be set to false before we begin to start painting // the last tile. @@ -2942,9 +2922,12 @@ public abstract class JComponent extends Container implements Serializable } /** - * Set the value of the {@link #opaque} property. + * Set if the component should paint all pixels withing its bounds. + * If this property is set to false, the component expects the cleared + * background. * - * @param isOpaque The new value of the property + * @param isOpaque if true, paint all pixels. If false, expect the clean + * background. * * @see ComponentUI#update */ diff --git a/javax/swing/JDesktopPane.java b/javax/swing/JDesktopPane.java index 92b25f979..454870ea6 100644 --- a/javax/swing/JDesktopPane.java +++ b/javax/swing/JDesktopPane.java @@ -56,7 +56,6 @@ import javax.swing.plaf.DesktopPaneUI; */ public class JDesktopPane extends JLayeredPane implements Accessible { - /** DOCUMENT ME! */ private static final long serialVersionUID = 766333777224038726L; /** @@ -94,15 +93,15 @@ public class JDesktopPane extends JLayeredPane implements Accessible private boolean clientDragModeSet = false; /** - * AccessibleJDesktopPane + * Provides the accessibility features for the JDesktopPane + * component. */ protected class AccessibleJDesktopPane extends AccessibleJComponent { - /** DOCUMENT ME! */ private static final long serialVersionUID = 6079388927946077570L; /** - * Constructor AccessibleJDesktopPane + * Creates a new AccessibleJDesktopPane instance. */ protected AccessibleJDesktopPane() { @@ -110,9 +109,9 @@ public class JDesktopPane extends JLayeredPane implements Accessible } /** - * getAccessibleRole + * Returns the accessible role for the JSlider component. * - * @return AccessibleRole + * @return {@link AccessibleRole#DESKTOP_PANE}. */ public AccessibleRole getAccessibleRole() { @@ -298,13 +297,22 @@ public class JDesktopPane extends JLayeredPane implements Accessible } /** - * This method returns a String that describes the JDesktopPane. + * Returns an implementation-dependent string describing the attributes of + * this JDesktopPane. * - * @return A String that describes the JDesktopPane. + * @return A string describing the attributes of this JDesktopPane + * (never null). */ protected String paramString() { - return "JDesktopPane"; + String superParamStr = super.paramString(); + StringBuffer sb = new StringBuffer(); + sb.append(",isOptimizedDrawingPossible="); + sb.append(isOptimizedDrawingEnabled()); + sb.append(",desktopManager="); + if (desktopManager != null) + sb.append(desktopManager); + return superParamStr + sb.toString(); } /** @@ -330,9 +338,11 @@ public class JDesktopPane extends JLayeredPane implements Accessible } /** - * getAccessibleContext + * Returns the object that provides accessibility features for this + * JDesktopPane component. * - * @return AccessibleContext + * @return The accessible context (an instance of + * {@link AccessibleJDesktopPane}). */ public AccessibleContext getAccessibleContext() { diff --git a/javax/swing/JInternalFrame.java b/javax/swing/JInternalFrame.java index 937212562..79dcc7326 100644 --- a/javax/swing/JInternalFrame.java +++ b/javax/swing/JInternalFrame.java @@ -280,15 +280,17 @@ public class JInternalFrame extends JComponent implements Accessible, updateUI(); } - /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ + /** + * Returns the object that provides accessibility features for this + * JDesktopIcon component. + * + * @return The accessible context (an instance of + * {@link AccessibleJDesktopIcon}). + */ public AccessibleContext getAccessibleContext() { if (accessibleContext == null) - accessibleContext = new AccessibleJDesktopIcon(); + accessibleContext = new AccessibleJDesktopIcon(); return accessibleContext; } @@ -773,10 +775,16 @@ public class JInternalFrame extends JComponent implements Accessible, } /** - * This method returns the default action taken when this JInternalFrame is - * closed. + * Returns a code for the default action taken when this + * JInternalFrame is closed. * - * @return The default action taken when this JInternalFrame is closed. + * @return The action code (usually one of + * {@link WindowConstants#DO_NOTHING_ON_CLOSE}, + * {@link WindowConstants#HIDE_ON_CLOSE}, or + * {@link WindowConstants#DISPOSE_ON_CLOSE}). + * + * @see #setDefaultCloseOperation(int) + * @see #doDefaultCloseAction() */ public int getDefaultCloseOperation() { @@ -1202,13 +1210,15 @@ public class JInternalFrame extends JComponent implements Accessible, } /** - * This method returns a String describing this JInternalFrame. + * An implementation dependent string describing the current state of this + * JInternalFrame instance. * - * @return A String describing this JInternalFrame. + * @return A string describing the current state of this + * JInternalFrame instance. */ protected String paramString() { - return super.paramString(); + return super.paramString() + ",title=" + getTitle(); } /** @@ -1322,12 +1332,17 @@ public class JInternalFrame extends JComponent implements Accessible, } /** - * This method sets the action taken when this JInternalFrame is closed. - * - * @param operation One of DO_NOTHING_ON_CLOSE, HIDE_ON_CLOSE or - * DISPOSE_ON_CLOSE. + * Sets a code for the action to be taken when this + * JInternalFrame is closed. Note that no validation is + * performed on the operation code, any integer will be + * accepted (nevertheless, you should pass in one of the listed values). * - * @throws Error If the given operation is not one of the allowed modes. + * @param operation one of {@link WindowConstants#DO_NOTHING_ON_CLOSE}, + * {@link WindowConstants#HIDE_ON_CLOSE} or + * {@link WindowConstants#DISPOSE_ON_CLOSE}. + * + * @see #getDefaultCloseOperation() + * @see #doDefaultCloseAction() */ public void setDefaultCloseOperation(int operation) { diff --git a/javax/swing/JLabel.java b/javax/swing/JLabel.java index 7c552469e..65b1e6fcd 100644 --- a/javax/swing/JLabel.java +++ b/javax/swing/JLabel.java @@ -512,6 +512,7 @@ public class JLabel extends JComponent implements Accessible, SwingConstants Icon oldIcon = icon; icon = newIcon; firePropertyChange("icon", oldIcon, newIcon); + repaint(); } } diff --git a/javax/swing/JList.java b/javax/swing/JList.java index 04f658361..04f3881a2 100644 --- a/javax/swing/JList.java +++ b/javax/swing/JList.java @@ -1,5 +1,5 @@ /* JList.java -- - Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2004, 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -1022,48 +1022,56 @@ public class JList extends JComponent implements Accessible, Scrollable /** - * Creates a new JList object. + * Creates a new JList object. */ public JList() { - init(); + init(new DefaultListModel()); } /** - * Creates a new JList object. + * Creates a new JList object. * - * @param listData Initial data to populate the list with + * @param items the initial list items. */ - public JList(Object[] listData) + public JList(Object[] items) { - init(); - setListData(listData); + init(createListModel(items)); } /** - * Creates a new JList object. + * Creates a new JList object. * - * @param listData Initial data to populate the list with + * @param items the initial list items. */ - public JList(Vector listData) + public JList(Vector items) { - init(); - setListData(listData); + init(createListModel(items)); } /** - * Creates a new JList object. + * Creates a new JList object. * - * @param listData Initial data to populate the list with + * @param model a model containing the list items (null not + * permitted). + * + * @throws IllegalArgumentException if model is + * null. */ - public JList(ListModel listData) + public JList(ListModel model) { - init(); - setModel(listData); + init(model); } - void init() + /** + * Initializes the list. + * + * @param m the list model (null not permitted). + */ + private void init(ListModel m) { + if (m == null) + throw new IllegalArgumentException("Null model not permitted."); dragEnabled = false; fixedCellHeight = -1; fixedCellWidth = -1; @@ -1075,9 +1083,17 @@ public class JList extends JComponent implements Accessible, Scrollable cellRenderer = new DefaultListCellRenderer(); listListener = new ListListener(); - setModel(new DefaultListModel()); - setSelectionModel(createSelectionModel()); - setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + model = m; + if (model != null) + model.addListDataListener(listListener); + + selectionModel = createSelectionModel(); + if (selectionModel != null) + { + selectionModel.addListSelectionListener(listListener); + selectionModel.setSelectionMode + (ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + } setLayout(null); updateUI(); @@ -1117,6 +1133,8 @@ public class JList extends JComponent implements Accessible, Scrollable * #prototypeCellValue} property is set, but setting it explicitly * overrides the height computed from {@link #prototypeCellValue}. * + * @param h the height. + * * @see #getFixedCellHeight * @see #getPrototypeCellValue */ @@ -1127,7 +1145,7 @@ public class JList extends JComponent implements Accessible, Scrollable int old = fixedCellHeight; fixedCellHeight = h; - firePropertyChange("fixedCellWidth", old, h); + firePropertyChange("fixedCellHeight", old, h); } @@ -1549,20 +1567,39 @@ public class JList extends JComponent implements Accessible, Scrollable * @param listData The object array to build a new list model on * @see #setModel */ - public void setListData(final Object[] listData) + public void setListData(Object[] listData) { - setModel(new AbstractListModel() - { - public int getSize() - { - return listData.length; - } + setModel(createListModel(listData)); + } - public Object getElementAt(int i) - { - return listData[i]; - } - }); + private ListModel createListModel(final Object[] items) + { + return new AbstractListModel() + { + public int getSize() + { + return items.length; + } + public Object getElementAt(int i) + { + return items[i]; + } + }; + } + + private ListModel createListModel(final Vector items) + { + return new AbstractListModel() + { + public int getSize() + { + return items.size(); + } + public Object getElementAt(int i) + { + return items.get(i); + } + }; } /** @@ -1576,17 +1613,17 @@ public class JList extends JComponent implements Accessible, Scrollable public void setListData(final Vector listData) { setModel(new AbstractListModel() - { - public int getSize() - { - return listData.size(); - } - - public Object getElementAt(int i) - { - return listData.elementAt(i); - } - }); + { + public int getSize() + { + return listData.size(); + } + + public Object getElementAt(int i) + { + return listData.elementAt(i); + } + }); } /** @@ -2022,11 +2059,27 @@ public class JList extends JComponent implements Accessible, Scrollable return selectionModel.getLeadSelectionIndex(); } + /** + * Returns the lowest item index in the current selection, or -1 + * if there is no selection. + * + * @return The index. + * + * @see #getMaxSelectionIndex() + */ public int getMinSelectionIndex() { - return selectionModel.getMaxSelectionIndex(); + return selectionModel.getMinSelectionIndex(); } + /** + * Returns the highest item index in the current selection, or + * -1 if there is no selection. + * + * @return The index. + * + * @see #getMinSelectionIndex() + */ public int getMaxSelectionIndex() { return selectionModel.getMaxSelectionIndex(); @@ -2140,7 +2193,14 @@ public class JList extends JComponent implements Accessible, Scrollable */ public Rectangle getCellBounds(int index0, int index1) { - return getUI().getCellBounds(this, index0, index1); + ListUI ui = getUI(); + Rectangle bounds = null; + if (ui != null) + { + bounds = ui.getCellBounds(this, index0, index1); + } + // When the UI is null, this method also returns null in the RI. + return bounds; } /** @@ -2203,4 +2263,28 @@ public class JList extends JComponent implements Accessible, Scrollable } return index; } + + /** + * Returns a string describing the attributes for the JList + * component, for use in debugging. The return value is guaranteed to be + * non-null, but the format of the string may vary between + * implementations. + * + * @return A string describing the attributes of the JList. + */ + protected String paramString() + { + StringBuffer sb = new StringBuffer(super.paramString()); + sb.append(",fixedCellHeight=").append(getFixedCellHeight()); + sb.append(",fixedCellWidth=").append(getFixedCellWidth()); + sb.append(",selectionBackground="); + if (getSelectionBackground() != null) + sb.append(getSelectionBackground()); + sb.append(",selectionForeground="); + if (getSelectionForeground() != null) + sb.append(getSelectionForeground()); + sb.append(",visibleRowCount=").append(getVisibleRowCount()); + sb.append(",layoutOrientation=").append(getLayoutOrientation()); + return sb.toString(); + } } diff --git a/javax/swing/JMenu.java b/javax/swing/JMenu.java index 438fc49f1..37ed14854 100644 --- a/javax/swing/JMenu.java +++ b/javax/swing/JMenu.java @@ -1,5 +1,5 @@ /* JMenu.java -- - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing; +import gnu.classpath.NotImplementedException; + import java.awt.Component; import java.awt.Point; import java.awt.event.KeyEvent; @@ -821,26 +823,31 @@ public class JMenu extends JMenuItem implements Accessible, MenuElement } public int getAccessibleChildrenCount() + throws NotImplementedException { return 0; } public Accessible getAccessibleChild(int value0) + throws NotImplementedException { return null; } public AccessibleSelection getAccessibleSelection() + throws NotImplementedException { return null; } public Accessible getAccessibleSelection(int value0) + throws NotImplementedException { return null; } public boolean isAccessibleChildSelected(int value0) + throws NotImplementedException { return false; } @@ -851,26 +858,31 @@ public class JMenu extends JMenuItem implements Accessible, MenuElement } public int getAccessibleSelectionCount() + throws NotImplementedException { return 0; } public void addAccessibleSelection(int value0) + throws NotImplementedException { // TODO: Implement this properly. } public void removeAccessibleSelection(int value0) + throws NotImplementedException { // TODO: Implement this properly. } public void clearAccessibleSelection() + throws NotImplementedException { // TODO: Implement this properly. } public void selectAllAccessibleSelection() + throws NotImplementedException { // TODO: Implement this properly. } diff --git a/javax/swing/JMenuItem.java b/javax/swing/JMenuItem.java index 643fe8fd5..272c1cfe6 100644 --- a/javax/swing/JMenuItem.java +++ b/javax/swing/JMenuItem.java @@ -1,5 +1,5 @@ /* JMenuItem.java -- - Copyright (C) 2002, 2004, 2005,2006 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing; +import gnu.classpath.NotImplementedException; + import java.awt.Component; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; @@ -671,16 +673,26 @@ public class JMenuItem extends AbstractButton implements Accessible, } /** - * A string that describes this JMenuItem. Normally only used - * for debugging. + * Returns a string describing the attributes for the JToolTip + * component, for use in debugging. The return value is guaranteed to be + * non-null, but the format of the string may vary between + * implementations. * - * @return A string describing this JMenuItem + * @return A string describing the attributes of the JMenuItem. */ protected String paramString() { + // calling super seems to be sufficient here... return super.paramString(); } + /** + * Returns the object that provides accessibility features for this + * JMenuItem component. + * + * @return The accessible context (an instance of + * {@link AccessibleJMenuItem}). + */ public AccessibleContext getAccessibleContext() { if (accessibleContext == null) @@ -689,13 +701,19 @@ public class JMenuItem extends AbstractButton implements Accessible, return accessibleContext; } + /** + * Provides the accessibility features for the JMenuItem + * component. + * + * @see JMenuItem#getAccessibleContext() + */ protected class AccessibleJMenuItem extends AccessibleAbstractButton implements ChangeListener { private static final long serialVersionUID = 6748924232082076534L; /** - * Creates a new AccessibleJMenuItem object. + * Creates a new AccessibleJMenuItem instance. */ AccessibleJMenuItem() { @@ -703,10 +721,16 @@ public class JMenuItem extends AbstractButton implements Accessible, } public void stateChanged(ChangeEvent event) + throws NotImplementedException { // TODO: What should be done here, if anything? } + /** + * Returns the accessible role for the JMenuItem component. + * + * @return {@link AccessibleRole#MENU_ITEM}. + */ public AccessibleRole getAccessibleRole() { return AccessibleRole.MENU_ITEM; diff --git a/javax/swing/JPanel.java b/javax/swing/JPanel.java index 815e452dc..3bd71d1c2 100644 --- a/javax/swing/JPanel.java +++ b/javax/swing/JPanel.java @@ -1,5 +1,5 @@ /* JPanel.java -- - Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -80,54 +80,108 @@ public class JPanel extends JComponent implements Accessible } } + /** + * Creates a new panel with a new instance of {@link FlowLayout} as the + * layout manager and double-buffering enabled. + */ public JPanel() { this(new FlowLayout(), true); } - public JPanel(boolean double_buffered) + /** + * Creates a new panel with double-buffering enabled or disabled as + * specified. The default layout manager is an instance of + * {@link FlowLayout}. + * + * @param isDoubleBuffered a flag that controls whether or not + * double-buffering is enabled. + */ + public JPanel(boolean isDoubleBuffered) { - this(new FlowLayout(), double_buffered); + this(new FlowLayout(), isDoubleBuffered); } + /** + * Creates a new panel with the specified layout manager. Double-buffering + * is enabled by default. + * + * @param layout the layout manager (null permitted). + */ public JPanel(LayoutManager layout) { this(layout, true); } + /** + * Creates a new panel with the specified layout manager and + * double-buffering. + * + * @param layout the layout manager (null permitted). + * @param isDoubleBuffered a flag that controls whether or not + * double-buffering is enabled. + */ public JPanel(LayoutManager layout, boolean isDoubleBuffered) { - if (layout == null) - { - // TODO: Is this correct? Or should we throw a NPE? - layout = new FlowLayout(); - } setLayout(layout); - setOpaque(true); - + setOpaque(true); + setDoubleBuffered(isDoubleBuffered); updateUI(); } + /** + * Returns the suffix ("PanelUI" in this case) used to + * determine the class name for a UI delegate that can provide the look and + * feel for a JPanel. + * + * @return "PanelUI". + */ public String getUIClassID() { return "PanelUI"; } + /** + * Sets the UI delegate for the JPanel component. + * + * @param ui the UI delegate. + * + * @since 1.4 + * @see #getUI() + */ public void setUI(PanelUI ui) { super.setUI(ui); } + /** + * Returns the UI delegate for the JPanel component. + * + * @return The UI delegate. + * + * @since 1.4 + * @see #setUI(PanelUI) + */ public PanelUI getUI() { return (PanelUI) ui; } + /** + * Sets this panel's UI delegate to the default (obtained from the + * {@link UIManager}) for the current look and feel. + */ public void updateUI() { setUI((PanelUI) UIManager.getUI(this)); } + /** + * Returns the object that provides accessibility features for this + * JPanel component. + * + * @return The accessible context (an instance of {@link AccessibleJPanel}). + */ public AccessibleContext getAccessibleContext() { if (accessibleContext == null) @@ -135,7 +189,14 @@ public class JPanel extends JComponent implements Accessible return accessibleContext; } - protected String paramString() + /** + * Returns an implementation-dependent string describing the attributes of + * this JPanel. + * + * @return A string describing the attributes of this JPanel + * (never null). + */ + protected String paramString() { return super.paramString(); } diff --git a/javax/swing/JProgressBar.java b/javax/swing/JProgressBar.java index 2f61ac305..db936f64a 100644 --- a/javax/swing/JProgressBar.java +++ b/javax/swing/JProgressBar.java @@ -634,15 +634,28 @@ public class JProgressBar extends JComponent implements SwingConstants, } /** - * This method returns a string that can be used to - * describe this JProgressBar. This method is usually - * only used for debugging purposes. + * Returns an implementation-dependent string describing the attributes of + * this JProgressBar. * - * @return A string that describes this JProgressBar. + * @return A string describing the attributes of this + * JProgressBar (never null). */ protected String paramString() { - return "JProgressBar"; + String superParamStr = super.paramString(); + StringBuffer sb = new StringBuffer(); + sb.append(",orientation="); + if (orientation == HORIZONTAL) + sb.append("HORIZONTAL"); + else + sb.append("VERTICAL"); + sb.append(",paintBorder=").append(isBorderPainted()); + sb.append(",paintString=").append(isStringPainted()); + sb.append(",progressString="); + if (progressString != null) + sb.append(progressString); + sb.append(",indeterminateString=").append(isIndeterminate()); + return superParamStr + sb.toString(); } /** diff --git a/javax/swing/JRadioButtonMenuItem.java b/javax/swing/JRadioButtonMenuItem.java index 61a8dbab3..0d7c1d105 100644 --- a/javax/swing/JRadioButtonMenuItem.java +++ b/javax/swing/JRadioButtonMenuItem.java @@ -1,5 +1,5 @@ /* JRadioButtonMenuItem.java -- - Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -168,16 +168,27 @@ public class JRadioButtonMenuItem extends JMenuItem implements Accessible } /** - * A string that describes this JRadioButtonMenuItem. Normally only used - * for debugging. + * Returns a string describing the attributes for the + * JRadioButtonMenuItem component, for use in debugging. The + * return value is guaranteed to be non-null, but the format of + * the string may vary between implementations. * - * @return A string describing this JRadioButtonMenuItem + * @return A string describing the attributes of the + * JRadioButtonMenuItem. */ protected String paramString() { - return "JRadioButtonMenuItem"; + // calling super seems to be sufficient here... + return super.paramString(); } + /** + * Returns the object that provides accessibility features for this + * JRadioButtonMenuItem component. + * + * @return The accessible context (an instance of + * {@link AccessibleJRadioButtonMenuItem}). + */ public AccessibleContext getAccessibleContext() { if (accessibleContext == null) @@ -186,18 +197,30 @@ public class JRadioButtonMenuItem extends JMenuItem implements Accessible return accessibleContext; } + /** + * Provides the accessibility features for the + * JRadioButtonMenuItem component. + * + * @see JRadioButtonMenuItem#getAccessibleContext() + */ protected class AccessibleJRadioButtonMenuItem extends AccessibleJMenuItem { private static final long serialVersionUID = 4381471510145292179L; /** - * Creates a new AccessibleJRadioButtonMenuItem object. + * Creates a new AccessibleJRadioButtonMenuItem instance. */ protected AccessibleJRadioButtonMenuItem() { // Nothing to do here. } + /** + * Returns the accessible role for the JRadioButtonMenuItem + * component. + * + * @return {@link AccessibleRole#RADIO_BUTTON}. + */ public AccessibleRole getAccessibleRole() { return AccessibleRole.RADIO_BUTTON; diff --git a/javax/swing/JScrollPane.java b/javax/swing/JScrollPane.java index b1e16a681..09e37378b 100644 --- a/javax/swing/JScrollPane.java +++ b/javax/swing/JScrollPane.java @@ -51,7 +51,6 @@ import javax.accessibility.AccessibleContext; import javax.swing.border.Border; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import javax.swing.plaf.ScrollBarUI; import javax.swing.plaf.ScrollPaneUI; import javax.swing.plaf.UIResource; diff --git a/javax/swing/JSeparator.java b/javax/swing/JSeparator.java index 602af6a38..c87783b73 100644 --- a/javax/swing/JSeparator.java +++ b/javax/swing/JSeparator.java @@ -37,12 +37,13 @@ exception statement from your version. */ package javax.swing; +import java.beans.PropertyChangeEvent; + import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleRole; import javax.swing.plaf.SeparatorUI; - /** * The JSeparator. It is mostly used to divide/space out * components. @@ -51,14 +52,15 @@ public class JSeparator extends JComponent implements SwingConstants, Accessible { /** - * AccessibleJSeparator + * Provides the accessibility features for the JSeparator + * component. */ protected class AccessibleJSeparator extends AccessibleJComponent { private static final long serialVersionUID = 916332890553201095L; /** - * Constructor AccessibleJSeparator + * Creates a new AccessibleJSeparator instance. */ protected AccessibleJSeparator() { @@ -66,9 +68,9 @@ public class JSeparator extends JComponent implements SwingConstants, } /** - * getAccessibleRole + * Returns the accessible role for the JSeparator component. * - * @return AccessibleRole + * @return {@link AccessibleRole#SEPARATOR}. */ public AccessibleRole getAccessibleRole() { @@ -82,7 +84,7 @@ public class JSeparator extends JComponent implements SwingConstants, private transient int orientation = HORIZONTAL; /** - * Creates a new horizontal JSeparator object. + * Creates a new horizontal JSeparator object. */ public JSeparator() { @@ -90,9 +92,13 @@ public class JSeparator extends JComponent implements SwingConstants, } /** - * Creates a new JSeparator object with the given orientation. + * Creates a new JSeparator object with the given orientation. * - * @param orientation The orientation of the JSeparator. + * @param orientation the orientation (either {@link #HORIZONTAL} or + * {@link #VERTICAL}). + * + * @throws IllegalArgumentException if orientation is not + * one of the specified values. */ public JSeparator(int orientation) { @@ -104,10 +110,9 @@ public class JSeparator extends JComponent implements SwingConstants, } /** - * This method returns the UI delegate being - * used with the JSeparator. + * Returns the UI delegate being used with the JSeparator. * - * @return SeparatorUI The JSeparator's UI delegate. + * @return The JSeparator's UI delegate. */ public SeparatorUI getUI() { @@ -115,10 +120,9 @@ public class JSeparator extends JComponent implements SwingConstants, } /** - * This method sets the UI delegate to use - * with the JSeparator. + * Sets the separator's UI delegate. * - * @param ui The UI delegate to use. + * @param ui the UI delegate. */ public void setUI(SeparatorUI ui) { @@ -126,8 +130,8 @@ public class JSeparator extends JComponent implements SwingConstants, } /** - * This method resets the UI delegate to the - * default for the current look and feel. + * Sets this separator's UI delegate to the default (obtained from the + * {@link UIManager}) for the current look and feel. */ public void updateUI() { @@ -135,11 +139,11 @@ public class JSeparator extends JComponent implements SwingConstants, } /** - * This method returns the identifier string - * that is used to determine the UI delegate - * from the current look and feel. + * Returns the suffix ("SeparatorUI" in this case) used to + * determine the class name for a UI delegate that can provide the look and + * feel for a JSeparator. * - * @return String The identifier string for the UI. + * @return "SeparatorUI". */ public String getUIClassID() { @@ -147,9 +151,11 @@ public class JSeparator extends JComponent implements SwingConstants, } /** - * This method returns the JSeparator's orientation. + * Returns the orientation of the JSeparator. * - * @return int The JSeparator's orientation. + * @return The orientation (one of {@link #HORIZONTAL} and {@link #VERTICAL}). + * + * @see #setOrientation(int) */ public int getOrientation() { @@ -157,33 +163,50 @@ public class JSeparator extends JComponent implements SwingConstants, } /** - * This method changes the JSeparator's orientation. + * Sets the orientation for the JSeparator and sends a + * {@link PropertyChangeEvent} (with the property name + * orientation) to all registered listeners. * - * @param orientation The JSeparator's orientation. + * @param orientation the orientation (either {@link #HORIZONTAL} or + * {@link #VERTICAL}). + * + * @throws IllegalArgumentException if orientation is not + * one of the specified values. + * + * @see #getOrientation() */ public void setOrientation(int orientation) { if (orientation != HORIZONTAL && orientation != VERTICAL) throw new IllegalArgumentException(orientation + " is not a valid orientation."); + int old = this.orientation; this.orientation = orientation; + firePropertyChange("orientation", old, orientation); } /** - * This method returns a string desribing the JSeparator. - * Normally only used in debugging. + * Returns an implementation-dependent string describing the attributes of + * this JSeparator. * - * @return String A string describing the JSeparator. + * @return A string describing the attributes of this JSeparator + * (never null). */ protected String paramString() { - return "JSeparator"; + String superParamStr = super.paramString(); + if (orientation == HORIZONTAL) + return superParamStr + ",orientation=HORIZONTAL"; + else + return superParamStr + ",orientation=VERTICAL"; } /** - * getAccessibleContext + * Returns the object that provides accessibility features for this + * JSeparator component. * - * @return AccessibleContext + * @return The accessible context (an instance of + * {@link AccessibleJSeparator}). */ public AccessibleContext getAccessibleContext() { diff --git a/javax/swing/JSlider.java b/javax/swing/JSlider.java index f298cbebf..ed94c4ecc 100644 --- a/javax/swing/JSlider.java +++ b/javax/swing/JSlider.java @@ -1068,15 +1068,35 @@ public class JSlider extends JComponent implements SwingConstants, Accessible, } /** - * Returns a string describing the attributes of this slider, for debugging - * purposes. According to the specification, this method is implementation - * specific, we just return "JSlider" at present. + * Returns an implementation-dependent string describing the attributes of + * this JSlider. * - * @return Returns a string describing the attributes of this slider. + * @return A string describing the attributes of this JSlider + * (never null). */ protected String paramString() { - return "JSlider"; + String superParamStr = super.paramString(); + StringBuffer sb = new StringBuffer(); + sb.append(",isInverted=").append(getInverted()); + sb.append(",majorTickSpacing=").append(getMajorTickSpacing()); + sb.append(",minorTickSpacing=").append(getMinorTickSpacing()); + sb.append(",orientation="); + if (orientation == HORIZONTAL) + sb.append("HORIZONTAL"); + else + sb.append("VERTICAL"); + sb.append(",paintLabels=").append(getPaintLabels()); + sb.append(",paintTicks=").append(getPaintTicks()); + sb.append(",paintTrack=").append(getPaintTrack()); + sb.append(",snapToTicks=").append(getSnapToTicks()); + + // the following is output by the reference implementation. We don't + // strictly need to replicate this. Perhaps it has some meaning, but + // I couldn't determine it yet... + sb.append(",snapToValue=true"); + + return superParamStr + sb.toString(); } /** diff --git a/javax/swing/JSpinner.java b/javax/swing/JSpinner.java index 882d216e1..70045ed53 100644 --- a/javax/swing/JSpinner.java +++ b/javax/swing/JSpinner.java @@ -106,6 +106,10 @@ public class JSpinner extends JComponent add(ftf); ftf.setValue(spinner.getValue()); ftf.addPropertyChangeListener(this); + if(getComponentOrientation().isLeftToRight()) + ftf.setHorizontalAlignment(JTextField.RIGHT); + else + ftf.setHorizontalAlignment(JTextField.LEFT); spinner.addChangeListener(this); } diff --git a/javax/swing/JSplitPane.java b/javax/swing/JSplitPane.java index cb2640570..4e18b7cda 100644 --- a/javax/swing/JSplitPane.java +++ b/javax/swing/JSplitPane.java @@ -1,5 +1,5 @@ /* JSplitPane.java -- - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -40,10 +40,12 @@ package javax.swing; import java.awt.Component; import java.awt.Graphics; +import java.beans.PropertyChangeEvent; import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleState; import javax.accessibility.AccessibleStateSet; import javax.accessibility.AccessibleValue; import javax.swing.plaf.SplitPaneUI; @@ -56,18 +58,18 @@ import javax.swing.plaf.SplitPaneUI; */ public class JSplitPane extends JComponent implements Accessible { + /** - * DOCUMENT ME! + * Provides the accessibility features for the JSplitPane + * component. */ - // FIXME: This inner class is a complete stub and must be implemented - // properly. protected class AccessibleJSplitPane extends JComponent.AccessibleJComponent implements AccessibleValue { private static final long serialVersionUID = -1788116871416305366L; /** - * Creates a new AccessibleJSplitPane object. + * Creates a new AccessibleJSplitPane instance. */ protected AccessibleJSplitPane() { @@ -75,75 +77,101 @@ public class JSplitPane extends JComponent implements Accessible } /** - * DOCUMENT ME! + * Returns a set containing the current state of the {@link JSplitPane} + * component. * - * @return DOCUMENT ME! + * @return The accessible state set. */ public AccessibleStateSet getAccessibleStateSet() { - return null; + AccessibleStateSet result = super.getAccessibleStateSet(); + if (getOrientation() == HORIZONTAL_SPLIT) + { + result.add(AccessibleState.HORIZONTAL); + } + else if (getOrientation() == VERTICAL_SPLIT) + { + result.add(AccessibleState.VERTICAL); + } + return result; } /** - * DOCUMENT ME! + * Returns the accessible role for the JSplitPane component. * - * @return DOCUMENT ME! + * @return {@link AccessibleRole#SPLIT_PANE}. */ public AccessibleRole getAccessibleRole() { - return null; + return AccessibleRole.SPLIT_PANE; } /** - * DOCUMENT ME! + * Returns an object that provides access to the current, minimum and + * maximum values for the {@link JSlider}. Since this class implements + * {@link AccessibleValue}, it returns itself. * - * @return DOCUMENT ME! + * @return The accessible value. */ public AccessibleValue getAccessibleValue() { - return null; + return this; } /** - * DOCUMENT ME! + * Returns the current divider location for the {@link JSplitPane} + * component, as an {@link Integer}. * - * @return DOCUMENT ME! + * @return The current divider location. */ public Number getCurrentAccessibleValue() { - return null; + return new Integer(getDividerLocation()); } /** - * DOCUMENT ME! + * Sets the divider location for the {@link JSplitPane} component and sends + * a {@link PropertyChangeEvent} (with the property name + * {@link AccessibleContext#ACCESSIBLE_VALUE_PROPERTY}) to all registered + * listeners. If the supplied value is null, this method + * does nothing and returns false. * - * @param value0 DOCUMENT ME! + * @param value the new slider value (null permitted). * - * @return DOCUMENT ME! + * @return true if the slider value is updated, and + * false otherwise. */ - public boolean setCurrentAccessibleValue(Number value0) + public boolean setCurrentAccessibleValue(Number value) { - return false; + if (value == null) + return false; + Number oldValue = getCurrentAccessibleValue(); + setDividerLocation(value.intValue()); + firePropertyChange(AccessibleContext.ACCESSIBLE_VALUE_PROPERTY, oldValue, + new Integer(value.intValue())); + return true; } /** - * DOCUMENT ME! + * Returns the minimum divider location for the {@link JSplitPane} + * component, as an {@link Integer}. * - * @return DOCUMENT ME! + * @return The minimum divider location. */ public Number getMinimumAccessibleValue() { - return null; + return new Integer(getMinimumDividerLocation()); } /** - * DOCUMENT ME! + * Returns the maximum divider location for the {@link JSplitPane} + * component, as an {@link Integer}. * - * @return DOCUMENT ME! + * @return The maximum divider location. */ public Number getMaximumAccessibleValue() { - return null; + return new Integer(getMaximumDividerLocation()); } } @@ -371,9 +399,11 @@ public class JSplitPane extends JComponent implements Accessible } /** - * DOCUMENT ME! + * Returns the object that provides accessibility features for this + * JSplitPane component. * - * @return DOCUMENT ME! + * @return The accessible context (an instance of + * {@link AccessibleJSplitPane}). */ public AccessibleContext getAccessibleContext() { @@ -559,14 +589,27 @@ public class JSplitPane extends JComponent implements Accessible } /** - * This method returns a String that describes this JSplitPane. The string - * is primarily used for debugging purposes. + * Returns an implementation-dependent string describing the attributes of + * this JSplitPane. * - * @return A String used for debugging purposes. + * @return A string describing the attributes of this JSplitPane + * (never null). */ protected String paramString() { - return "JSplitPane"; + // FIXME: the next line can be restored once PR27208 is fixed + String superParamStr = ""; //super.paramString(); + StringBuffer sb = new StringBuffer(); + sb.append(",continuousLayout=").append(isContinuousLayout()); + sb.append(",dividerSize=").append(getDividerSize()); + sb.append(",lastDividerLocation=").append(getLastDividerLocation()); + sb.append(",oneTouchExpandable=").append(isOneTouchExpandable()); + sb.append(",orientation="); + if (orientation == HORIZONTAL_SPLIT) + sb.append("HORIZONTAL_SPLIT"); + else + sb.append("VERTICAL_SPLIT"); + return superParamStr + sb.toString(); } /** @@ -753,11 +796,15 @@ public class JSplitPane extends JComponent implements Accessible } /** - * This method sets the orientation of the JSplitPane. + * Sets the orientation for the JSplitPane and sends a + * {@link PropertyChangeEvent} (with the property name + * {@link #ORIENTATION_PROPERTY}) to all registered listeners. * - * @param orientation The orientation of the JSplitPane. + * @param orientation the orientation (either {@link #HORIZONTAL_SPLIT} + * or {@link #VERTICAL_SPLIT}). * - * @throws IllegalArgumentException DOCUMENT ME! + * @throws IllegalArgumentException if orientation is not one of + * the listed values. */ public void setOrientation(int orientation) { @@ -784,7 +831,14 @@ public class JSplitPane extends JComponent implements Accessible */ public void setResizeWeight(double value) { - resizeWeight = value; + if (value < 0.0 || value > 1.0) + throw new IllegalArgumentException("Value outside permitted range."); + if (this.resizeWeight != value) + { + double old = resizeWeight; + resizeWeight = value; + firePropertyChange(RESIZE_WEIGHT_PROPERTY, old, value); + } } /** diff --git a/javax/swing/JTabbedPane.java b/javax/swing/JTabbedPane.java index 0c2180969..34ab8eeaa 100644 --- a/javax/swing/JTabbedPane.java +++ b/javax/swing/JTabbedPane.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing; +import gnu.classpath.NotImplementedException; + import java.awt.Color; import java.awt.Component; import java.awt.Point; @@ -102,6 +104,7 @@ public class JTabbedPane extends JComponent implements Serializable, * @param e the change event describing the change */ public void stateChanged(ChangeEvent e) + throws NotImplementedException { // Implement this properly. } @@ -113,6 +116,7 @@ public class JTabbedPane extends JComponent implements Serializable, * @return the accessible role of the JTabbedPane */ public AccessibleRole getAccessibleRole() + throws NotImplementedException { return null; } @@ -125,6 +129,7 @@ public class JTabbedPane extends JComponent implements Serializable, * JTabbedPane */ public int getAccessibleChildrenCount() + throws NotImplementedException { return 0; } @@ -153,6 +158,7 @@ public class JTabbedPane extends JComponent implements Serializable, * @return the current selection state of the JTabbedPane */ public AccessibleSelection getAccessibleSelection() + throws NotImplementedException { return null; } @@ -169,6 +175,7 @@ public class JTabbedPane extends JComponent implements Serializable, * this location */ public Accessible getAccessibleAt(Point p) + throws NotImplementedException { return null; } @@ -183,6 +190,7 @@ public class JTabbedPane extends JComponent implements Serializable, * JTabbedPane */ public int getAccessibleSelectionCount() + throws NotImplementedException { return 0; } @@ -195,6 +203,7 @@ public class JTabbedPane extends JComponent implements Serializable, * @return DOCUMENT ME! */ public Accessible getAccessibleSelection(int i) + throws NotImplementedException { return null; } @@ -207,6 +216,7 @@ public class JTabbedPane extends JComponent implements Serializable, * @return DOCUMENT ME! */ public boolean isAccessibleChildSelected(int i) + throws NotImplementedException { return false; } @@ -217,6 +227,7 @@ public class JTabbedPane extends JComponent implements Serializable, * @param i DOCUMENT ME! */ public void addAccessibleSelection(int i) + throws NotImplementedException { // TODO: Implement this properly. } @@ -227,6 +238,7 @@ public class JTabbedPane extends JComponent implements Serializable, * @param i DOCUMENT ME! */ public void removeAccessibleSelection(int i) + throws NotImplementedException { // TODO: Implement this properly. } @@ -235,6 +247,7 @@ public class JTabbedPane extends JComponent implements Serializable, * DOCUMENT ME! */ public void clearAccessibleSelection() + throws NotImplementedException { // TODO: Implement this properly. } @@ -243,6 +256,7 @@ public class JTabbedPane extends JComponent implements Serializable, * DOCUMENT ME! */ public void selectAllAccessibleSelection() + throws NotImplementedException { // TODO: Implement this properly. } @@ -595,12 +609,14 @@ public class JTabbedPane extends JComponent implements Serializable, } public AccessibleStateSet getAccessibleStateSet() + throws NotImplementedException { // FIXME: Implement this properly. return null; } public int getAccessibleIndexInParent() + throws NotImplementedException { // FIXME: Implement this properly. return 0; diff --git a/javax/swing/JTable.java b/javax/swing/JTable.java index 89272451e..3463ac26f 100644 --- a/javax/swing/JTable.java +++ b/javax/swing/JTable.java @@ -2053,9 +2053,6 @@ public class JTable int column, boolean includeSpacing) { - // moveToCellBeingEdited expects the cached value and clones it. - // If the caching would be removed later, uplate moveToCellBeingEdited - // as well. int height = getRowHeight(row); int width = columnModel.getColumn(column).getWidth(); int x_gap = columnModel.getColumnMargin(); @@ -2069,12 +2066,14 @@ public class JTable for (int i = 0; i < column; ++i) x += columnModel.getColumn(i).getWidth(); + + Rectangle rect = new Rectangle(); if (includeSpacing) - rectCache.setBounds(x, y, width, height +y_gap); + rect.setBounds(x, y, width, height +y_gap); else - rectCache.setBounds(x, y, width - x_gap, height); - return rectCache; + rect.setBounds(x, y, width - x_gap, height); + return rect; } public void clearSelection() @@ -2434,7 +2433,7 @@ public class JTable /** * Get the value of the columnCount property by - * delegation to the @{link #columnModel} field. + * delegation to the {@link #columnModel} field. * * @return The current value of the columnCount property */ @@ -2445,7 +2444,7 @@ public class JTable /** * Get the value of the rowCount property by - * delegation to the @{link #dataModel} field. + * delegation to the {@link #dataModel} field. * * @return The current value of the rowCount property */ @@ -2466,7 +2465,7 @@ public class JTable /** * Get the value of the selectedColumn property by - * delegation to the @{link #columnModel} field. + * delegation to the {@link #columnModel} field. * * @return The current value of the selectedColumn property */ @@ -2535,7 +2534,7 @@ public class JTable /** * Get the value of the selectedColumnCount property by - * delegation to the @{link #columnModel} field. + * delegation to the {@link #columnModel} field. * * @return The current value of the selectedColumnCount property */ @@ -2546,7 +2545,7 @@ public class JTable /** * Get the value of the selectedColumns property by - * delegation to the @{link #columnModel} field. + * delegation to the {@link #columnModel} field. * * @return The current value of the selectedColumns property */ @@ -2567,7 +2566,7 @@ public class JTable /** * Get the value of the selectedRowCount property by - * delegation to the @{link #selectionModel} field. + * delegation to the {@link #selectionModel} field. * * @return The current value of the selectedRowCount property */ @@ -2578,7 +2577,7 @@ public class JTable /** * Get the value of the selectedRows property by - * delegation to the @{link #selectionModel} field. + * delegation to the {@link #selectionModel} field. * * @return The current value of the selectedRows property */ @@ -3722,8 +3721,7 @@ public class JTable private void moveToCellBeingEdited(Component component) { Rectangle r = getCellRect(editingRow, editingColumn, true); - // Clone rectangle as getCellRect returns the cached value. - component.setBounds(new Rectangle(r)); + component.setBounds(r); } /** diff --git a/javax/swing/JToolBar.java b/javax/swing/JToolBar.java index bc97f9ecd..b576b4f2a 100644 --- a/javax/swing/JToolBar.java +++ b/javax/swing/JToolBar.java @@ -38,8 +38,6 @@ exception statement from your version. */ package javax.swing; -import gnu.classpath.NotImplementedException; - import java.awt.Component; import java.awt.Container; import java.awt.Dimension; @@ -67,17 +65,15 @@ import javax.swing.plaf.ToolBarUI; public class JToolBar extends JComponent implements SwingConstants, Accessible { /** - * AccessibleJToolBar + * Provides the accessibility features for the JToolBar + * component. */ - // FIXME: This inner class is a complete stub and must be implemented - // properly. protected class AccessibleJToolBar extends AccessibleJComponent { - /** DOCUMENT ME! */ private static final long serialVersionUID = -5516888265903814215L; /** - * Constructor AccessibleJToolBar + * Creates a new AccessibleJToolBar instance. */ protected AccessibleJToolBar() { @@ -85,20 +81,23 @@ public class JToolBar extends JComponent implements SwingConstants, Accessible } /** - * getAccessibleStateSet + * Returns a set containing the current state of the {@link JToolBar} + * component. The current implementation simply calls the superclass. * - * @return AccessibleStateSet + * @return The accessible state set. */ public AccessibleStateSet getAccessibleStateSet() - throws NotImplementedException { - return null; // TODO + // running tests against the reference implementation, I was unable + // to find any state information that is set specifically by the + // tool bar... + return super.getAccessibleStateSet(); } /** - * getAccessibleRole + * Returns the accessible role for the JToolBar component. * - * @return AccessibleRole + * @return {@link AccessibleRole#TOOL_BAR}. */ public AccessibleRole getAccessibleRole() { @@ -768,9 +767,10 @@ public class JToolBar extends JComponent implements SwingConstants, Accessible } // paramString() /** - * getAccessibleContext + * Returns the object that provides accessibility features for this + * JToolBar component. * - * @return AccessibleContext + * @return The accessible context (an instance of {@link AccessibleJToolBar}). */ public AccessibleContext getAccessibleContext() { diff --git a/javax/swing/JToolTip.java b/javax/swing/JToolTip.java index 1a4a0f205..836c122c6 100644 --- a/javax/swing/JToolTip.java +++ b/javax/swing/JToolTip.java @@ -127,7 +127,7 @@ public class JToolTip extends JComponent implements Accessible * Returns the object that provides accessibility features for this * JToolTip component. * - * @return The accessible context (an instance of {@link AccessibleJToolTip}. + * @return The accessible context (an instance of {@link AccessibleJToolTip}). */ public AccessibleContext getAccessibleContext() { diff --git a/javax/swing/JTree.java b/javax/swing/JTree.java index f4b37e106..eb54523e2 100644 --- a/javax/swing/JTree.java +++ b/javax/swing/JTree.java @@ -1276,10 +1276,16 @@ public class JTree extends JComponent implements Scrollable, Accessible */ public void valueChanged(TreeSelectionEvent ev) { - TreeSelectionEvent rewritten = + TreeSelectionEvent rewritten = (TreeSelectionEvent) ev.cloneWithSource(JTree.this); fireValueChanged(rewritten); - JTree.this.repaint(); + + // Only repaint the changed nodes. + TreePath[] changed = ev.getPaths(); + for (int i = 0; i < changed.length; i++) + { + repaint(getPathBounds(changed[i])); + } } } @@ -1396,8 +1402,6 @@ public class JTree extends JComponent implements Scrollable, Accessible private TreePath anchorSelectionPath; - private TreePath leadSelectionPath; - /** * This contains the state of all nodes in the tree. Al/ entries map the * TreePath of a note to to its state. Valid states are EXPANDED and @@ -1504,8 +1508,8 @@ public class JTree extends JComponent implements Scrollable, Accessible */ public JTree(TreeModel model) { - updateUI(); setRootVisible(true); + // The setModel also calls the updateUI setModel(model); setSelectionModel(new EmptySelectionModel()); selectionModel.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); @@ -1562,7 +1566,15 @@ public class JTree extends JComponent implements Scrollable, Accessible TreeUI ui = getUI(); return ui != null ? ui.getPathForRow(this, row) : null; } - + + /** + * Get the pathes that are displayes between the two given rows. + * + * @param index0 the starting row, inclusive + * @param index1 the ending row, inclusive + * + * @return the array of the tree pathes + */ protected TreePath[] getPathBetweenRows(int index0, int index1) { TreeUI ui = getUI(); @@ -1941,9 +1953,19 @@ public class JTree extends JComponent implements Scrollable, Accessible if (rootVisible == flag) return; + // If the root is currently selected, unselect it + if (rootVisible && !flag) + { + TreeSelectionModel model = getSelectionModel(); + // The root is always shown in the first row + TreePath rootPath = getPathForRow(0); + model.removeSelectionPath(rootPath); + } + boolean oldValue = rootVisible; rootVisible = flag; firePropertyChange(ROOT_VISIBLE_PROPERTY, oldValue, flag); + } public boolean getShowsRootHandles() @@ -2110,27 +2132,8 @@ public class JTree extends JComponent implements Scrollable, Accessible { if (path == null) return; - - Object[] oPath = path.getPath(); - TreePath temp = new TreePath(oPath[0]); - boolean stop = false; - int i = 1; - while (!stop) - { - while (isVisible(temp)) - if (i < oPath.length) - temp = temp.pathByAddingChild(oPath[i++]); - else - { - stop = true; - break; - } - makeVisible(temp); - } Rectangle rect = getPathBounds(path); scrollRectToVisible(rect); - revalidate(); - repaint(); } public void scrollRowToVisible(int row) @@ -2225,7 +2228,15 @@ public class JTree extends JComponent implements Scrollable, Accessible addSelectionPaths(paths); } - + + /** + * Select all rows between the two given indexes, inclusive. The method + * will not select the inner leaves and braches of the currently collapsed + * nodes in this interval. + * + * @param index0 the starting row, inclusive + * @param index1 the ending row, inclusive + */ public void addSelectionInterval(int index0, int index1) { TreePath[] paths = getPathBetweenRows(index0, index1); @@ -2281,7 +2292,10 @@ public class JTree extends JComponent implements Scrollable, Accessible public TreePath getLeadSelectionPath() { - return leadSelectionPath; + if (selectionModel == null) + return null; + else + return selectionModel.getLeadSelectionPath(); } /** @@ -2289,12 +2303,24 @@ public class JTree extends JComponent implements Scrollable, Accessible */ public void setLeadSelectionPath(TreePath path) { - if (leadSelectionPath == path) - return; - - TreePath oldValue = leadSelectionPath; - leadSelectionPath = path; - firePropertyChange(LEAD_SELECTION_PATH_PROPERTY, oldValue, path); + if (selectionModel != null) + { + TreePath oldValue = selectionModel.getLeadSelectionPath(); + if (path.equals(oldValue)) + return; + + // Repaint the previous and current rows with the lead selection path. + if (path != null) + { + repaint(getPathBounds(path)); + selectionModel.addSelectionPath(path); + } + + if (oldValue!=null) + repaint(getPathBounds(oldValue)); + + firePropertyChange(LEAD_SELECTION_PATH_PROPERTY, oldValue, path); + } } /** @@ -2430,7 +2456,8 @@ public class JTree extends JComponent implements Scrollable, Accessible public void expandPath(TreePath path) { // Don't expand if path is null - if (path == null) + // or is already expanded. + if (path == null || isExpanded(path)) return; try @@ -2967,10 +2994,20 @@ public class JTree extends JComponent implements Scrollable, Accessible } /** - * Sent when the tree has changed enough that we need to resize the bounds, - * but not enough that we need to remove the expanded node set (e.g nodes - * were expanded or collapsed, or nodes were inserted into the tree). You - * should never have to invoke this, the UI will invoke this as it needs to. + *

+ * Sent when the tree has changed enough that we need to resize the bounds, + * but not enough that we need to remove the expanded node set (e.g nodes were + * expanded or collapsed, or nodes were inserted into the tree). You should + * never have to invoke this, the UI will invoke this as it needs to. + *

+ *

+ * If the tree uses {@link DefaultTreeModel}, you must call + * {@link DefaultTreeModel#reload(TreeNode)} or + * {@link DefaultTreeModel#reload()} after adding or removing nodes. Following + * the official Java 1.5 API standard, just calling treeDidChange, repaint() + * or revalidate() does not update the tree appearance properly. + * + * @see DefaultTreeModel#reload() */ public void treeDidChange() { diff --git a/javax/swing/ProgressMonitor.java b/javax/swing/ProgressMonitor.java index dc0c6434c..73e36b9ca 100644 --- a/javax/swing/ProgressMonitor.java +++ b/javax/swing/ProgressMonitor.java @@ -398,7 +398,11 @@ public class ProgressMonitor if (( now - timestamp ) > millisToDecideToPopup ) { first = false; - long expected = ( now - timestamp ) * ( max - min ) / ( progress - min ); + + + long expected = ( progress - min == 0 ) ? + ( now - timestamp ) * ( max - min ) : + ( now - timestamp ) * ( max - min ) / ( progress - min ); if ( expected > millisToPopup ) { diff --git a/javax/swing/RepaintManager.java b/javax/swing/RepaintManager.java index a5e0379f6..9e246ee1e 100644 --- a/javax/swing/RepaintManager.java +++ b/javax/swing/RepaintManager.java @@ -160,9 +160,9 @@ public class RepaintManager if (o1 instanceof JComponent && o2 instanceof JComponent) { JComponent c1 = (JComponent) o1; - Rectangle d1 = (Rectangle) dirtyComponents.get(c1); + Rectangle d1 = (Rectangle) dirtyComponentsWork.get(c1); JComponent c2 = (JComponent) o2; - Rectangle d2 = (Rectangle) dirtyComponents.get(c2); + Rectangle d2 = (Rectangle) dirtyComponentsWork.get(c2); return d2.width * d2.height - d1.width * d1.height; } throw new ClassCastException("This comparator can only be used with " @@ -187,6 +187,12 @@ public class RepaintManager */ HashMap dirtyComponents; + /** + * The dirtyComponents which is used in paintDiryRegions to avoid unnecessary + * locking. + */ + HashMap dirtyComponentsWork; + /** * The comparator used for ordered inserting into the repaintOrder list. */ @@ -262,6 +268,7 @@ public class RepaintManager public RepaintManager() { dirtyComponents = new HashMap(); + dirtyComponentsWork = new HashMap(); invalidComponents = new ArrayList(); repaintWorker = new RepaintWorker(); doubleBufferMaximumSize = new Dimension(2000,2000); @@ -554,31 +561,36 @@ public class RepaintManager if (dirtyComponents.size() == 0) return; + // Swap dirtyRegions with dirtyRegionsWork to avoid locking. synchronized (dirtyComponents) { - // We sort the components by their size here. This way we have a good - // chance that painting the bigger components also paints the smaller - // components and we don't need to paint them twice. - ArrayList repaintOrder = new ArrayList(dirtyComponents.size()); - repaintOrder.addAll(dirtyComponents.keySet()); - if (comparator == null) - comparator = new ComponentComparator(); - Collections.sort(repaintOrder, comparator); - repaintUnderway = true; - for (Iterator i = repaintOrder.iterator(); i.hasNext();) - { - JComponent comp = (JComponent) i.next(); - // If a component is marked completely clean in the meantime, then skip - // it. - Rectangle damaged = (Rectangle) dirtyComponents.get(comp); - if (damaged == null || damaged.isEmpty()) - continue; - comp.paintImmediately(damaged); - dirtyComponents.remove(comp); - } - repaintUnderway = false; - commitRemainingBuffers(); + HashMap swap = dirtyComponents; + dirtyComponents = dirtyComponentsWork; + dirtyComponentsWork = swap; } + + ArrayList repaintOrder = new ArrayList(dirtyComponentsWork.size());; + // We sort the components by their size here. This way we have a good + // chance that painting the bigger components also paints the smaller + // components and we don't need to paint them twice. + repaintOrder.addAll(dirtyComponentsWork.keySet()); + + if (comparator == null) + comparator = new ComponentComparator(); + Collections.sort(repaintOrder, comparator); + repaintUnderway = true; + for (Iterator i = repaintOrder.iterator(); i.hasNext();) + { + JComponent comp = (JComponent) i.next(); + // If a component is marked completely clean in the meantime, then skip + // it. + Rectangle damaged = (Rectangle) dirtyComponentsWork.remove(comp); + if (damaged == null || damaged.isEmpty()) + continue; + comp.paintImmediately(damaged); + } + repaintUnderway = false; + commitRemainingBuffers(); } /** diff --git a/javax/swing/ScrollPaneLayout.java b/javax/swing/ScrollPaneLayout.java index 9f6829f4d..da8f03afb 100644 --- a/javax/swing/ScrollPaneLayout.java +++ b/javax/swing/ScrollPaneLayout.java @@ -328,7 +328,7 @@ public class ScrollPaneLayout // parent is no JScrollPane, so do we. JScrollPane sc = (JScrollPane) parent; JViewport viewport = sc.getViewport(); - Dimension viewSize = viewport.getViewSize(); + Dimension viewSize = viewport.getView().getPreferredSize(); int x1 = 0, x2 = 0, x3 = 0, x4 = 0; int y1 = 0, y2 = 0, y3 = 0, y4 = 0; diff --git a/javax/swing/SpinnerDateModel.java b/javax/swing/SpinnerDateModel.java index a92f5a49e..e5ff76f1a 100644 --- a/javax/swing/SpinnerDateModel.java +++ b/javax/swing/SpinnerDateModel.java @@ -59,13 +59,13 @@ public class SpinnerDateModel extends AbstractSpinnerModel private Calendar date; /** - * The start or earliest permitted date (null for no - * minimum). + * A constraint on the start or earliest permitted date (null + * for no minimum). */ private Comparable start; /** - * The end or latest permitted date (null for no + * A constraint on the end or latest permitted date (null for no * maximum). */ private Comparable end; @@ -77,7 +77,6 @@ public class SpinnerDateModel extends AbstractSpinnerModel /** * For compatability with Sun's JDK - * FIXME: Which fields should be serialized? */ private static final long serialVersionUID = -4802518107105940612L; @@ -92,14 +91,21 @@ public class SpinnerDateModel extends AbstractSpinnerModel } /** - * Constructs a SpinnerDateModel which spins a given calendar field, - * using a given date and start and end date limits. - * @param value - the initial Date value - * @param start - start limit, as a Date object, or null - * for no lower limit. - * @param end - end limit, or null for no upper limit. - * @param calendarField - the Calendar field to spin, - * (Calendar.ZONE_OFFSET and Calendar.DST_OFFSET are invalid) + * Constructs a SpinnerDateModel with the specified value, lower + * and upper bounds, and which spins the specified calendar field. + *

+ * The start and end limits must have a + * compareTo method that supports instances of {@link Date}, but + * do not themselves need to be instances of {@link Date} (although typically + * they are). + * + * @param value the initial value/date (null not permitted). + * @param start a constraint that specifies the earliest permitted date + * value, or null for no lower limit. + * @param end a constraint that specifies the latest permitted date value, + * or null for no upper limit. + * @param calendarField the Calendar field to spin, + * (Calendar.ZONE_OFFSET and Calendar.DST_OFFSET are invalid) */ public SpinnerDateModel(Date value, Comparable start, Comparable end, int calendarField) @@ -129,9 +135,11 @@ public class SpinnerDateModel extends AbstractSpinnerModel } /** - * Returns the current date. + * Returns the current date/time. + * + * @return The current date/time (never null). * - * @return The current date. + * @see #getValue() */ public Date getDate() { @@ -139,9 +147,12 @@ public class SpinnerDateModel extends AbstractSpinnerModel } /** - * Returns the start date, or null if there is no minimum date. + * Returns the lower limit on the date/time value, or null if + * there is no minimum date/time. * - * @return The start date. + * @return The lower limit. + * + * @see #setStart(Comparable) */ public Comparable getStart() { @@ -149,9 +160,12 @@ public class SpinnerDateModel extends AbstractSpinnerModel } /** - * Returns the end date, or null if there is no maximum date. + * Returns the upper limit on the date/time value, or null if + * there is no maximum date/time. + * + * @return The upper limit. * - * @return The end date. + * @see #setEnd(Comparable) */ public Comparable getEnd() { @@ -160,9 +174,9 @@ public class SpinnerDateModel extends AbstractSpinnerModel /** * Returns the current date in the sequence (this method returns the same as - * {@link #getDate()}. + * {@link #getDate()}). * - * @return The current date. + * @return The current date (never null). */ public Object getValue() { @@ -171,10 +185,13 @@ public class SpinnerDateModel extends AbstractSpinnerModel /** * Returns the next date in the sequence, or null if the - * next date is after the end date. The current date is not changed. + * next date is past the upper limit (if one is specified). The current date + * is not changed. * * @return The next date, or null if the current value is * the latest date represented by the model. + * + * @see #getEnd() */ public Object getNextValue() { @@ -190,11 +207,13 @@ public class SpinnerDateModel extends AbstractSpinnerModel /** * Returns the previous date in the sequence, or null if the - * previous date is prior to the start date. The current date is not - * changed. + * previous date is prior to the lower limit (if one is specified). The + * current date is not changed. * * @return The previous date, or null if the current value is * the earliest date represented by the model. + * + * @see #getStart() */ public Object getPreviousValue() { @@ -233,14 +252,16 @@ public class SpinnerDateModel extends AbstractSpinnerModel } /** - * Sets the start date and, if the new date is different to the old date, - * sends a {@link ChangeEvent} to all registered listeners. A - * null date is interpreted as "no start date". No check - * is made to ensure that the new start date is on or before the current - * date - the caller is responsible for ensuring that this relationship - * holds. + * Sets the lower limit for the date/time value and, if the new limit is + * different to the old limit, sends a {@link ChangeEvent} to all registered + * listeners. A null value is interpreted as "no lower limit". + * No check is made to ensure that the current date/time is on or after the + * new lower limit - the caller is responsible for ensuring that this + * relationship holds. In addition, the caller should ensure that + * start is {@link Serializable}. * - * @param start the new start date (null permitted). + * @param start the new lower limit for the date/time value + * (null permitted). */ public void setStart(Comparable start) { @@ -252,13 +273,16 @@ public class SpinnerDateModel extends AbstractSpinnerModel } /** - * Sets the end date and, if the new date is different to the old date, - * sends a {@link ChangeEvent} to all registered listeners. A - * null date is interpreted as "no end date". No check - * is made to ensure that the new end date is on or after the current date - - * the caller is responsible for ensuring that this relationship holds. + * Sets the upper limit for the date/time value and, if the new limit is + * different to the old limit, sends a {@link ChangeEvent} to all registered + * listeners. A null value is interpreted as "no upper limit". + * No check is made to ensure that the current date/time is on or before the + * new upper limit - the caller is responsible for ensuring that this + * relationship holds. In addition, the caller should ensure that + * end is {@link Serializable}. * - * @param end the new end date (null permitted). + * @param end the new upper limit for the date/time value (null + * permitted). */ public void setEnd(Comparable end) { diff --git a/javax/swing/SpinnerNumberModel.java b/javax/swing/SpinnerNumberModel.java index 389c536e4..1abbbe377 100644 --- a/javax/swing/SpinnerNumberModel.java +++ b/javax/swing/SpinnerNumberModel.java @@ -110,12 +110,14 @@ public class SpinnerNumberModel extends AbstractSpinnerModel } /** - * Creates a SpinnerNumberModel with the given attributes. + * Creates a SpinnerNumberModel with the given attributes. The + * caller should ensure that both minimum and + * maximum are serializable. * - * @param value the initial value. + * @param value the initial value (null not permitted). * @param minimum the minimum value (null permitted). * @param maximum the maximum value (null permitted). - * @param stepSize the step size. + * @param stepSize the step size (null not permitted). * * @throws IllegalArgumentException if minimum <= value <= maximum * does not hold @@ -171,9 +173,12 @@ public class SpinnerNumberModel extends AbstractSpinnerModel } /** - * Returns the current value. + * Returns the current value, which for this class is always an instance of + * {@link Number}. * * @return The current value. + * + * @see #getNumber() */ public Object getValue() { @@ -258,6 +263,8 @@ public class SpinnerNumberModel extends AbstractSpinnerModel * Returns the minimum value, or null if there is no minimum. * * @return The minimum value. + * + * @see #setMinimum(Comparable) */ public Comparable getMinimum() { @@ -270,9 +277,12 @@ public class SpinnerNumberModel extends AbstractSpinnerModel * null value is interpreted as "no minimum value". No check * is made to ensure that the new minimum is less than or equal to the * current value, the caller is responsible for ensuring that this - * relationship holds. + * relationship holds. In addition, the caller should ensure that + * newMinimum is {@link Serializable}. * * @param newMinimum the new minimum value (null permitted). + * + * @see #getMinimum() */ public void setMinimum(Comparable newMinimum) { @@ -287,6 +297,9 @@ public class SpinnerNumberModel extends AbstractSpinnerModel * Returns the maximum value, or null if there is no maximum. * * @return The maximum value. + * + * @see #getMinimum() + * @see #setMaximum(Comparable) */ public Comparable getMaximum() { @@ -299,9 +312,12 @@ public class SpinnerNumberModel extends AbstractSpinnerModel * null value is interpreted as "no maximum value". No check * is made to ensure that the new maximum is greater than or equal to the * current value, the caller is responsible for ensuring that this - * relationship holds. + * relationship holds. In addition, the caller should ensure that + * newMaximum is {@link Serializable}. * * @param newMaximum the new maximum (null permitted). + * + * @see #getMaximum() */ public void setMaximum(Comparable newMaximum) { @@ -315,7 +331,7 @@ public class SpinnerNumberModel extends AbstractSpinnerModel /** * Returns the step size. * - * @return The step size. + * @return The step size (never null). */ public Number getStepSize() { diff --git a/javax/swing/UIManager.java b/javax/swing/UIManager.java index 3b9166261..e1ee28b3f 100644 --- a/javax/swing/UIManager.java +++ b/javax/swing/UIManager.java @@ -1,5 +1,5 @@ /* UIManager.java -- - Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2004, 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,8 +38,6 @@ exception statement from your version. */ package javax.swing; -import gnu.classpath.NotImplementedException; - import java.awt.Color; import java.awt.Dimension; import java.awt.Font; diff --git a/javax/swing/ViewportLayout.java b/javax/swing/ViewportLayout.java index 67b69eb28..b61834e9e 100644 --- a/javax/swing/ViewportLayout.java +++ b/javax/swing/ViewportLayout.java @@ -158,7 +158,7 @@ public class ViewportLayout implements LayoutManager, Serializable // the viewport require inputs in view space. Rectangle portBounds = port.getViewRect(); - Dimension viewPref = view.getPreferredSize(); + Dimension viewPref = new Dimension(view.getPreferredSize()); Point portLowerRight = new Point(portBounds.x + portBounds.width, portBounds.y + portBounds.height); @@ -182,14 +182,10 @@ public class ViewportLayout implements LayoutManager, Serializable } } - // The scroll pane manages the view size itself. - if (! (port.getParent() instanceof JScrollPane) ) - { - if (viewPref.width < portBounds.width) - viewPref.width = portBounds.width; - if (viewPref.height < portBounds.height) - viewPref.height = portBounds.height; - } + if (viewPref.width < portBounds.width) + viewPref.width = portBounds.width; + if (viewPref.height < portBounds.height) + viewPref.height = portBounds.height; // If the view is larger than the port, the port is top and right // aligned. diff --git a/javax/swing/border/AbstractBorder.java b/javax/swing/border/AbstractBorder.java index 7cbbcdaa8..c995de1c2 100644 --- a/javax/swing/border/AbstractBorder.java +++ b/javax/swing/border/AbstractBorder.java @@ -1,5 +1,5 @@ /* AbstractBorder.java -- - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -68,7 +68,7 @@ public abstract class AbstractBorder implements Border, Serializable * Performs nothing, because the default implementation provided by * this class is an invisible, zero-width border. Subclasses will * likely want to override this method, but they are not required - * for doing so. + * to do so. * * @param c the component whose border is to be painted. * @param g the graphics for painting. @@ -87,9 +87,11 @@ public abstract class AbstractBorder implements Border, Serializable } /** - * Measures the width of this border. + * Returns the insets required for drawing this border around the specified + * component. * - * @param c the component whose border is to be measured. + * @param c the component that the border applies to (ignored here, + * subclasses may use it). * * @return an Insets object whose left, right, * top and bottom fields indicate the @@ -104,16 +106,23 @@ public abstract class AbstractBorder implements Border, Serializable } /** - * Determines the insets of this border. The implementation provided - * by AbstractButton sets the left, right, - * top and bottom fields of the passed - * insets parameter to zero. + * Returns the insets required for drawing this border around the specified + * component. The default implementation provided here sets the + * left, right, top and + * bottom fields of the passed insets parameter to + * zero. * - * @param c the component whose border is to be measured + * @param c the component that the border applies to (ignored here, + * subclasses may use it). + * @param insets an instance that will be overwritten and returned as the + * result (null not permitted). * - * @return the same object that was passed for insets + * @return The border insets (the same object that was passed as the + * insets argument). * * @see #getBorderInsets(Component) + * + * @throws NullPointerException if insets is null. */ public Insets getBorderInsets(Component c, Insets insets) { @@ -126,7 +135,7 @@ public abstract class AbstractBorder implements Border, Serializable * fills every pixel in its area when painting. Partially * translucent borders must return false, or ugly * artifacts can appear on screen. The default implementation - * provided by AbstractBorder always returns false. + * provided here always returns false. * * @return false. */ @@ -136,9 +145,9 @@ public abstract class AbstractBorder implements Border, Serializable } /** - * Returns a rectangle that covers the specified area minus this - * border. Components that wish to determine an area into which - * they can safely draw without intersecting with a border might + * Returns a rectangle that covers the specified area minus the insets + * required to draw this border. Components that wish to determine an area + * into which they can safely draw without intersecting with a border might * want to use this helper method. * * @param c the component in the center of this border. @@ -146,24 +155,30 @@ public abstract class AbstractBorder implements Border, Serializable * @param y the vertical position of the border. * @param width the width of the available area for the border. * @param height the height of the available area for the border. + * + * @return The interior rectangle. */ public Rectangle getInteriorRectangle(Component c, int x, int y, int width, int height) { - return getInteriorRectangle (c, this, x, y, width, height); + return getInteriorRectangle(c, this, x, y, width, height); } /** - * Returns a rectangle that covers the specified area minus a - * border. Components that wish to determine an area into which - * they can safely draw without intersecting with a border might - * want to use this helper method. + * Returns a rectangle that covers the specified area minus the insets + * required to draw the specified border (if the border is null, + * zero insets are assumed). Components that wish to determine an area into + * which they can safely draw without intersecting with a border might want + * to use this helper method. * * @param c the component in the center of this border. + * @param b the border (null permitted). * @param x the horizontal position of the border. * @param y the vertical position of the border. * @param width the width of the available area for the border. * @param height the height of the available area for the border. + * + * @return The interior rectangle. */ public static Rectangle getInteriorRectangle(Component c, Border b, int x, int y, int width, int height) @@ -172,7 +187,7 @@ public abstract class AbstractBorder implements Border, Serializable if (b != null) { - borderInsets = b.getBorderInsets (c); + borderInsets = b.getBorderInsets(c); x += borderInsets.left; y += borderInsets.top; width -= borderInsets.left + borderInsets.right; diff --git a/javax/swing/border/BevelBorder.java b/javax/swing/border/BevelBorder.java index 45b758cae..403c35c04 100644 --- a/javax/swing/border/BevelBorder.java +++ b/javax/swing/border/BevelBorder.java @@ -305,6 +305,8 @@ public class BevelBorder extends AbstractBorder * * @param c the component enclosed by this border. * + * @return The color. + * * @see #getHighlightInnerColor(java.awt.Component) * @see java.awt.Color#brighter() */ @@ -326,6 +328,8 @@ public class BevelBorder extends AbstractBorder * * @param c the component enclosed by this border. * + * @return The color. + * * @see java.awt.Component#getBackground() * @see java.awt.Color#brighter() */ @@ -347,6 +351,8 @@ public class BevelBorder extends AbstractBorder * * @param c the component enclosed by this border. * + * @return The color. + * * @see java.awt.Component#getBackground() * @see java.awt.Color#darker() */ @@ -367,6 +373,8 @@ public class BevelBorder extends AbstractBorder * * @param c the component enclosed by this border. * + * @return The color. + * * @see #getShadowInnerColor(java.awt.Component) * @see java.awt.Color#darker() */ @@ -384,6 +392,8 @@ public class BevelBorder extends AbstractBorder * highlighted edges when painting the border, or null * if that color will be derived from the background of the enclosed * Component. + * + * @return The color (possibly null). */ public Color getHighlightOuterColor() { @@ -396,6 +406,8 @@ public class BevelBorder extends AbstractBorder * highlighted edges when painting the border, or null * if that color will be derived from the background of the enclosed * Component. + * + * @return The color (possibly null). */ public Color getHighlightInnerColor() { @@ -408,6 +420,8 @@ public class BevelBorder extends AbstractBorder * shadowed edges when painting the border, or null if * that color will be derived from the background of the enclosed * Component. + * + * @return The color (possibly null). */ public Color getShadowInnerColor() { @@ -420,6 +434,8 @@ public class BevelBorder extends AbstractBorder * shadowed edges when painting the border, or null if * that color will be derived from the background of the enclosed * Component. + * + * @return The color (possibly null). */ public Color getShadowOuterColor() { @@ -430,6 +446,8 @@ public class BevelBorder extends AbstractBorder /** * Returns the appearance of this border, which is either {@link * #RAISED} or {@link #LOWERED}. + * + * @return The bevel type ({@link #RAISED} or {@link #LOWERED}). */ public int getBevelType() { diff --git a/javax/swing/border/CompoundBorder.java b/javax/swing/border/CompoundBorder.java index 998a9bab3..a69c5e20a 100644 --- a/javax/swing/border/CompoundBorder.java +++ b/javax/swing/border/CompoundBorder.java @@ -224,6 +224,8 @@ public class CompoundBorder extends AbstractBorder * Returns the outside border, which is painted outside both the * bordered Component and the inside border. It is valid for the * result to be null. + * + * @return The outside border (possibly null). */ public Border getOutsideBorder() { @@ -234,6 +236,8 @@ public class CompoundBorder extends AbstractBorder * Returns the inside border, which is painted between the bordered * Component and the outside border. It is valid for the result to * be null. + * + * @return The inside border (possibly null). */ public Border getInsideBorder () { diff --git a/javax/swing/border/EtchedBorder.java b/javax/swing/border/EtchedBorder.java index 22882b78c..cd48b18da 100644 --- a/javax/swing/border/EtchedBorder.java +++ b/javax/swing/border/EtchedBorder.java @@ -281,6 +281,8 @@ public class EtchedBorder extends AbstractBorder /** * Returns the appearance of this EtchedBorder, which is either * {@link #RAISED} or {@link #LOWERED}. + * + * @return The type ({@link #RAISED} or {@link #LOWERED}). */ public int getEtchType() { @@ -297,6 +299,8 @@ public class EtchedBorder extends AbstractBorder * * @param c the component enclosed by this border. * + * @return The color. + * * @see java.awt.Component#getBackground() * @see java.awt.Color#brighter() */ @@ -312,6 +316,8 @@ public class EtchedBorder extends AbstractBorder * Returns the color that will be used for highlighted parts when * painting the border, or null if that color will be * derived from the background of the enclosed Component. + * + * @return The highlight color (possibly null). */ public Color getHighlightColor() { @@ -328,6 +334,8 @@ public class EtchedBorder extends AbstractBorder * * @param c the component enclosed by this border. * + * @return The shadow color. + * * @see java.awt.Component#getBackground() * @see java.awt.Color#darker() */ @@ -344,6 +352,8 @@ public class EtchedBorder extends AbstractBorder * Returns the color that will be used for shadowed parts when * painting the border, or null if that color will be * derived from the background of the enclosed Component. + * + * @return The shadow color (possibly null). */ public Color getShadowColor() { diff --git a/javax/swing/border/LineBorder.java b/javax/swing/border/LineBorder.java index 36abddd91..31e19fe1f 100644 --- a/javax/swing/border/LineBorder.java +++ b/javax/swing/border/LineBorder.java @@ -162,8 +162,10 @@ public class LineBorder extends AbstractBorder /** - * Returns a black, one pixel thick, plain LineBorder. The method - * may always return the same (singleton) LineBorder instance. + * Returns a black, one pixel thick, plain {@link LineBorder}. The method + * may always return the same (singleton) {@link LineBorder} instance. + * + * @return The border. */ public static Border createBlackLineBorder() { @@ -178,8 +180,10 @@ public class LineBorder extends AbstractBorder /** - * Returns a gray, one pixel thick, plain LineBorder. The method - * may always return the same (singleton) LineBorder instance. + * Returns a gray, one pixel thick, plain {@link LineBorder}. The method + * may always return the same (singleton) {@link LineBorder} instance. + * + * @return The border. */ public static Border createGrayLineBorder() { @@ -295,6 +299,8 @@ public class LineBorder extends AbstractBorder /** * Returns the color of the line. + * + * @return The line color (never null). */ public Color getLineColor() { @@ -304,6 +310,8 @@ public class LineBorder extends AbstractBorder /** * Returns the thickness of the line in pixels. + * + * @return The line thickness (in pixels). */ public int getThickness() { diff --git a/javax/swing/border/MatteBorder.java b/javax/swing/border/MatteBorder.java index 4d5b8c253..114cac623 100644 --- a/javax/swing/border/MatteBorder.java +++ b/javax/swing/border/MatteBorder.java @@ -299,6 +299,8 @@ public class MatteBorder extends EmptyBorder * Returns the color that is used for filling the border, or * null if the border is filled with repetitions of a * tile icon. + * + * @return The color (possibly null). */ public Color getMatteColor() { @@ -310,6 +312,8 @@ public class MatteBorder extends EmptyBorder * Returns the icon is used for tiling the border, or * null if the border is filled with a color instead of * an icon. + * + * @return The icon (possibly null). */ public Icon getTileIcon() { diff --git a/javax/swing/border/TitledBorder.java b/javax/swing/border/TitledBorder.java index 8d3ee13d4..38b575423 100644 --- a/javax/swing/border/TitledBorder.java +++ b/javax/swing/border/TitledBorder.java @@ -912,8 +912,10 @@ public class TitledBorder extends AbstractBorder * Calculates the minimum size needed for displaying the border * and its title. * - * @param c the Component for which this TitledBorder consitutes + * @param c the Component for which this TitledBorder constitutes * a border. + * + * @return The minimum size. */ public Dimension getMinimumSize(Component c) { @@ -980,6 +982,10 @@ public class TitledBorder extends AbstractBorder /** * Performs various measurements for the current state of this TitledBorder * and the given Component. + * + * @param c the component (null not permitted). + * + * @return Various measurements. */ private Measurements getMeasurements(Component c) { @@ -1172,6 +1178,8 @@ public class TitledBorder extends AbstractBorder /** * Calculates the minimum size needed for displaying the border * and its title. Used by {@link TitledBorder#getMinimumSize(Component)}. + * + * @return The minimum size. */ public Dimension getMinimumSize() { diff --git a/javax/swing/event/ChangeEvent.java b/javax/swing/event/ChangeEvent.java index f75c15aac..8854282a9 100644 --- a/javax/swing/event/ChangeEvent.java +++ b/javax/swing/event/ChangeEvent.java @@ -1,5 +1,5 @@ /* ChangeEvent.java -- - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -37,23 +37,30 @@ exception statement from your version. */ package javax.swing.event; -// Imports import java.util.EventObject; /** - * ChangeEvent + * An event used to signal a state change for an object. + * + * @see ChangeListener + * @see CellEditorListener + * @see TableColumnModelListener + * * @author Andrew Selkirk * @author Ronald Veldema */ -public class ChangeEvent extends EventObject { +public class ChangeEvent + extends EventObject +{ - /** - * ChangeEvent constructor - * @param source Source object - */ - public ChangeEvent(Object source) { - super(source); - } // ChangeEvent() + /** + * Creates a new ChangeEvent instance for the specified source. + * + * @param source the source for the event (null not permitted). + */ + public ChangeEvent(Object source) + { + super(source); + } - -} // ChangeEvent +} diff --git a/javax/swing/event/ChangeListener.java b/javax/swing/event/ChangeListener.java index 1e58b1d82..75809707b 100644 --- a/javax/swing/event/ChangeListener.java +++ b/javax/swing/event/ChangeListener.java @@ -1,5 +1,5 @@ /* ChangeListener.java -- - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -37,21 +37,27 @@ exception statement from your version. */ package javax.swing.event; -// Imports import java.util.EventListener; /** - * ChangeListener interface + * A ChangeListener can register with an object to receive + * notification of state changes (for objects that support this mechanism). + * * @author Andrew Selkirk * @author Ronald Veldema */ -public interface ChangeListener extends EventListener { - - /** - * State changed - * @param event Change Event - */ - void stateChanged(ChangeEvent event); - - -} // ChangeListener +public interface ChangeListener + extends EventListener +{ + + /** + * Called by an object to notify the listener that the object's state has + * changed. The incoming event identifies the + * source of the event, allowing the listener to differentiate + * when it is listening for changes in multiple sources. + * + * @param event the change event. + */ + void stateChanged(ChangeEvent event); + +} diff --git a/javax/swing/event/TableColumnModelListener.java b/javax/swing/event/TableColumnModelListener.java index 90e1b29cc..522e0a8c6 100644 --- a/javax/swing/event/TableColumnModelListener.java +++ b/javax/swing/event/TableColumnModelListener.java @@ -1,5 +1,5 @@ /* TableColumnModelListener.java -- - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -37,44 +37,58 @@ exception statement from your version. */ package javax.swing.event; -// Imports import java.util.EventListener; +import javax.swing.table.TableColumnModel; + /** - * TableColumnModelListener public interface + * A TableColumnModelListener can register with a + * {@link TableColumnModel} to receive notification of changes to the model. + * * @author Andrew Selkirk */ -public interface TableColumnModelListener extends EventListener { - - /** - * Column added - * @param event Table Column Model Event - */ - void columnAdded(TableColumnModelEvent event); - - /** - * Column margin changed - * @param event Change Event - */ - void columnMarginChanged(ChangeEvent event); - - /** - * Column moved - * @param event Table Column Model Event - */ - void columnMoved(TableColumnModelEvent event); - - /** - * Column removed - * @param event Table Column Model Event - */ - void columnRemoved(TableColumnModelEvent event); - - /** - * Column selection changed - * @param event List Selection Event - */ - void columnSelectionChanged(ListSelectionEvent event); - - -} // TableColumnModelListener +public interface TableColumnModelListener + extends EventListener +{ + + /** + * Called by the {@link TableColumnModel} to indicate that a column has been + * added to the model. + * + * @param event information about the column addition. + */ + void columnAdded(TableColumnModelEvent event); + + /** + * Called by the {@link TableColumnModel} to indicate that the model's + * column margin has changed. + * + * @param event the event (identifies the source). + */ + void columnMarginChanged(ChangeEvent event); + + /** + * Called by the {@link TableColumnModel} to indicate that a column has been + * moved. + * + * @param event information about the column move. + */ + void columnMoved(TableColumnModelEvent event); + + /** + * Called by the {@link TableColumnModel} to indicate that a column has been + * removed from the model. + * + * @param event information about the column removal. + */ + void columnRemoved(TableColumnModelEvent event); + + /** + * Called by the {@link TableColumnModel} to indicate that the column + * selection state has changed. + * + * @param event information about the column selection state. + */ + void columnSelectionChanged(ListSelectionEvent event); + +} diff --git a/javax/swing/plaf/basic/BasicComboBoxUI.java b/javax/swing/plaf/basic/BasicComboBoxUI.java index e62432f10..557eea93f 100644 --- a/javax/swing/plaf/basic/BasicComboBoxUI.java +++ b/javax/swing/plaf/basic/BasicComboBoxUI.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import gnu.classpath.NotImplementedException; + import java.awt.Color; import java.awt.Component; import java.awt.Container; @@ -972,6 +974,7 @@ public class BasicComboBoxUI extends ComboBoxUI * by the look and feel. */ protected void installKeyboardActions() + throws NotImplementedException { // FIXME: Need to implement. } @@ -981,6 +984,7 @@ public class BasicComboBoxUI extends ComboBoxUI * installed by in {@link #installListeners}. */ protected void uninstallKeyboardActions() + throws NotImplementedException { // FIXME: Need to implement. } diff --git a/javax/swing/plaf/basic/BasicComboPopup.java b/javax/swing/plaf/basic/BasicComboPopup.java index 90b0585c4..d4eabc602 100644 --- a/javax/swing/plaf/basic/BasicComboPopup.java +++ b/javax/swing/plaf/basic/BasicComboPopup.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import gnu.classpath.NotImplementedException; + import java.awt.Color; import java.awt.Component; import java.awt.Dimension; @@ -292,6 +294,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup * This method uninstalls keyboard actions installed by the UI. */ protected void uninstallKeyboardActions() + throws NotImplementedException { // FIXME: Need to implement } @@ -559,6 +562,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup * DOCUMENT ME! */ protected void installKeyboardActions() + throws NotImplementedException { // FIXME: Need to implement } diff --git a/javax/swing/plaf/basic/BasicInternalFrameUI.java b/javax/swing/plaf/basic/BasicInternalFrameUI.java index 75aab2fe7..0a330e776 100644 --- a/javax/swing/plaf/basic/BasicInternalFrameUI.java +++ b/javax/swing/plaf/basic/BasicInternalFrameUI.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import gnu.classpath.NotImplementedException; + import java.awt.AWTEvent; import java.awt.Color; import java.awt.Component; @@ -1209,6 +1211,7 @@ public class BasicInternalFrameUI extends InternalFrameUI * This method installs the keyboard actions for the JInternalFrame. */ protected void installKeyboardActions() + throws NotImplementedException { // FIXME: Implement. } @@ -1291,6 +1294,7 @@ public class BasicInternalFrameUI extends InternalFrameUI * This method uninstalls the keyboard actions for the JInternalFrame. */ protected void uninstallKeyboardActions() + throws NotImplementedException { // FIXME: Implement. } diff --git a/javax/swing/plaf/basic/BasicLabelUI.java b/javax/swing/plaf/basic/BasicLabelUI.java index d0964f473..60e3a9868 100644 --- a/javax/swing/plaf/basic/BasicLabelUI.java +++ b/javax/swing/plaf/basic/BasicLabelUI.java @@ -37,6 +37,8 @@ package javax.swing.plaf.basic; +import gnu.classpath.NotImplementedException; + import java.awt.Color; import java.awt.Dimension; import java.awt.FontMetrics; @@ -372,6 +374,7 @@ public class BasicLabelUI extends LabelUI implements PropertyChangeListener * @param l The {@link JLabel} to install keyboard actions for. */ protected void installKeyboardActions(JLabel l) + throws NotImplementedException { //FIXME: implement. } @@ -382,6 +385,7 @@ public class BasicLabelUI extends LabelUI implements PropertyChangeListener * @param l The {@link JLabel} to uninstall keyboard actions for. */ protected void uninstallKeyboardActions(JLabel l) + throws NotImplementedException { //FIXME: implement. } diff --git a/javax/swing/plaf/basic/BasicListUI.java b/javax/swing/plaf/basic/BasicListUI.java index 6892833b2..e5dcd1c4f 100644 --- a/javax/swing/plaf/basic/BasicListUI.java +++ b/javax/swing/plaf/basic/BasicListUI.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import gnu.classpath.NotImplementedException; + import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics; @@ -1025,6 +1027,7 @@ public class BasicListUI extends ListUI * Uninstalls keyboard actions for this UI in the {@link JList}. */ protected void uninstallKeyboardActions() + throws NotImplementedException { // TODO: Implement this properly. } diff --git a/javax/swing/plaf/basic/BasicMenuBarUI.java b/javax/swing/plaf/basic/BasicMenuBarUI.java index a21514467..f258ebe30 100644 --- a/javax/swing/plaf/basic/BasicMenuBarUI.java +++ b/javax/swing/plaf/basic/BasicMenuBarUI.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import gnu.classpath.NotImplementedException; + import java.awt.Dimension; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; @@ -176,6 +178,7 @@ public class BasicMenuBarUI extends MenuBarUI * This method installs the keyboard actions for the JMenuBar. */ protected void installKeyboardActions() + throws NotImplementedException { // FIXME: implement } @@ -223,6 +226,7 @@ public class BasicMenuBarUI extends MenuBarUI * This method reverses the work done in installKeyboardActions. */ protected void uninstallKeyboardActions() + throws NotImplementedException { // FIXME: implement. } diff --git a/javax/swing/plaf/basic/BasicMenuUI.java b/javax/swing/plaf/basic/BasicMenuUI.java index 4fb250d24..f8936be5b 100644 --- a/javax/swing/plaf/basic/BasicMenuUI.java +++ b/javax/swing/plaf/basic/BasicMenuUI.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import gnu.classpath.NotImplementedException; + import java.awt.Component; import java.awt.Dimension; import java.awt.event.MouseEvent; @@ -218,6 +220,7 @@ public class BasicMenuUI extends BasicMenuItemUI * */ protected void installKeyboardActions() + throws NotImplementedException { // FIXME: Need to implement } @@ -262,6 +265,7 @@ public class BasicMenuUI extends BasicMenuItemUI * Basic look and feel's defaults. */ protected void uninstallKeyboardActions() + throws NotImplementedException { // FIXME: Need to implement } diff --git a/javax/swing/plaf/basic/BasicOptionPaneUI.java b/javax/swing/plaf/basic/BasicOptionPaneUI.java index 005a3b394..88bca3b53 100644 --- a/javax/swing/plaf/basic/BasicOptionPaneUI.java +++ b/javax/swing/plaf/basic/BasicOptionPaneUI.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import gnu.classpath.NotImplementedException; + import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; @@ -1204,6 +1206,7 @@ public class BasicOptionPaneUI extends OptionPaneUI * This method installs keyboard actions for the JOptionpane. */ protected void installKeyboardActions() + throws NotImplementedException { // FIXME: implement. } @@ -1336,6 +1339,7 @@ public class BasicOptionPaneUI extends OptionPaneUI * This method uninstalls keyboard actions for the JOptionPane. */ protected void uninstallKeyboardActions() + throws NotImplementedException { // FIXME: implement. } diff --git a/javax/swing/plaf/basic/BasicPopupMenuUI.java b/javax/swing/plaf/basic/BasicPopupMenuUI.java index 6ecd06b39..a26a5c7c4 100644 --- a/javax/swing/plaf/basic/BasicPopupMenuUI.java +++ b/javax/swing/plaf/basic/BasicPopupMenuUI.java @@ -37,6 +37,8 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import gnu.classpath.NotImplementedException; + import java.awt.Component; import java.awt.Dimension; import java.awt.event.ComponentEvent; @@ -137,6 +139,7 @@ public class BasicPopupMenuUI extends PopupMenuUI * This method installs the keyboard actions for this {@link JPopupMenu}. */ protected void installKeyboardActions() + throws NotImplementedException { // FIXME: Need to implement } @@ -179,6 +182,7 @@ public class BasicPopupMenuUI extends PopupMenuUI * Uninstalls any keyboard actions. */ protected void uninstallKeyboardActions() + throws NotImplementedException { // FIXME: Need to implement } diff --git a/javax/swing/plaf/basic/BasicScrollBarUI.java b/javax/swing/plaf/basic/BasicScrollBarUI.java index 0ab2914ea..f24485484 100644 --- a/javax/swing/plaf/basic/BasicScrollBarUI.java +++ b/javax/swing/plaf/basic/BasicScrollBarUI.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import gnu.classpath.NotImplementedException; + import java.awt.Color; import java.awt.Component; import java.awt.Container; @@ -763,6 +765,7 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, * This method installs the keyboard actions for the scrollbar. */ protected void installKeyboardActions() + throws NotImplementedException { // FIXME: implement. } @@ -1141,6 +1144,7 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, * during install. */ protected void uninstallKeyboardActions() + throws NotImplementedException { // FIXME: implement. } diff --git a/javax/swing/plaf/basic/BasicScrollPaneUI.java b/javax/swing/plaf/basic/BasicScrollPaneUI.java index 1e982008f..e6a4eaf4f 100644 --- a/javax/swing/plaf/basic/BasicScrollPaneUI.java +++ b/javax/swing/plaf/basic/BasicScrollPaneUI.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import gnu.classpath.NotImplementedException; + import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics; @@ -484,6 +486,7 @@ public class BasicScrollPaneUI extends ScrollPaneUI * @param sp the scrollpane to install keyboard actions on */ protected void installKeyboardActions(JScrollPane sp) + throws NotImplementedException { // TODO: Is this only a hook method or should we actually do something // here? If the latter, than figure out what and implement this. @@ -579,6 +582,7 @@ public class BasicScrollPaneUI extends ScrollPaneUI * @param sp the scrollpane to uninstall keyboard actions from */ protected void uninstallKeyboardActions(JScrollPane sp) + throws NotImplementedException { // TODO: Is this only a hook method or should we actually do something // here? If the latter, than figure out what and implement this. diff --git a/javax/swing/plaf/basic/BasicSliderUI.java b/javax/swing/plaf/basic/BasicSliderUI.java index 9137ae9dc..137ab55a6 100644 --- a/javax/swing/plaf/basic/BasicSliderUI.java +++ b/javax/swing/plaf/basic/BasicSliderUI.java @@ -63,7 +63,9 @@ import java.util.Dictionary; import java.util.Enumeration; import javax.swing.AbstractAction; +import javax.swing.ActionMap; import javax.swing.BoundedRangeModel; +import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JSlider; @@ -74,6 +76,7 @@ import javax.swing.UIManager; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.MouseInputAdapter; +import javax.swing.plaf.ActionMapUIResource; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.SliderUI; @@ -871,9 +874,11 @@ public class BasicSliderUI extends SliderUI * installed. */ protected void installKeyboardActions(JSlider slider) - throws NotImplementedException { - // FIXME: implement. + InputMap keyMap = getInputMap(JComponent.WHEN_FOCUSED); + SwingUtilities.replaceUIInputMap(slider, JComponent.WHEN_FOCUSED, keyMap); + ActionMap map = getActionMap(); + SwingUtilities.replaceUIActionMap(slider, map); } /** @@ -884,9 +889,9 @@ public class BasicSliderUI extends SliderUI * uninstalled. */ protected void uninstallKeyboardActions(JSlider slider) - throws NotImplementedException { - // FIXME: implement. + SwingUtilities.replaceUIActionMap(slider, null); + SwingUtilities.replaceUIInputMap(slider, JComponent.WHEN_FOCUSED, null); } /* XXX: This is all after experimentation with SUN's implementation. @@ -2073,18 +2078,22 @@ public class BasicSliderUI extends SliderUI } /** - * This method is used to move the thumb one block in the direction - * specified. If the slider snaps to ticks, this method is responsible for - * snapping it to a tick after the thumb has been moved. + * Moves the thumb one block in the direction specified (a block is 1/10th + * of the slider range). If the slider snaps to ticks, this method is + * responsible for snapping it to a tick after the thumb has been moved. * - * @param direction The direction to move in. + * @param direction the direction (positive values increment the thumb + * position by one block, zero/negative values decrement the thumb position + * by one block). */ public void scrollByBlock(int direction) { - // The direction is -1 for backwards and 1 for forwards. - int unit = direction * (slider.getMaximum() - slider.getMinimum()) / 10; - - int moveTo = slider.getValue() + unit; + int unit = (slider.getMaximum() - slider.getMinimum()) / 10; + int moveTo = slider.getValue(); + if (direction > 0) + moveTo += unit; + else + moveTo -= unit; if (slider.getSnapToTicks()) moveTo = findClosestTick(moveTo); @@ -2093,16 +2102,21 @@ public class BasicSliderUI extends SliderUI } /** - * This method is used to move the thumb one unit in the direction - * specified. If the slider snaps to ticks, this method is responsible for - * snapping it to a tick after the thumb has been moved. + * Moves the thumb one unit in the specified direction. If the slider snaps + * to ticks, this method is responsible for snapping it to a tick after the + * thumb has been moved. * - * @param direction The direction to move in. + * @param direction the direction (positive values increment the thumb + * position by one, zero/negative values decrement the thumb position by + * one). */ public void scrollByUnit(int direction) { - // The direction is -1 for backwards and 1 for forwards. - int moveTo = slider.getValue() + direction; + int moveTo = slider.getValue(); + if (direction > 0) + moveTo++; + else + moveTo--; if (slider.getSnapToTicks()) moveTo = findClosestTick(moveTo); @@ -2316,4 +2330,123 @@ public class BasicSliderUI extends SliderUI else return value + minor; } + + InputMap getInputMap(int condition) + { + if (condition == JComponent.WHEN_FOCUSED) + return (InputMap) UIManager.get("Slider.focusInputMap"); + return null; + } + + /** + * Returns the action map for the {@link JSlider}. All sliders share + * a single action map which is created the first time this method is + * called, then stored in the UIDefaults table for subsequent access. + * + * @return The shared action map. + */ + ActionMap getActionMap() + { + ActionMap map = (ActionMap) UIManager.get("Slider.actionMap"); + + if (map == null) // first time here + { + map = createActionMap(); + if (map != null) + UIManager.put("Slider.actionMap", map); + } + return map; + } + + /** + * Creates the action map shared by all {@link JSlider} instances. + * This method is called once by {@link #getActionMap()} when it + * finds no action map in the UIDefaults table...after the map is + * created, it gets added to the defaults table so that subsequent + * calls to {@link #getActionMap()} will return the same shared + * instance. + * + * @return The action map. + */ + ActionMap createActionMap() + { + ActionMap map = new ActionMapUIResource(); + map.put("positiveUnitIncrement", + new AbstractAction("positiveUnitIncrement") { + public void actionPerformed(ActionEvent event) + { + JSlider slider = (JSlider) event.getSource(); + BasicSliderUI ui = (BasicSliderUI) slider.getUI(); + if (slider.getInverted()) + ui.scrollByUnit(BasicSliderUI.NEGATIVE_SCROLL); + else + ui.scrollByUnit(BasicSliderUI.POSITIVE_SCROLL); + } + } + ); + map.put("negativeUnitIncrement", + new AbstractAction("negativeUnitIncrement") { + public void actionPerformed(ActionEvent event) + { + JSlider slider = (JSlider) event.getSource(); + BasicSliderUI ui = (BasicSliderUI) slider.getUI(); + if (slider.getInverted()) + ui.scrollByUnit(BasicSliderUI.POSITIVE_SCROLL); + else + ui.scrollByUnit(BasicSliderUI.NEGATIVE_SCROLL); + } + } + ); + map.put("positiveBlockIncrement", + new AbstractAction("positiveBlockIncrement") { + public void actionPerformed(ActionEvent event) + { + JSlider slider = (JSlider) event.getSource(); + BasicSliderUI ui = (BasicSliderUI) slider.getUI(); + if (slider.getInverted()) + ui.scrollByBlock(BasicSliderUI.NEGATIVE_SCROLL); + else + ui.scrollByBlock(BasicSliderUI.POSITIVE_SCROLL); + } + } + ); + map.put("negativeBlockIncrement", + new AbstractAction("negativeBlockIncrement") { + public void actionPerformed(ActionEvent event) + { + JSlider slider = (JSlider) event.getSource(); + BasicSliderUI ui = (BasicSliderUI) slider.getUI(); + if (slider.getInverted()) + ui.scrollByBlock(BasicSliderUI.POSITIVE_SCROLL); + else + ui.scrollByBlock(BasicSliderUI.NEGATIVE_SCROLL); + } + } + ); + map.put("minScroll", + new AbstractAction("minScroll") { + public void actionPerformed(ActionEvent event) + { + JSlider slider = (JSlider) event.getSource(); + if (slider.getInverted()) + slider.setValue(slider.getMaximum()); + else + slider.setValue(slider.getMinimum()); + } + } + ); + map.put("maxScroll", + new AbstractAction("maxScroll") { + public void actionPerformed(ActionEvent event) + { + JSlider slider = (JSlider) event.getSource(); + if (slider.getInverted()) + slider.setValue(slider.getMinimum()); + else + slider.setValue(slider.getMaximum()); + } + } + ); + return map; + } } diff --git a/javax/swing/plaf/basic/BasicSpinnerUI.java b/javax/swing/plaf/basic/BasicSpinnerUI.java index 6f7a41a1d..465374bfd 100644 --- a/javax/swing/plaf/basic/BasicSpinnerUI.java +++ b/javax/swing/plaf/basic/BasicSpinnerUI.java @@ -41,7 +41,6 @@ package javax.swing.plaf.basic; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; -import java.awt.Font; import java.awt.Insets; import java.awt.LayoutManager; import java.awt.event.ActionEvent; @@ -365,9 +364,9 @@ public class BasicSpinnerUI extends SpinnerUI private class DefaultLayoutManager implements LayoutManager { /** - * DOCUMENT ME! + * Layout the spinners inner parts. * - * @param parent DOCUMENT ME! + * @param parent The parent container */ public void layoutContainer(Container parent) { @@ -385,12 +384,12 @@ public class BasicSpinnerUI extends SpinnerUI Dimension e = prefSize(editor); Dimension n = prefSize(next); Dimension p = prefSize(previous); - Dimension s = spinner.getPreferredSize(); + Dimension s = parent.getSize(); int x = l2r ? i.left : i.right; int y = i.top; int w = Math.max(p.width, n.width); - int h = e.height / 2; + int h = (s.height - i.bottom) / 2; int e_width = s.width - w - i.left - i.right; if (l2r) diff --git a/javax/swing/plaf/basic/BasicSplitPaneUI.java b/javax/swing/plaf/basic/BasicSplitPaneUI.java index 906acfe16..694baadda 100644 --- a/javax/swing/plaf/basic/BasicSplitPaneUI.java +++ b/javax/swing/plaf/basic/BasicSplitPaneUI.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import gnu.classpath.NotImplementedException; + import java.awt.Canvas; import java.awt.Color; import java.awt.Component; @@ -1047,6 +1049,7 @@ public class BasicSplitPaneUI extends SplitPaneUI * This method installs the keyboard actions for the JSplitPane. */ protected void installKeyboardActions() + throws NotImplementedException { // FIXME: implement. } @@ -1055,6 +1058,7 @@ public class BasicSplitPaneUI extends SplitPaneUI * This method reverses the work done in installKeyboardActions. */ protected void uninstallKeyboardActions() + throws NotImplementedException { // FIXME: implement. } diff --git a/javax/swing/plaf/basic/BasicTabbedPaneUI.java b/javax/swing/plaf/basic/BasicTabbedPaneUI.java index dd27b7d2d..6d9bed331 100644 --- a/javax/swing/plaf/basic/BasicTabbedPaneUI.java +++ b/javax/swing/plaf/basic/BasicTabbedPaneUI.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import gnu.classpath.NotImplementedException; + import java.awt.Color; import java.awt.Component; import java.awt.Container; @@ -1734,6 +1736,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants * This method installs keyboard actions for the JTabbedPane. */ protected void installKeyboardActions() + throws NotImplementedException { // FIXME: Implement. } @@ -1742,6 +1745,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants * This method uninstalls keyboard actions for the JTabbedPane. */ protected void uninstallKeyboardActions() + throws NotImplementedException { // FIXME: Implement. } @@ -1950,6 +1954,8 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants return; } + int ascent = metrics.getAscent(); + int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex); if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex)) { @@ -1966,10 +1972,9 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants if (mnemIndex != -1) BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, textRect.x, - textRect.y - + metrics.getAscent()); + textRect.y + ascent); else - g.drawString(title, textRect.x, textRect.y + metrics.getAscent()); + g.drawString(title, textRect.x, textRect.y + ascent); } else { @@ -1977,17 +1982,19 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants g.setColor(bg.brighter()); if (mnemIndex != -1) BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, - textRect.x, textRect.y); + textRect.x, textRect.y + + ascent); else - g.drawString(title, textRect.x, textRect.y); + g.drawString(title, textRect.x, textRect.y + ascent); g.setColor(bg.darker()); if (mnemIndex != -1) BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, textRect.x + 1, - textRect.y + 1); + textRect.y + 1 + + ascent); else - g.drawString(title, textRect.x + 1, textRect.y + 1); + g.drawString(title, textRect.x + 1, textRect.y + 1 + ascent); } } @@ -2552,10 +2559,23 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants */ protected int lastTabInRun(int tabCount, int run) { - if (tabRuns[run] == 0) - return tabCount - 1; + int lastTab; + if (runCount == 1) + lastTab = tabCount - 1; else - return tabRuns[run] - 1; + { + int nextRun; + if (run == runCount - 1) + nextRun = 0; + else + nextRun = run + 1; + + if (tabRuns[nextRun] == 0) + lastTab = tabCount - 1; + else + lastTab = tabRuns[nextRun] - 1; + } + return lastTab; } /** diff --git a/javax/swing/plaf/basic/BasicTableHeaderUI.java b/javax/swing/plaf/basic/BasicTableHeaderUI.java index c6f9e37df..fbef6e69f 100644 --- a/javax/swing/plaf/basic/BasicTableHeaderUI.java +++ b/javax/swing/plaf/basic/BasicTableHeaderUI.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import gnu.classpath.NotImplementedException; + import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; @@ -415,6 +417,7 @@ public class BasicTableHeaderUI extends TableHeaderUI } protected void installKeyboardActions() + throws NotImplementedException { // TODO: Implement this properly. } @@ -447,6 +450,7 @@ public class BasicTableHeaderUI extends TableHeaderUI } protected void uninstallKeyboardActions() + throws NotImplementedException { // TODO: Implement this properly. } diff --git a/javax/swing/plaf/basic/BasicTableUI.java b/javax/swing/plaf/basic/BasicTableUI.java index 9ddaeb2e9..0711ce385 100644 --- a/javax/swing/plaf/basic/BasicTableUI.java +++ b/javax/swing/plaf/basic/BasicTableUI.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import gnu.classpath.NotImplementedException; + import java.awt.Color; import java.awt.Component; import java.awt.ComponentOrientation; @@ -1168,6 +1170,7 @@ public class BasicTableUI extends TableUI } protected void uninstallKeyboardActions() + throws NotImplementedException { // TODO: Implement this properly. } diff --git a/javax/swing/plaf/basic/BasicTextAreaUI.java b/javax/swing/plaf/basic/BasicTextAreaUI.java index e9f566e9a..93e119b31 100644 --- a/javax/swing/plaf/basic/BasicTextAreaUI.java +++ b/javax/swing/plaf/basic/BasicTextAreaUI.java @@ -1,5 +1,5 @@ /* BasicTextAreaUI.java -- - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -45,11 +45,9 @@ import javax.swing.JComponent; import javax.swing.JTextArea; import javax.swing.UIDefaults; import javax.swing.plaf.ComponentUI; -import javax.swing.text.Document; import javax.swing.text.Element; import javax.swing.text.PlainView; import javax.swing.text.View; -import javax.swing.text.ViewFactory; import javax.swing.text.WrappedPlainView; public class BasicTextAreaUI extends BasicTextUI diff --git a/javax/swing/plaf/basic/BasicTextFieldUI.java b/javax/swing/plaf/basic/BasicTextFieldUI.java index 4e2ca9f93..89c4e5a75 100644 --- a/javax/swing/plaf/basic/BasicTextFieldUI.java +++ b/javax/swing/plaf/basic/BasicTextFieldUI.java @@ -1,5 +1,5 @@ /* BasicTextFieldUI.java - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -42,6 +42,7 @@ import java.beans.PropertyChangeEvent; import javax.swing.JComponent; import javax.swing.UIDefaults; +import javax.swing.plaf.ColorUIResource; import javax.swing.plaf.ComponentUI; import javax.swing.text.Element; import javax.swing.text.FieldView; @@ -83,6 +84,9 @@ public class BasicTextFieldUI extends BasicTextUI * Receives notification whenever one of the text component's bound * properties changes. Here we check for the editable and enabled * properties and adjust the background color accordingly. + * + *

The colors are only changed if they are not a + * ColorUIResource.

* * @param event the property change event */ @@ -91,10 +95,11 @@ public class BasicTextFieldUI extends BasicTextUI if (event.getPropertyName().equals("editable")) { boolean editable = ((Boolean) event.getNewValue()).booleanValue(); - if (editable) - textComponent.setBackground(background); - else - textComponent.setBackground(inactiveBackground); + + // Changing the color only if the current background is an instance of + // ColorUIResource is the behavior of the RI. + if (textComponent.getBackground() instanceof ColorUIResource) + textComponent.setBackground(editable ? background : inactiveBackground); } } } diff --git a/javax/swing/plaf/basic/BasicTextUI.java b/javax/swing/plaf/basic/BasicTextUI.java index 6a45969cc..66c0da284 100644 --- a/javax/swing/plaf/basic/BasicTextUI.java +++ b/javax/swing/plaf/basic/BasicTextUI.java @@ -61,7 +61,6 @@ import javax.swing.Action; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.JComponent; -import javax.swing.KeyStroke; import javax.swing.LookAndFeel; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; @@ -69,7 +68,6 @@ import javax.swing.UIManager; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.plaf.ActionMapUIResource; -import javax.swing.plaf.InputMapUIResource; import javax.swing.plaf.TextUI; import javax.swing.plaf.UIResource; import javax.swing.text.AbstractDocument; @@ -824,6 +822,7 @@ public abstract class BasicTextUI extends TextUI * this UI. */ protected void uninstallKeyboardActions() + throws NotImplementedException { // FIXME: Uninstall keyboard actions here. } @@ -1139,9 +1138,14 @@ public abstract class BasicTextUI extends TextUI public int getNextVisualPositionFrom(JTextComponent t, int pos, Position.Bias b, int direction, Position.Bias[] biasRet) - throws BadLocationException, NotImplementedException + throws BadLocationException { - return 0; // TODO: Implement me. + // A comment in the spec of NavigationFilter.getNextVisualPositionFrom() + // suggests that this method should be implemented by forwarding the call + // the root view. + return rootView.getNextVisualPositionFrom(pos, b, + getVisibleEditorRect(), + direction, biasRet); } /** diff --git a/javax/swing/plaf/basic/BasicToolBarUI.java b/javax/swing/plaf/basic/BasicToolBarUI.java index 5d718876f..80fec6a77 100644 --- a/javax/swing/plaf/basic/BasicToolBarUI.java +++ b/javax/swing/plaf/basic/BasicToolBarUI.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import gnu.classpath.NotImplementedException; + import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; @@ -604,6 +606,7 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants * by the look and feel. */ protected void installKeyboardActions() + throws NotImplementedException { // FIXME: implement. } @@ -900,6 +903,7 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants * This method uninstalls keyboard actions installed by the UI. */ protected void uninstallKeyboardActions() + throws NotImplementedException { // FIXME: implement. } diff --git a/javax/swing/plaf/basic/BasicTreeUI.java b/javax/swing/plaf/basic/BasicTreeUI.java index 78d0a586a..fb09ac998 100644 --- a/javax/swing/plaf/basic/BasicTreeUI.java +++ b/javax/swing/plaf/basic/BasicTreeUI.java @@ -1,5 +1,5 @@ /* BasicTreeUI.java -- - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -57,6 +57,7 @@ import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; +import java.awt.event.InputEvent; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; @@ -252,25 +253,25 @@ public class BasicTreeUI int maxHeight = 0; /** Listeners */ - private PropertyChangeListener propertyChangeListener; + PropertyChangeListener propertyChangeListener; - private FocusListener focusListener; + FocusListener focusListener; - private TreeSelectionListener treeSelectionListener; + TreeSelectionListener treeSelectionListener; - private MouseListener mouseListener; + MouseListener mouseListener; - private KeyListener keyListener; + KeyListener keyListener; - private PropertyChangeListener selectionModelPropertyChangeListener; + PropertyChangeListener selectionModelPropertyChangeListener; - private ComponentListener componentListener; + ComponentListener componentListener; CellEditorListener cellEditorListener; - private TreeExpansionListener treeExpansionListener; + TreeExpansionListener treeExpansionListener; - private TreeModelListener treeModelListener; + TreeModelListener treeModelListener; /** * This timer fires the editing action after about 1200 ms if not reset during @@ -668,7 +669,8 @@ public class BasicTreeUI maxHeight = Math.max(maxHeight, iconHeight + gap); } - + + treeState.setRowHeight(maxHeight); return maxHeight; } @@ -1313,10 +1315,11 @@ public class BasicTreeUI public void installUI(JComponent c) { tree = (JTree) c; + treeModel = tree.getModel(); + prepareForUIInstall(); super.installUI(c); installDefaults(); - installComponents(); installKeyboardActions(); installListeners(); @@ -1384,25 +1387,11 @@ public class BasicTreeUI int endIndex = tree.getClosestRowForLocation(clip.x + clip.width, clip.y + clip.height); - for (int i = startIndex; i <= endIndex; i++) - { - TreePath path = treeState.getPathForRow(i); - boolean isLeaf = treeModel.isLeaf(path.getLastPathComponent()); - boolean isExpanded = tree.isExpanded(path); - - Rectangle bounds = getPathBounds(tree, path); - - paintHorizontalPartOfLeg(g, clip, insets, bounds, path, i, - isExpanded, false, isLeaf); - paintRow(g, clip, insets, bounds, path, i, isExpanded, false, - isLeaf); - if (isLastChild(path)) - paintVerticalPartOfLeg(g, clip, insets, path); - } - // Also paint dashes to the invisible nodes below: int rows = treeState.getRowCount(); + // These should be painted first, otherwise they may cover + // the control icons. if (endIndex < rows) for (int i = endIndex + 1; i < rows; i++) { @@ -1410,6 +1399,37 @@ public class BasicTreeUI if (isLastChild(path)) paintVerticalPartOfLeg(g, clip, insets, path); } + + // The two loops are required to ensure that the lines are not + // painted over the other tree components. + + int n = endIndex - startIndex + 1; + Rectangle[] bounds = new Rectangle[n]; + boolean[] isLeaf = new boolean[n]; + boolean[] isExpanded = new boolean[n]; + TreePath[] path = new TreePath[n]; + int k; + + k = 0; + for (int i = startIndex; i <= endIndex; i++, k++) + { + path[k] = treeState.getPathForRow(i); + isLeaf[k] = treeModel.isLeaf(path[k].getLastPathComponent()); + isExpanded[k] = tree.isExpanded(path[k]); + bounds[k] = getPathBounds(tree, path[k]); + + paintHorizontalPartOfLeg(g, clip, insets, bounds[k], path[k], i, + isExpanded[k], false, isLeaf[k]); + if (isLastChild(path[k])) + paintVerticalPartOfLeg(g, clip, insets, path[k]); + } + + k = 0; + for (int i = startIndex; i <= endIndex; i++, k++) + { + paintRow(g, clip, insets, bounds[k], path[k], i, isExpanded[k], + false, isLeaf[k]); + } } } @@ -1508,8 +1528,9 @@ public class BasicTreeUI { if (! validCachedPreferredSize) { + Rectangle size = tree.getBounds(); // Add the scrollbar dimensions to the preferred size. - preferredSize = new Dimension(treeState.getPreferredWidth(null), + preferredSize = new Dimension(treeState.getPreferredWidth(size), treeState.getPreferredHeight()); validCachedPreferredSize = true; } @@ -1598,12 +1619,6 @@ public class BasicTreeUI */ protected boolean startEditing(TreePath path, MouseEvent event) { - // Force to recalculate the maximal row height. - maxHeight = 0; - - // Force to recalculate the cached preferred size. - validCachedPreferredSize = false; - updateCellEditor(); TreeCellEditor ed = getCellEditor(); @@ -1720,7 +1735,10 @@ public class BasicTreeUI /** * Returning true signifies a mouse event on the node should toggle the - * selection of only the row under the mouse. + * selection of only the row under the mouse. The BasisTreeUI treats the + * event as "toggle selection event" if the CTRL button was pressed while + * clicking. The event is not counted as toggle event if the associated + * tree does not support the multiple selection. * * @param event is the MouseEvent performed on the row. * @return true signifies a mouse event on the node should toggle the @@ -1728,12 +1746,18 @@ public class BasicTreeUI */ protected boolean isToggleSelectionEvent(MouseEvent event) { - return (tree.getSelectionModel().getSelectionMode() == TreeSelectionModel.SINGLE_TREE_SELECTION); + return + (tree.getSelectionModel().getSelectionMode() != + TreeSelectionModel.SINGLE_TREE_SELECTION) && + ((event.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0); } /** * Returning true signifies a mouse event on the node should select from the - * anchor point. + * anchor point. The BasisTreeUI treats the event as "multiple selection + * event" if the SHIFT button was pressed while clicking. The event is not + * counted as multiple selection event if the associated tree does not support + * the multiple selection. * * @param event is the MouseEvent performed on the node. * @return true signifies a mouse event on the node should select from the @@ -1741,7 +1765,10 @@ public class BasicTreeUI */ protected boolean isMultiSelectEvent(MouseEvent event) { - return (tree.getSelectionModel().getSelectionMode() == TreeSelectionModel.CONTIGUOUS_TREE_SELECTION); + return + (tree.getSelectionModel().getSelectionMode() != + TreeSelectionModel.SINGLE_TREE_SELECTION) && + ((event.getModifiersEx() & InputEvent.SHIFT_DOWN_MASK) != 0); } /** @@ -1763,15 +1790,19 @@ public class BasicTreeUI * row. If the even is a toggle selection event, the row is either selected, * or deselected. If the event identifies a multi selection event, the * selection is updated from the anchor point. Otherwise, the row is selected, - * and if the even specified a toggle event the row is expanded/collapsed. + * and the previous selection is cleared.

* * @param path is the path selected for an event * @param event is the MouseEvent performed on the path. + * + * @see #isToggleSelectionEvent(MouseEvent) + * @see #isMultiSelectEvent(MouseEvent) */ protected void selectPathForEvent(TreePath path, MouseEvent event) { if (isToggleSelectionEvent(event)) { + // The event selects or unselects the clicked row. if (tree.isPathSelected(path)) tree.removeSelectionPath(path); else @@ -1782,6 +1813,7 @@ public class BasicTreeUI } else if (isMultiSelectEvent(event)) { + // The event extends selection form anchor till the clicked row. TreePath anchor = tree.getAnchorSelectionPath(); if (anchor != null) { @@ -1792,7 +1824,11 @@ public class BasicTreeUI tree.addSelectionPath(path); } else - tree.addSelectionPath(path); + { + // This is an ordinary event that just selects the clicked row. + tree.setSelectionPath(path); + tree.setAnchorSelectionPath(path); + } } /** @@ -1865,7 +1901,7 @@ public class BasicTreeUI if (tree.isEditing() && ! command.equals("startEditing")) tree.stopEditing(); - tree.scrollPathToVisible(lead); + tree.scrollPathToVisible(tree.getLeadSelectionPath()); } } @@ -2017,24 +2053,38 @@ public class BasicTreeUI /** * Invoked when focus is activated on the tree we're in, redraws the lead - * row. Invoked when a component gains the keyboard focus. + * row. Invoked when a component gains the keyboard focus. The method + * repaints the lead row that is shown differently when the tree is in + * focus. * * @param e is the focus event that is activated */ public void focusGained(FocusEvent e) { - // TODO: Implement this properly. + repaintLeadRow(); } /** * Invoked when focus is deactivated on the tree we're in, redraws the lead - * row. Invoked when a component loses the keyboard focus. + * row. Invoked when a component loses the keyboard focus. The method + * repaints the lead row that is shown differently when the tree is in + * focus. * * @param e is the focus event that is deactivated */ public void focusLost(FocusEvent e) { - // TODO: Implement this properly. + repaintLeadRow(); + } + + /** + * Repaint the lead row. + */ + void repaintLeadRow() + { + TreePath lead = tree.getLeadSelectionPath(); + if (lead!=null) + tree.repaint(tree.getPathBounds(lead)); } } @@ -2131,6 +2181,11 @@ public class BasicTreeUI { Rectangle bounds = getPathBounds(tree, path); int row = getRowForPath(tree, path); + + // Cancel the editing session if clicked on the different row. + if (tree.isEditing() && row != editingRow) + cancelEditing(tree); + boolean cntlClick = isLocationInExpandControl(path, click.x, click.y); boolean isLeaf = isLeaf(row); @@ -2171,23 +2226,22 @@ public class BasicTreeUI startEditTimer.stop(); startEditTimer = new Timer(WAIT_TILL_EDITING, - new ActionListener() - { - public void actionPerformed( - ActionEvent e) - { - startEditing(editPath, - EDIT); - } - }); + new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + startEditing(editPath, EDIT); + } + }); startEditTimer.setRepeats(false); startEditTimer.start(); } else { - selectPath(tree, path); if (e.getClickCount() == 2 && ! isLeaf(row)) toggleExpandState(path); + else + selectPathForEvent(path, e); } } @@ -2410,12 +2464,13 @@ public class BasicTreeUI */ protected int getRowX(int row, int depth) { - return depth * rightChildIndent; + int iw = getCurrentControlIcon(null).getIconWidth(); + return depth * (rightChildIndent + iw/2); } }// NodeDimensionsHandler /** - * PropertyChangeListener for the tree. Updates the appropriate varaible, or + * PropertyChangeListener for the tree. Updates the appropriate variable, or * TreeState, based on what changes. */ public class PropertyChangeHandler @@ -2438,12 +2493,23 @@ public class BasicTreeUI */ public void propertyChange(PropertyChangeEvent event) { - if ((event.getPropertyName()).equals("rootVisible")) + String property = event.getPropertyName(); + if (property.equals(JTree.ROOT_VISIBLE_PROPERTY)) { validCachedPreferredSize = false; treeState.setRootVisible(tree.isRootVisible()); tree.repaint(); } + else if (property.equals(JTree.SELECTION_MODEL_PROPERTY)) + { + treeSelectionModel = tree.getSelectionModel(); + treeSelectionModel.setRowMapper(treeState); + } + else if (property.equals(JTree.TREE_MODEL_PROPERTY)) + { + treeModel = tree.getModel(); + treeModel.addTreeModelListener(treeModelListener); + } } } @@ -2536,6 +2602,8 @@ public class BasicTreeUI { validCachedPreferredSize = false; treeState.setExpandedState(event.getPath(), true); + tree.revalidate(); + tree.repaint(); } /** @@ -2547,6 +2615,8 @@ public class BasicTreeUI { validCachedPreferredSize = false; treeState.setExpandedState(event.getPath(), false); + tree.revalidate(); + tree.repaint(); } }// TreeExpansionHandler @@ -2643,35 +2713,54 @@ public class BasicTreeUI if (command.equals("selectPreviousChangeLead") && hasPrev) { newPath = treeState.getPathForRow(prevRow); - selectPath(tree, newPath); + tree.setSelectionPath(newPath); + tree.setAnchorSelectionPath(newPath); tree.setLeadSelectionPath(newPath); } else if (command.equals("selectPreviousExtendSelection") && hasPrev) { newPath = treeState.getPathForRow(prevRow); + + // If the new path is already selected, the selection shrinks, + // unselecting the previously current path. + if (tree.isPathSelected(newPath)) + tree.getSelectionModel().removeSelectionPath(currentPath); + + // This must be called in any case because it updates the model + // lead selection index. tree.addSelectionPath(newPath); tree.setLeadSelectionPath(newPath); } else if (command.equals("selectPrevious") && hasPrev) { newPath = treeState.getPathForRow(prevRow); - selectPath(tree, newPath); + tree.setSelectionPath(newPath); } else if (command.equals("selectNext") && hasNext) { newPath = treeState.getPathForRow(nextRow); - selectPath(tree, newPath); + tree.setSelectionPath(newPath); } else if (command.equals("selectNextExtendSelection") && hasNext) { newPath = treeState.getPathForRow(nextRow); + + // If the new path is already selected, the selection shrinks, + // unselecting the previously current path. + if (tree.isPathSelected(newPath)) + tree.getSelectionModel().removeSelectionPath(currentPath); + + // This must be called in any case because it updates the model + // lead selection index. tree.addSelectionPath(newPath); + tree.setLeadSelectionPath(newPath); } else if (command.equals("selectNextChangeLead") && hasNext) { newPath = treeState.getPathForRow(nextRow); - selectPath(tree, newPath); + tree.setSelectionPath(newPath); + tree.setAnchorSelectionPath(newPath); tree.setLeadSelectionPath(newPath); } } @@ -2837,7 +2926,24 @@ public class BasicTreeUI public void valueChanged(TreeSelectionEvent event) { if (tree.isEditing()) - tree.stopEditing(); + tree.cancelEditing(); + + TreePath op = event.getOldLeadSelectionPath(); + TreePath np = event.getNewLeadSelectionPath(); + + // Repaint of the changed lead selection path. + if (op != np) + { + Rectangle o = treeState.getBounds(event.getOldLeadSelectionPath(), + new Rectangle()); + Rectangle n = treeState.getBounds(event.getNewLeadSelectionPath(), + new Rectangle()); + + if (o!=null) + tree.repaint(o); + if (n!=null) + tree.repaint(n); + } } }// TreeSelectionHandler @@ -2913,16 +3019,41 @@ public class BasicTreeUI return; if (e.getActionCommand().equals("selectParent")) - selectPath(tree, current.getParentPath()); + { + if (current == null) + return; + + if (tree.isExpanded(current)) + { + tree.collapsePath(current); + } + else + { + // If the node is not expanded (also, if it is a leaf node), + // we just select the parent. We do not select the root if it + // is not visible. + TreePath parent = current.getParentPath(); + if (parent != null && + !(parent.getPathCount()==1 && !tree.isRootVisible()) ) + tree.setSelectionPath(parent); + } + } else if (e.getActionCommand().equals("selectChild")) { Object node = current.getLastPathComponent(); int nc = treeModel.getChildCount(node); - if (nc > 0) - node = treeModel.getChild(node, 0); - - TreePath path = current.pathByAddingChild(node); - selectPath(tree, path); + if (nc == 0 || treeState.isExpanded(current)) + { + // If the node is leaf or it is already expanded, + // we just select the next row. + int nextRow = tree.getLeadSelectionRow() + 1; + if (nextRow <= tree.getRowCount()) + tree.setSelectionRow(nextRow); + } + else + { + tree.expandPath(current); + } } } @@ -3018,23 +3149,9 @@ public class BasicTreeUI { if (path != null) { - if (tree.getSelectionModel().getSelectionMode() == TreeSelectionModel.SINGLE_TREE_SELECTION) - { - tree.getSelectionModel().clearSelection(); - tree.addSelectionPath(path); - tree.setLeadSelectionPath(path); - } - else if (tree.getSelectionModel().getSelectionMode() == TreeSelectionModel.CONTIGUOUS_TREE_SELECTION) - { - // TODO - } - else - { - tree.addSelectionPath(path); - tree.setLeadSelectionPath(path); - tree.getSelectionModel().setSelectionMode( - TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); - } + tree.setSelectionPath(path); + tree.setLeadSelectionPath(path); + tree.makeVisible(path); tree.scrollPathToVisible(path); } } @@ -3172,9 +3289,7 @@ public class BasicTreeUI { Icon icon = getCurrentControlIcon(path); int iconW = icon.getIconWidth(); - int x = bounds.x - rightChildIndent + iconW / 2; - if (x + iconW > bounds.x) - x = bounds.x - rightChildIndent - gap; + int x = bounds.x - iconW - gap; icon.paintIcon(tree, g, x, bounds.y + bounds.height / 2 - icon.getIconHeight() / 2); } @@ -3203,8 +3318,12 @@ public class BasicTreeUI boolean isLeaf) { if (row != 0) - paintHorizontalLine(g, tree, bounds.y + bounds.height / 2, bounds.x - gap - - 2, bounds.x); + { + Icon icon = getCurrentControlIcon(path); + int iconW = icon.getIconWidth(); + paintHorizontalLine(g, tree, bounds.y + bounds.height / 2, + bounds.x - iconW/2 - gap, bounds.x - gap); + } } /** @@ -3224,7 +3343,7 @@ public class BasicTreeUI if (parent != null) { Rectangle parentBounds = getPathBounds(tree, parent); - paintVerticalLine(g, tree, parentBounds.x + gap + 2, + paintVerticalLine(g, tree, parentBounds.x + 2* gap, parentBounds.y + parentBounds.height / 2, bounds.y + bounds.height / 2); } @@ -3260,9 +3379,15 @@ public class BasicTreeUI if (dtcr == null) dtcr = createDefaultCellRenderer(); + boolean focused = false; + if (treeSelectionModel!= null) + focused = treeSelectionModel.getLeadSelectionRow() == row + && tree.isFocusOwner(); + Component c = dtcr.getTreeCellRendererComponent(tree, node, selected, isExpanded, isLeaf, row, - tree.hasFocus()); + focused); + rendererPane.paintComponent(g, c, c.getParent(), bounds); } @@ -3298,15 +3423,17 @@ public class BasicTreeUI */ void finish() { + treeState.invalidatePathBounds(treeState.getPathForRow(editingRow)); editingPath = null; editingRow = - 1; stopEditingInCompleteEditing = false; isEditing = false; + Rectangle bounds = editingComponent.getParent().getBounds(); tree.removeAll(); validCachedPreferredSize = false; - // Repaint the region, where was the editing component. - tree.repaint(editingComponent.getParent().getBounds()); + tree.repaint(bounds); editingComponent = null; + tree.requestFocus(); } } // BasicTreeUI diff --git a/javax/swing/table/DefaultTableCellRenderer.java b/javax/swing/table/DefaultTableCellRenderer.java index 0d9b62567..f56fd4f0e 100644 --- a/javax/swing/table/DefaultTableCellRenderer.java +++ b/javax/swing/table/DefaultTableCellRenderer.java @@ -1,5 +1,5 @@ /* DefaultTableCellRenderer.java -- - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -49,7 +49,6 @@ import javax.swing.JTable; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; -import javax.swing.JTextField; /** * Class to display every cells. diff --git a/javax/swing/table/DefaultTableColumnModel.java b/javax/swing/table/DefaultTableColumnModel.java index cd04a6979..6ed6331c2 100644 --- a/javax/swing/table/DefaultTableColumnModel.java +++ b/javax/swing/table/DefaultTableColumnModel.java @@ -1,5 +1,5 @@ /* DefaultTableColumnModel.java -- - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -46,6 +46,7 @@ import java.util.EventListener; import java.util.Vector; import javax.swing.DefaultListSelectionModel; +import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.event.ChangeEvent; import javax.swing.event.EventListenerList; @@ -55,9 +56,11 @@ import javax.swing.event.TableColumnModelEvent; import javax.swing.event.TableColumnModelListener; /** - * DefaultTableColumnModel + * A model that stores information about the columns used in a {@link JTable}. + * + * @see JTable#setColumnModel(TableColumnModel) + * * @author Andrew Selkirk - * @version 1.0 */ public class DefaultTableColumnModel implements TableColumnModel, PropertyChangeListener, ListSelectionListener, @@ -66,88 +69,116 @@ public class DefaultTableColumnModel private static final long serialVersionUID = 6580012493508960512L; /** - * Columns that this model keeps track of. + * Storage for the table columns. */ protected Vector tableColumns; /** - * Selection Model that keeps track of columns selection + * A selection model that keeps track of column selections. */ protected ListSelectionModel selectionModel; /** - * Space between two columns. By default it is set to 1 + * The space between the columns (the default value is 1). */ protected int columnMargin; /** - * listenerList keeps track of all listeners registered with this model + * Storage for the listeners registered with the model. */ protected EventListenerList listenerList = new EventListenerList(); /** - * changeEvent is fired when change occurs in one of the columns properties + * A change event used when notifying listeners of a change to the + * columnMargin field. This single event is reused for all + * notifications. */ + // FIXME: use lazy instantiation protected transient ChangeEvent changeEvent = new ChangeEvent(this); /** - * Indicates whether columns can be selected + * A flag that indicates whether or not columns can be selected. */ protected boolean columnSelectionAllowed; /** - * Total width of all the columns in this model + * The total width of all the columns in this model. */ protected int totalColumnWidth; /** - * Constructor DefaultTableColumnModel + * Creates a new table column model with zero columns. A default column + * selection model is created by calling {@link #createSelectionModel()}. + * The default value for columnMargin is 1 and + * the default value for columnSelectionAllowed is + * false. */ public DefaultTableColumnModel() { tableColumns = new Vector(); - setSelectionModel(createSelectionModel()); + selectionModel = createSelectionModel(); + selectionModel.addListSelectionListener(this); columnMargin = 1; columnSelectionAllowed = false; } /** - * addColumn adds column to the model. This method fires ColumnAdded - * event to model's registered TableColumnModelListeners. + * Adds a column to the model then calls + * {@link #fireColumnAdded(TableColumnModelEvent)} to notify the registered + * listeners. The model registers itself with the column as a + * {@link PropertyChangeListener} so that changes to the column width will + * invalidate the cached {@link #totalColumnWidth} value. * - * @param col column to add + * @param column the column (null not permitted). + * + * @throws IllegalArgumentException if column is + * null. + * + * @see #removeColumn(TableColumn) */ - public void addColumn(TableColumn col) + public void addColumn(TableColumn column) { - if (col == null) + if (column == null) throw new IllegalArgumentException("Null 'col' argument."); - tableColumns.add(col); + tableColumns.add(column); + column.addPropertyChangeListener(this); invalidateWidthCache(); - fireColumnAdded(new TableColumnModelEvent(this, 0, tableColumns.size() - 1)); + fireColumnAdded(new TableColumnModelEvent(this, 0, + tableColumns.size() - 1)); } /** - * removeColumn removes table column from the model. This method fires - * ColumnRemoved event to model's registered TableColumnModelListeners. + * Removes a column from the model then calls + * {@link #fireColumnRemoved(TableColumnModelEvent)} to notify the registered + * listeners. If the specified column does not belong to the model, or is + * null, this method does nothing. * - * @param col column to be removed + * @param column the column to be removed (null permitted). + * + * @see #addColumn(TableColumn) */ - public void removeColumn(TableColumn col) + public void removeColumn(TableColumn column) { - int index = this.tableColumns.indexOf(col); + int index = this.tableColumns.indexOf(column); if (index < 0) return; + tableColumns.remove(column); fireColumnRemoved(new TableColumnModelEvent(this, index, 0)); - tableColumns.remove(col); + column.removePropertyChangeListener(this); invalidateWidthCache(); } /** - * moveColumn moves column at index i to index j. This method fires - * ColumnMoved event to model's registered TableColumnModelListeners. + * Moves the column at index i to the position specified by index j, then + * calls {@link #fireColumnMoved(TableColumnModelEvent)} to notify registered + * listeners. * - * @param i index of the column that will be moved - * @param j index of column's new location + * @param i index of the column that will be moved. + * @param j index of the column's new location. + * + * @throws IllegalArgumentException if i or j are + * outside the range 0 to N-1, where + * N is the column count. */ public void moveColumn(int i, int j) { @@ -158,22 +189,27 @@ public class DefaultTableColumnModel throw new IllegalArgumentException("Index 'j' out of range."); TableColumn column = tableColumns.remove(i); tableColumns.add(j, column); - fireColumnAdded(new TableColumnModelEvent(this, i, j)); + fireColumnMoved(new TableColumnModelEvent(this, i, j)); } /** - * setColumnMargin sets margin of the columns. - * @param m new column margin + * Sets the column margin then calls {@link #fireColumnMarginChanged()} to + * notify the registered listeners. + * + * @param margin the column margin. + * + * @see #getColumnMargin() */ - public void setColumnMargin(int m) + public void setColumnMargin(int margin) { - columnMargin = m; + columnMargin = margin; fireColumnMarginChanged(); } /** - * getColumnCount returns number of columns in the model - * @return int number of columns in the model + * Returns the number of columns in the model. + * + * @return The column count. */ public int getColumnCount() { @@ -181,8 +217,9 @@ public class DefaultTableColumnModel } /** - * getColumns - * @return Enumeration + * Returns an enumeration of the columns in the model. + * + * @return An enumeration of the columns in the model. */ public Enumeration getColumns() { @@ -214,18 +251,28 @@ public class DefaultTableColumnModel } /** - * getColumn returns column at the specified index - * @param i index of the column - * @return TableColumn column at the specified index + * Returns the column at the specified index. + * + * @param columnIndex the column index (in the range from 0 to + * N-1, where N is the number of columns in + * the model). + * + * @return The column at the specified index. + * + * @throws ArrayIndexOutOfBoundsException if i is not within + * the specified range. */ - public TableColumn getColumn(int i) + public TableColumn getColumn(int columnIndex) { - return (TableColumn) tableColumns.get(i); + return (TableColumn) tableColumns.get(columnIndex); } /** - * getColumnMargin returns column margin - * @return int column margin + * Returns the column margin. + * + * @return The column margin. + * + * @see #setColumnMargin(int) */ public int getColumnMargin() { @@ -233,16 +280,26 @@ public class DefaultTableColumnModel } /** - * getColumnIndexAtX returns column that contains specified x-coordinate. - * @param x x-coordinate that column should contain - * @return int index of the column that contains specified x-coordinate relative - * to this column model + * Returns the index of the column that contains the specified x-coordinate. + * This method assumes that: + *
    + *
  • column zero begins at position zero;
  • + *
  • all columns appear in order;
  • + *
  • individual column widths are taken into account, but the column margin + * is ignored.
  • + *
+ * If no column contains the specified position, this method returns + * -1. + * + * @param x the x-position. + * + * @return The column index, or -1. */ public int getColumnIndexAtX(int x) { for (int i = 0; i < tableColumns.size(); ++i) { - int w = ((TableColumn)tableColumns.get(i)).getWidth(); + int w = ((TableColumn) tableColumns.get(i)).getWidth(); if (0 <= x && x < w) return i; else @@ -252,10 +309,10 @@ public class DefaultTableColumnModel } /** - * getTotalColumnWidth returns total width of all the columns including - * column's margins. + * Returns total width of all the columns in the model, ignoring the + * {@link #columnMargin}. * - * @return total width of all the columns + * @return The total width of all the columns. */ public int getTotalColumnWidth() { @@ -265,24 +322,32 @@ public class DefaultTableColumnModel } /** - * setSelectionModel sets selection model that will be used by this ColumnTableModel - * to keep track of currently selected columns + * Sets the selection model that will be used to keep track of the selected + * columns. * - * @param model new selection model - * @exception IllegalArgumentException if model is null + * @param model the selection model (null not permitted). + * + * @throws IllegalArgumentException if model is + * null. + * + * @see #getSelectionModel() */ public void setSelectionModel(ListSelectionModel model) { if (model == null) throw new IllegalArgumentException(); + selectionModel.removeListSelectionListener(this); selectionModel = model; selectionModel.addListSelectionListener(this); } /** - * getSelectionModel returns selection model - * @return ListSelectionModel selection model + * Returns the selection model used to track table column selections. + * + * @return The selection model. + * + * @see #setSelectionModel(ListSelectionModel) */ public ListSelectionModel getSelectionModel() { @@ -290,10 +355,11 @@ public class DefaultTableColumnModel } /** - * setColumnSelectionAllowed sets whether column selection is allowed - * or not. + * Sets the flag that indicates whether or not column selection is allowed. * - * @param flag true if column selection is allowed and false otherwise + * @param flag the new flag value. + * + * @see #getColumnSelectionAllowed() */ public void setColumnSelectionAllowed(boolean flag) { @@ -301,10 +367,12 @@ public class DefaultTableColumnModel } /** - * getColumnSelectionAllowed indicates whether column selection is - * allowed or not. + * Returns true if column selection is allowed, and + * false if column selection is not allowed. * - * @return boolean true if column selection is allowed and false otherwise. + * @return A boolean. + * + * @see #setColumnSelectionAllowed(boolean) */ public boolean getColumnSelectionAllowed() { @@ -312,10 +380,9 @@ public class DefaultTableColumnModel } /** - * getSelectedColumns returns array containing indexes of currently - * selected columns + * Returns an array containing the indices of the selected columns. * - * @return int[] array containing indexes of currently selected columns + * @return An array containing the indices of the selected columns. */ public int[] getSelectedColumns() { @@ -356,8 +423,11 @@ public class DefaultTableColumnModel } /** - * getSelectedColumnCount returns number of currently selected columns - * @return int number of currently selected columns + * Returns the number of selected columns in the model. + * + * @return The selected column count. + * + * @see #getSelectionModel() */ public int getSelectedColumnCount() { @@ -395,10 +465,10 @@ public class DefaultTableColumnModel } /** - * addColumnModelListener adds specified listener to the model's - * listener list + * Registers a listener with the model, so that it will receive + * {@link TableColumnModelEvent} notifications. * - * @param listener the listener to add + * @param listener the listener (null ignored). */ public void addColumnModelListener(TableColumnModelListener listener) { @@ -406,10 +476,10 @@ public class DefaultTableColumnModel } /** - * removeColumnModelListener removes specified listener from the model's - * listener list. + * Deregisters a listener so that it no longer receives notification of + * changes to this model. * - * @param listener the listener to remove + * @param listener the listener to remove */ public void removeColumnModelListener(TableColumnModelListener listener) { @@ -417,6 +487,13 @@ public class DefaultTableColumnModel } /** + * Returns an array containing the listeners that are registered with the + * model. If there are no listeners, an empty array is returned. + * + * @return An array containing the listeners that are registered with the + * model. + * + * @see #addColumnModelListener(TableColumnModelListener) * @since 1.4 */ public TableColumnModelListener[] getColumnModelListeners() @@ -426,78 +503,97 @@ public class DefaultTableColumnModel } /** - * fireColumnAdded fires TableColumnModelEvent to registered - * TableColumnModelListeners to indicate that column was added - * - * @param e TableColumnModelEvent + * Sends the specified {@link TableColumnModelEvent} to all registered + * listeners, to indicate that a column has been added to the model. The + * event's toIndex attribute should contain the index of the + * added column. + * + * @param e the event. + * + * @see #addColumn(TableColumn) */ protected void fireColumnAdded(TableColumnModelEvent e) { TableColumnModelListener[] listeners = getColumnModelListeners(); - for (int i=0; i< listeners.length; i++) + for (int i = 0; i < listeners.length; i++) listeners[i].columnAdded(e); } /** - * fireColumnAdded fires TableColumnModelEvent to registered - * TableColumnModelListeners to indicate that column was removed - * - * @param e TableColumnModelEvent + * Sends the specified {@link TableColumnModelEvent} to all registered + * listeners, to indicate that a column has been removed from the model. The + * event's fromIndex attribute should contain the index of the + * removed column. + * + * @param e the event. + * + * @see #removeColumn(TableColumn) */ protected void fireColumnRemoved(TableColumnModelEvent e) { TableColumnModelListener[] listeners = getColumnModelListeners(); - for (int i=0; i< listeners.length; i++) + for (int i = 0; i < listeners.length; i++) listeners[i].columnRemoved(e); } /** - * fireColumnAdded fires TableColumnModelEvent to registered - * TableColumnModelListeners to indicate that column was moved - * - * @param e TableColumnModelEvent + * Sends the specified {@link TableColumnModelEvent} to all registered + * listeners, to indicate that a column in the model has been moved. The + * event's fromIndex attribute should contain the old column + * index, and the toIndex attribute should contain the new + * column index. + * + * @param e the event. + * + * @see #moveColumn(int, int) */ protected void fireColumnMoved(TableColumnModelEvent e) { TableColumnModelListener[] listeners = getColumnModelListeners(); - for (int i=0; i< listeners.length; i++) + for (int i = 0; i < listeners.length; i++) listeners[i].columnMoved(e); } /** - * fireColumnSelectionChanged fires TableColumnModelEvent to model's - * registered TableColumnModelListeners to indicate that different column - * was selected. + * Sends the specified {@link ListSelectionEvent} to all registered listeners, + * to indicate that the column selections have changed. * - * @param evt ListSelectionEvent + * @param e the event. + * + * @see #valueChanged(ListSelectionEvent) */ - protected void fireColumnSelectionChanged(ListSelectionEvent evt) + protected void fireColumnSelectionChanged(ListSelectionEvent e) { EventListener [] listeners = getListeners(TableColumnModelListener.class); for (int i = 0; i < listeners.length; ++i) - ((TableColumnModelListener)listeners[i]).columnSelectionChanged(evt); + ((TableColumnModelListener) listeners[i]).columnSelectionChanged(e); } /** - * fireColumnMarginChanged fires TableColumnModelEvent to model's - * registered TableColumnModelListeners to indicate that column margin - * was changed. + * Sends a {@link ChangeEvent} to the model's registered listeners to + * indicate that the column margin was changed. + * + * @see #setColumnMargin(int) */ protected void fireColumnMarginChanged() { EventListener [] listeners = getListeners(TableColumnModelListener.class); for (int i = 0; i < listeners.length; ++i) - ((TableColumnModelListener)listeners[i]).columnMarginChanged(changeEvent); + ((TableColumnModelListener) listeners[i]).columnMarginChanged(changeEvent); } /** - * getListeners returns currently registered listeners with this model. - * @param listenerType type of listeners to return + * Returns an array containing the listeners (of the specified type) that + * are registered with this model. + * + * @param listenerType the listener type (must indicate a subclass of + * {@link EventListener}, null not permitted). * - * @return EventListener[] array of model's listeners of the specified type + * @return An array containing the listeners (of the specified type) that + * are registered with this model. */ public T[] getListeners(Class listenerType) { @@ -505,20 +601,26 @@ public class DefaultTableColumnModel } /** - * propertyChange handles changes occuring in the properties of the - * model's columns. + * Receives notification of property changes for the columns in the model. + * If the width property for any column changes, we invalidate + * the {@link #totalColumnWidth} value here. * - * @param evt PropertyChangeEvent + * @param event the event. */ - public void propertyChange(PropertyChangeEvent evt) + public void propertyChange(PropertyChangeEvent event) { - if (evt.getPropertyName().equals(TableColumn.COLUMN_WIDTH_PROPERTY)) - invalidateWidthCache(); + if (event.getPropertyName().equals("width")) + invalidateWidthCache(); } /** - * valueChanged handles changes in the selectionModel. - * @param e ListSelectionEvent + * Receives notification of the change to the list selection model, and + * responds by calling + * {@link #fireColumnSelectionChanged(ListSelectionEvent)}. + * + * @param e the list selection event. + * + * @see #getSelectionModel() */ public void valueChanged(ListSelectionEvent e) { @@ -526,10 +628,11 @@ public class DefaultTableColumnModel } /** - * createSelectionModel creates selection model that will keep track - * of currently selected column(s) + * Creates a default selection model to track the currently selected + * column(s). This method is called by the constructor and returns a new + * instance of {@link DefaultListSelectionModel}. * - * @return ListSelectionModel selection model of the columns + * @return A new default column selection model. */ protected ListSelectionModel createSelectionModel() { @@ -537,9 +640,10 @@ public class DefaultTableColumnModel } /** - * recalcWidthCache calculates total width of the columns. - * If the current cache of the total width is in invalidated state, - * then width is recalculated. Otherwise nothing is done. + * Recalculates the total width of the columns, if the cached value is + * -1. Otherwise this method does nothing. + * + * @see #getTotalColumnWidth() */ protected void recalcWidthCache() { @@ -548,13 +652,15 @@ public class DefaultTableColumnModel totalColumnWidth = 0; for (int i = 0; i < tableColumns.size(); ++i) { - totalColumnWidth += ((TableColumn)tableColumns.get(i)).getWidth(); + totalColumnWidth += ((TableColumn) tableColumns.get(i)).getWidth(); } } } /** - * invalidateWidthCache + * Sets the {@link #totalColumnWidth} field to -1. + * + * @see #recalcWidthCache() */ private void invalidateWidthCache() { diff --git a/javax/swing/table/TableColumnModel.java b/javax/swing/table/TableColumnModel.java index 66f52e619..7e8a70c3a 100644 --- a/javax/swing/table/TableColumnModel.java +++ b/javax/swing/table/TableColumnModel.java @@ -1,5 +1,5 @@ /* TableColumnModel.java -- - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -42,6 +42,8 @@ import java.util.Enumeration; import javax.swing.JTable; import javax.swing.ListSelectionModel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.TableColumnModelEvent; import javax.swing.event.TableColumnModelListener; /** @@ -50,7 +52,6 @@ import javax.swing.event.TableColumnModelListener; * * @author Andrew Selkirk */ -// FIXME: The API documentation in this class is incomplete. public interface TableColumnModel { /** @@ -80,21 +81,26 @@ public interface TableColumnModel void moveColumn(int columnIndex, int newIndex); /** - * setColumnMargin - * @param margin Margin of column + * Sets the column margin and sends a {@link ChangeEvent} to all registered + * {@link TableColumnModelListener}s registered with the model. + * + * @param margin the column margin. + * + * @see #getColumnMargin() */ void setColumnMargin(int margin); /** * Returns the number of columns in the model. * - * @return The column count + * @return The column count. */ int getColumnCount(); /** - * getColumns - * @return Enumeration of columns + * Returns an enumeration of the columns in the model. + * + * @return An enumeration of the columns in the model. */ Enumeration getColumns(); @@ -123,30 +129,53 @@ public interface TableColumnModel * Returns the column margin. * * @return The column margin. + * + * @see #setColumnMargin(int) */ int getColumnMargin(); /** - * getColumnIndexAtX - * @return Column index as position x + * Returns the index of the column that contains the specified x-coordinate, + * assuming that: + *
    + *
  • column zero begins at position zero;
  • + *
  • all columns appear in order;
  • + *
  • individual column widths are taken into account, but the column margin + * is ignored.
  • + *
+ * If no column contains the specified position, this method returns + * -1. + * + * @param xPosition the x-position. + * + * @return The column index, or -1. */ int getColumnIndexAtX(int xPosition); /** - * getTotalColumnWidth - * @return Total column width + * Returns total width of all the columns in the model, ignoring the + * column margin (see {@link #getColumnMargin()}). + * + * @return The total width of all the columns. */ int getTotalColumnWidth(); /** - * setColumnSelectionAllowed - * @param value Set column selection + * Sets the flag that indicates whether or not column selection is allowed. + * + * @param allowed the new flag value. + * + * @see #getColumnSelectionAllowed() */ - void setColumnSelectionAllowed(boolean value); + void setColumnSelectionAllowed(boolean allowed); /** - * getColumnSelectionAllowed - * @return true if column selection allowed, false otherwise + * Returns true if column selection is allowed, and + * false if column selection is not allowed. + * + * @return A boolean. + * + * @see #setColumnSelectionAllowed(boolean) */ boolean getColumnSelectionAllowed(); @@ -157,31 +186,47 @@ public interface TableColumnModel int[] getSelectedColumns(); /** - * getSelectedColumnCount - * @return Count of selected columns + * Returns the number of selected columns in the model. + * + * @return The selected column count. + * + * @see #getSelectionModel() */ int getSelectedColumnCount(); /** - * setSelectionModel - * @param model ListSelectionModel + * Sets the selection model that will be used to keep track of the selected + * columns. + * + * @param model the selection model (null not permitted). + * + * @throws IllegalArgumentException if model is + * null. */ void setSelectionModel(ListSelectionModel model); /** - * getSelectionModel + * Returns the selection model used to track table column selections. + * + * @return The selection model. + * + * @see #setSelectionModel(ListSelectionModel) */ ListSelectionModel getSelectionModel(); /** - * addColumnModelListener - * @param listener TableColumnModelListener + * Registers a listener with the model, so that it will receive + * {@link TableColumnModelEvent} notifications. + * + * @param listener the listener (null ignored). */ void addColumnModelListener(TableColumnModelListener listener); /** - * removeColumnModelListener - * @param listener TableColumnModelListener + * Deregisters a listener, so that it will no longer receive + * {@link TableColumnModelEvent} notifications. + * + * @param listener the listener. */ void removeColumnModelListener(TableColumnModelListener listener); } diff --git a/javax/swing/text/AbstractDocument.java b/javax/swing/text/AbstractDocument.java index e656e7e9c..bb065044d 100644 --- a/javax/swing/text/AbstractDocument.java +++ b/javax/swing/text/AbstractDocument.java @@ -51,6 +51,7 @@ import javax.swing.event.DocumentListener; import javax.swing.event.EventListenerList; import javax.swing.event.UndoableEditEvent; import javax.swing.event.UndoableEditListener; +import javax.swing.text.DocumentFilter; import javax.swing.tree.TreeNode; import javax.swing.undo.AbstractUndoableEdit; import javax.swing.undo.CompoundEdit; @@ -148,6 +149,11 @@ public abstract class AbstractDocument implements Document, Serializable */ Object documentCV = new Object(); + /** An instance of a DocumentFilter.FilterBypass which allows calling + * the insert, remove and replace method without checking for an installed + * document filter. + */ + DocumentFilter.FilterBypass bypass; /** * Creates a new AbstractDocument with the specified @@ -180,6 +186,19 @@ public abstract class AbstractDocument implements Document, Serializable content = doc; context = ctx; } + + /** Returns the DocumentFilter.FilterBypass instance for this + * document and create it if it does not exist yet. + * + * @return This document's DocumentFilter.FilterBypass instance. + */ + private DocumentFilter.FilterBypass getBypass() + { + if (bypass == null) + bypass = new Bypass(); + + return bypass; + } /** * Returns the paragraph {@link Element} that holds the specified position. @@ -521,6 +540,9 @@ public abstract class AbstractDocument implements Document, Serializable /** * Inserts a String into this Document at the specified * position and assigning the specified attributes to it. + * + *

If a {@link DocumentFilter} is installed in this document, the + * corresponding method of the filter object is called.

* * @param offset the location at which the string should be inserted * @param text the content to be inserted @@ -531,6 +553,15 @@ public abstract class AbstractDocument implements Document, Serializable */ public void insertString(int offset, String text, AttributeSet attributes) throws BadLocationException + { + if (documentFilter != null) + documentFilter.insertString(getBypass(), offset, text, attributes); + else + insertStringImpl(offset, text, attributes); + } + + void insertStringImpl(int offset, String text, AttributeSet attributes) + throws BadLocationException { // Just return when no text to insert was given. if (text == null || text.length() == 0) @@ -673,6 +704,9 @@ public abstract class AbstractDocument implements Document, Serializable /** * Removes a piece of content from this Document. + * + *

If a {@link DocumentFilter} is installed in this document, the + * corresponding method of the filter object is called.

* * @param offset the start offset of the fragment to be removed * @param length the length of the fragment to be removed @@ -682,6 +716,14 @@ public abstract class AbstractDocument implements Document, Serializable * document */ public void remove(int offset, int length) throws BadLocationException + { + if (documentFilter != null) + documentFilter.remove(getBypass(), offset, length); + else + removeImpl(offset, length); + } + + void removeImpl(int offset, int length) throws BadLocationException { DefaultDocumentEvent event = new DefaultDocumentEvent(offset, length, @@ -707,6 +749,9 @@ public abstract class AbstractDocument implements Document, Serializable /** * Replaces a piece of content in this Document with * another piece of content. + * + *

If a {@link DocumentFilter} is installed in this document, the + * corresponding method of the filter object is called.

* * @param offset the start offset of the fragment to be removed * @param length the length of the fragment to be removed @@ -720,11 +765,21 @@ public abstract class AbstractDocument implements Document, Serializable * @since 1.4 */ public void replace(int offset, int length, String text, + AttributeSet attributes) + throws BadLocationException + { + if (documentFilter != null) + documentFilter.replace(getBypass(), offset, length, text, attributes); + else + replaceImpl(offset, length, text, attributes); + } + + void replaceImpl(int offset, int length, String text, AttributeSet attributes) throws BadLocationException { - remove(offset, length); - insertString(offset, text, attributes); + removeImpl(offset, length); + insertStringImpl(offset, text, attributes); } /** @@ -2239,4 +2294,37 @@ public abstract class AbstractDocument implements Document, Serializable + getStartOffset() + "," + getEndOffset() + "\n"); } } + + /** A class whose methods delegate to the insert, remove and replace methods + * of this document which do not check for an installed DocumentFilter. + */ + class Bypass extends DocumentFilter.FilterBypass + { + + public Document getDocument() + { + return AbstractDocument.this; + } + + public void insertString(int offset, String string, AttributeSet attr) + throws BadLocationException + { + AbstractDocument.this.insertStringImpl(offset, string, attr); + } + + public void remove(int offset, int length) + throws BadLocationException + { + AbstractDocument.this.removeImpl(offset, length); + } + + public void replace(int offset, int length, String string, + AttributeSet attrs) + throws BadLocationException + { + AbstractDocument.this.replaceImpl(offset, length, string, attrs); + } + + } + } diff --git a/javax/swing/text/AsyncBoxView.java b/javax/swing/text/AsyncBoxView.java index 863c409ed..90447f86e 100644 --- a/javax/swing/text/AsyncBoxView.java +++ b/javax/swing/text/AsyncBoxView.java @@ -1367,7 +1367,7 @@ public class AsyncBoxView /** * Updates the layout for this view. This is implemented to trigger - * {link ChildLocator#childChanged} for the changed view, if there is + * {@link ChildLocator#childChanged} for the changed view, if there is * any. * * @param ec the element change, may be null if there were diff --git a/javax/swing/text/CompositeView.java b/javax/swing/text/CompositeView.java index 9195602ce..17f13dbed 100644 --- a/javax/swing/text/CompositeView.java +++ b/javax/swing/text/CompositeView.java @@ -633,8 +633,51 @@ public abstract class CompositeView Position.Bias[] biasRet) throws BadLocationException { - // FIXME: Implement this correctly. - return pos; + // TODO: It is unknown to me how this method has to be implemented and + // there is no specification telling me how to do it properly. Therefore + // the implementation was done for cases that are known. + // + // If this method ever happens to act silly for your particular case then + // it is likely that it is a cause of not knowing about your case when it + // was implemented first. You are free to fix the behavior. + // + // Here are the assumptions that lead to the implementation: + // If direction is NORTH chose the View preceding the one that contains the + // offset 'pos' (imagine the views are stacked on top of each other where + // the top is 0 and the bottom is getViewCount()-1. + // Consecutively when the direction is SOUTH the View following the one + // the offset 'pos' lies in is questioned. + // + // This limitation is described as PR 27345. + int index = getViewIndex(pos, b); + View v = null; + + if (index == -1) + return pos; + + switch (direction) + { + case NORTH: + // If we cannot calculate a proper offset return the one that was + // provided. + if (index <= 0) + return pos; + + v = getView(index - 1); + break; + case SOUTH: + // If we cannot calculate a proper offset return the one that was + // provided. + if (index >= getViewCount() - 1) + return pos; + + v = getView(index + 1); + break; + default: + throw new IllegalArgumentException(); + } + + return v.getNextVisualPositionFrom(pos, b, a, direction, biasRet); } /** @@ -667,8 +710,55 @@ public abstract class CompositeView Position.Bias[] biasRet) throws BadLocationException { - // FIXME: Implement this correctly. - return pos; + // TODO: It is unknown to me how this method has to be implemented and + // there is no specification telling me how to do it properly. Therefore + // the implementation was done for cases that are known. + // + // If this method ever happens to act silly for your particular case then + // it is likely that it is a cause of not knowing about your case when it + // was implemented first. You are free to fix the behavior. + // + // Here are the assumptions that lead to the implementation: + // If direction is EAST increase the offset by one and ask the View to + // which that index belong to calculate the 'next visual position'. + // If the direction is WEST do the same with offset 'pos' being decreased + // by one. + // This behavior will fail in a right-to-left or bidi environment! + // + // This limitation is described as PR 27346. + int index; + + View v = null; + + switch (direction) + { + case EAST: + index = getViewIndex(pos + 1, b); + // If we cannot calculate a proper offset return the one that was + // provided. + if (index == -1) + return pos; + + v = getView(index); + break; + case WEST: + index = getViewIndex(pos - 1, b); + // If we cannot calculate a proper offset return the one that was + // provided. + if (index == -1) + return pos; + + v = getView(index); + break; + default: + throw new IllegalArgumentException(); + } + + return v.getNextVisualPositionFrom(pos, + b, + a, + direction, + biasRet); } /** diff --git a/javax/swing/text/DefaultCaret.java b/javax/swing/text/DefaultCaret.java index 9b6cd6b07..fc2aca0a0 100644 --- a/javax/swing/text/DefaultCaret.java +++ b/javax/swing/text/DefaultCaret.java @@ -59,6 +59,7 @@ import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.event.EventListenerList; +import javax.swing.text.Position.Bias; /** * The default implementation of the {@link Caret} interface. @@ -75,6 +76,31 @@ public class DefaultCaret extends Rectangle */ static JTextComponent componentWithSelection; + /** An implementation of NavigationFilter.FilterBypass which delegates + * to the corresponding methods of the DefaultCaret. + * + * @author Robert Schuster (robertschuster@fsfe.org) + */ + class Bypass extends NavigationFilter.FilterBypass + { + + public Caret getCaret() + { + return DefaultCaret.this; + } + + public void moveDot(int dot, Bias bias) + { + DefaultCaret.this.moveDotImpl(dot); + } + + public void setDot(int dot, Bias bias) + { + DefaultCaret.this.setDotImpl(dot); + } + + } + /** * Controls the blinking of the caret. * @@ -298,6 +324,13 @@ public class DefaultCaret extends Rectangle private BlinkTimerListener blinkListener; + /** + * A NavigationFilter.FilterBypass instance which + * is provided to the a NavigationFilter to + * unconditionally set or move the caret. + */ + NavigationFilter.FilterBypass bypass; + /** * Creates a new DefaultCaret instance. */ @@ -305,6 +338,16 @@ public class DefaultCaret extends Rectangle { // Nothing to do here. } + + /** Returns the caret's NavigationFilter.FilterBypass instance + * and creates it if it does not yet exist. + * + * @return The caret's NavigationFilter.FilterBypass instance. + */ + private NavigationFilter.FilterBypass getBypass() + { + return (bypass == null) ? bypass = new Bypass() : bypass; + } /** * Sets the Caret update policy. @@ -946,11 +989,23 @@ public class DefaultCaret extends Rectangle * Moves the dot location without touching the * mark. This is used when making a selection. * + *

If the underlying text component has a {@link NavigationFilter} + * installed the caret will call the corresponding method of that object.

+ * * @param dot the location where to move the dot * * @see #setDot(int) */ public void moveDot(int dot) + { + NavigationFilter filter = textComponent.getNavigationFilter(); + if (filter != null) + filter.moveDot(getBypass(), dot, Bias.Forward); + else + moveDotImpl(dot); + } + + void moveDotImpl(int dot) { if (dot >= 0) { @@ -970,11 +1025,23 @@ public class DefaultCaret extends Rectangle * Document. This also sets the mark to the new * location. * + *

If the underlying text component has a {@link NavigationFilter} + * installed the caret will call the corresponding method of that object.

+ * * @param dot * the new position to be set * @see #moveDot(int) */ public void setDot(int dot) + { + NavigationFilter filter = textComponent.getNavigationFilter(); + if (filter != null) + filter.setDot(getBypass(), dot, Bias.Forward); + else + setDotImpl(dot); + } + + void setDotImpl(int dot) { if (dot >= 0) { @@ -1135,4 +1202,5 @@ public class DefaultCaret extends Rectangle blinkTimer = new Timer(getBlinkRate(), blinkListener); blinkTimer.setRepeats(true); } + } diff --git a/javax/swing/text/DefaultHighlighter.java b/javax/swing/text/DefaultHighlighter.java index 58602c249..59f77316e 100644 --- a/javax/swing/text/DefaultHighlighter.java +++ b/javax/swing/text/DefaultHighlighter.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.text; +import gnu.classpath.NotImplementedException; + import java.awt.Color; import java.awt.Graphics; import java.awt.Insets; @@ -45,6 +47,7 @@ import java.awt.Rectangle; import java.awt.Shape; import java.util.ArrayList; +import javax.swing.SwingUtilities; import javax.swing.plaf.TextUI; public class DefaultHighlighter extends LayeredHighlighter @@ -91,8 +94,18 @@ public class DefaultHighlighter extends LayeredHighlighter Rectangle l0 = ui.modelToView(t, p0, null); Rectangle l1 = ui.modelToView(t, p1, null); + // Note: The computed locations may lie outside of the allocation + // area if the text is scrolled. + if (l0.y == l1.y) - paintHighlight(g, l0.union(l1)); + { + SwingUtilities.computeUnion(l0.x, l0.y, l0.width, l0.height, l1); + + // Paint only inside the allocation area. + SwingUtilities.computeIntersection(rect.x, rect.y, rect.width, rect.height, l1); + + paintHighlight(g, l1); + } else { // 1. The line of p0 is painted from the position of p0 @@ -104,7 +117,11 @@ public class DefaultHighlighter extends LayeredHighlighter // position of p1. // Highlight first line until the end. - l0.width = rect.width - l0.x; + // If rect.x is non-zero the calculation will properly adjust the + // area to be painted. + l0.x -= rect.x; + l0.width = rect.width - l0.x - rect.x; + paintHighlight(g, l0); int posBelow = Utilities.getPositionBelow(t, p0, l0.x); @@ -358,6 +375,7 @@ public class DefaultHighlighter extends LayeredHighlighter public void paintLayeredHighlights(Graphics g, int p0, int p1, Shape viewBounds, JTextComponent editor, View view) + throws NotImplementedException { // TODO: Implement this properly. } diff --git a/javax/swing/text/FieldView.java b/javax/swing/text/FieldView.java index 928949b56..127f32f53 100644 --- a/javax/swing/text/FieldView.java +++ b/javax/swing/text/FieldView.java @@ -236,8 +236,13 @@ public class FieldView extends PlainView checkContainer(); Shape newAlloc = adjustAllocation(s); - + + // Set a clip to prevent drawing outside of the allocation area. + // TODO: Is there a better way to achieve this? + Shape clip = g.getClip(); + g.setClip(s); super.paint(g, newAlloc); + g.setClip(clip); } public void insertUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) diff --git a/javax/swing/text/FlowView.java b/javax/swing/text/FlowView.java index 8be8f41e9..8ca55d834 100644 --- a/javax/swing/text/FlowView.java +++ b/javax/swing/text/FlowView.java @@ -433,7 +433,7 @@ public abstract class FlowView extends BoxView /** * Loads the children of this view. The FlowView does not * directly load its children. Instead it creates a logical view - * (@{link #layoutPool}) which is filled by the logical child views. + * ({@link #layoutPool}) which is filled by the logical child views. * The real children are created at layout time and each represent one * row. * diff --git a/javax/swing/text/Utilities.java b/javax/swing/text/Utilities.java index 3149048f7..f154e55aa 100644 --- a/javax/swing/text/Utilities.java +++ b/javax/swing/text/Utilities.java @@ -48,6 +48,7 @@ import java.text.BreakIterator; * inside this package. * * @author Roman Kennke (roman@ontographics.com) + * @author Robert Schuster (robertschuster@fsfe.org) */ public class Utilities { @@ -238,34 +239,39 @@ public class Utilities // At the end of the for loop, this holds the requested model location int pos; int currentX = x0; + int width = 0; for (pos = 0; pos < s.count; pos++) { char nextChar = s.array[s.offset+pos]; if (nextChar == 0) - { - if (! round && pos > 0) - pos--; break; - } + if (nextChar != '\t') - currentX += fm.charWidth(nextChar); + width = fm.charWidth(nextChar); else { if (te == null) - currentX += fm.charWidth(' '); + width = fm.charWidth(' '); else - currentX = (int) te.nextTabStop(currentX, pos); + width = ((int) te.nextTabStop(currentX, pos)) - currentX; } - if (currentX >= x) + if (round) { - if (! round && pos > 0) - pos--; - break; + if (currentX + (width>>1) > x) + break; } + else + { + if (currentX + width > x) + break; + } + + currentX += width; } + return pos + p0; } @@ -316,21 +322,31 @@ public class Utilities String text = c.getText(); BreakIterator wb = BreakIterator.getWordInstance(); wb.setText(text); + int last = wb.following(offs); int current = wb.next(); + int cp; + while (current != BreakIterator.DONE) { for (int i = last; i < current; i++) { - // FIXME: Should use isLetter(int) and text.codePointAt(int) - // instead, but isLetter(int) isn't implemented yet - if (Character.isLetter(text.charAt(i))) + cp = text.codePointAt(i); + + // Return the last found bound if there is a letter at the current + // location or is not whitespace (meaning it is a number or + // punctuation). The first case means that 'last' denotes the + // beginning of a word while the second case means it is the start + // of some else. + if (Character.isLetter(cp) + || !Character.isWhitespace(cp)) return last; } last = current; current = wb.next(); } - return BreakIterator.DONE; + + throw new BadLocationException("no more word", offs); } /** @@ -359,9 +375,7 @@ public class Utilities { for (int i = last; i < offs; i++) { - // FIXME: Should use isLetter(int) and text.codePointAt(int) - // instead, but isLetter(int) isn't implemented yet - if (Character.isLetter(text.charAt(i))) + if (Character.isLetter(text.codePointAt(i))) return last; } last = current; @@ -511,24 +525,28 @@ public class Utilities int x0, int x, TabExpander e, int startOffset) { - int mark = Utilities.getTabbedTextOffset(s, metrics, x0, x, e, startOffset); + int mark = Utilities.getTabbedTextOffset(s, metrics, x0, x, e, startOffset, false); BreakIterator breaker = BreakIterator.getWordInstance(); breaker.setText(s); - // If mark is equal to the end of the string, just use that position - if (mark >= s.count) + // If startOffset and s.offset differ then we need to use + // that difference two convert the offset between the two metrics. + int shift = startOffset - s.offset; + + // If mark is equal to the end of the string, just use that position. + if (mark >= shift + s.count) return mark; // Try to find a word boundary previous to the mark at which we - // can break the text - int preceding = breaker.preceding(mark + 1); + // can break the text. + int preceding = breaker.preceding(mark + 1 - shift); if (preceding != 0) - return preceding; - else - // If preceding is 0 we couldn't find a suitable word-boundary so - // just break it on the character boundary - return mark; + return preceding + shift; + + // If preceding is 0 we couldn't find a suitable word-boundary so + // just break it on the character boundary + return mark; } /** diff --git a/javax/swing/text/View.java b/javax/swing/text/View.java index 2feaf29a4..d8ad5f585 100644 --- a/javax/swing/text/View.java +++ b/javax/swing/text/View.java @@ -1,5 +1,5 @@ /* View.java -- - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -733,23 +733,38 @@ public abstract class View implements SwingConstants throws BadLocationException { int ret = pos; + Rectangle r; + View parent; + switch (d) { - case WEST: - ret = pos - 1; - break; case EAST: - ret = pos + 1; + // TODO: take component orientation into account? + // Note: If pos is below zero the implementation will return + // pos + 1 regardless of whether that value is a correct offset + // in the document model. However this is what the RI does. + ret = Math.min(pos + 1, getEndOffset()); + break; + case WEST: + // TODO: take component orientation into account? + ret = Math.max(pos - 1, getStartOffset()); break; case NORTH: - // TODO: Implement this + // Try to find a suitable offset by examining the area above. + parent = getParent(); + r = parent.modelToView(pos, a, b).getBounds(); + ret = parent.viewToModel(r.x, r.y - 1, a, biasRet); break; case SOUTH: - // TODO: Implement this + // Try to find a suitable offset by examining the area below. + parent = getParent(); + r = parent.modelToView(pos, a, b).getBounds(); + ret = parent.viewToModel(r.x + r.width, r.y + r.height, a, biasRet); break; default: throw new IllegalArgumentException("Illegal value for d"); } + return ret; } } diff --git a/javax/swing/text/WrappedPlainView.java b/javax/swing/text/WrappedPlainView.java index 9477f23f7..1cd85b515 100644 --- a/javax/swing/text/WrappedPlainView.java +++ b/javax/swing/text/WrappedPlainView.java @@ -275,7 +275,17 @@ public class WrappedPlainView extends BoxView implements TabExpander protected int calculateBreakPosition(int p0, int p1) { Container c = getContainer(); - Rectangle alloc = new Rectangle(0, 0, getWidth(), getHeight()); + + int li = getLeftInset(); + int ti = getTopInset(); + + Rectangle alloc = new Rectangle(li, ti, + getWidth()-getRightInset()-li, + getHeight()-getBottomInset()-ti); + + // Mimic a behavior observed in the RI. + if (alloc.isEmpty()) + return 0; updateMetrics(); @@ -288,10 +298,10 @@ public class WrappedPlainView extends BoxView implements TabExpander // this shouldn't happen throw new InternalError("Invalid offsets p0: " + p0 + " - p1: " + p1); } - // FIXME: Should we account for the insets of the container? + if (wordWrap) - return p0 + Utilities.getBreakLocation(lineBuffer, metrics, alloc.x, - alloc.x + alloc.width, this, 0); + return Utilities.getBreakLocation(lineBuffer, metrics, alloc.x, + alloc.x + alloc.width, this, p0); else return p0 + Utilities.getTabbedTextOffset(lineBuffer, metrics, alloc.x, alloc.x + alloc.width, this, 0, @@ -419,7 +429,7 @@ public class WrappedPlainView extends BoxView implements TabExpander class WrappedLine extends View { /** Used to cache the number of lines for this View **/ - int numLines; + int numLines = 1; public WrappedLine(Element elem) { @@ -437,17 +447,30 @@ public class WrappedPlainView extends BoxView implements TabExpander int end = getEndOffset(); int currStart = getStartOffset(); - int currEnd; + int currEnd; + int count = 0; while (currStart < end) { currEnd = calculateBreakPosition(currStart, end); + drawLine(currStart, currEnd, g, rect.x, rect.y + metrics.getAscent()); + rect.y += lineHeight; if (currEnd == currStart) currStart ++; else - currStart = currEnd; + currStart = currEnd; + + count++; + + } + + if (count != numLines) + { + numLines = count; + preferenceChanged(this, false, true); } + } /** @@ -470,6 +493,9 @@ public class WrappedPlainView extends BoxView implements TabExpander // depending on which position calculateBreakPosition returns breakPoint = calculateBreakPosition(i, end); + if (breakPoint == 0) + return; + // If breakPoint is equal to the current index no further // line is needed and we can end the loop. if (breakPoint == i) @@ -492,7 +518,7 @@ public class WrappedPlainView extends BoxView implements TabExpander if (axis == X_AXIS) return getWidth(); else if (axis == Y_AXIS) - return numLines * metrics.getHeight(); + return numLines * metrics.getHeight(); throw new IllegalArgumentException("Invalid axis for getPreferredSpan: " + axis); @@ -578,13 +604,15 @@ public class WrappedPlainView extends BoxView implements TabExpander Rectangle rect = a.getBounds(); int currLineStart = getStartOffset(); - // WrappedLine does not represent the last possible offset in a line. - // So we should never return that offset. Behavior observed in the RI. - int end = getEndOffset() - 1; + // Although calling modelToView with the last possible offset will + // cause a BadLocationException in CompositeView it is allowed + // to return that offset in viewToModel. + int end = getEndOffset(); int lineHeight = metrics.getHeight(); if (y < rect.y) return currLineStart; + if (y > rect.y + rect.height) return end; @@ -592,9 +620,10 @@ public class WrappedPlainView extends BoxView implements TabExpander // text but the area where text *may* be painted. This means the width // is most of the time identical to the component's width. - while (true) + while (currLineStart != end) { int currLineEnd = calculateBreakPosition(currLineStart, end); + // If we're at the right y-position that means we're on the right // logical line and we should look for the character if (y >= rect.y && y < rect.y + lineHeight) @@ -608,18 +637,27 @@ public class WrappedPlainView extends BoxView implements TabExpander // Shouldn't happen } - return Utilities.getTabbedTextOffset(s, metrics, rect.x, + int offset = Utilities.getTabbedTextOffset(s, metrics, rect.x, (int) x, WrappedPlainView.this, currLineStart); + // If the calculated offset is the end of the line (in the + // document (= start of the next line) return the preceding + // offset instead. This makes sure that clicking right besides + // the last character in a line positions the cursor after the + // last character and not in the beginning of the next line. + return (offset == currLineEnd) ? offset - 1 : offset; } // Increment rect.y so we're checking the next logical line rect.y += lineHeight; // Increment currLineStart to the model position of the start - // of the next logical line + // of the next logical line. currLineStart = currLineEnd; + } + + return end; } /** @@ -632,6 +670,16 @@ public class WrappedPlainView extends BoxView implements TabExpander */ void updateDamage (Rectangle a) { + // If the allocation area is empty we can't do anything useful. + // As determining the number of lines is impossible in that state we + // reset it to an invalid value which can then be recalculated at a + // later point. + if (a.isEmpty()) + { + numLines = 1; + return; + } + int oldNumLines = numLines; determineNumLines(); diff --git a/javax/swing/tree/AbstractLayoutCache.java b/javax/swing/tree/AbstractLayoutCache.java index 445aa233e..713c9cae7 100644 --- a/javax/swing/tree/AbstractLayoutCache.java +++ b/javax/swing/tree/AbstractLayoutCache.java @@ -44,6 +44,7 @@ import java.awt.Rectangle; import java.util.Enumeration; import javax.swing.event.TreeModelEvent; +import javax.swing.tree.VariableHeightLayoutCache.NodeRecord; /** * class AbstractLayoutCache @@ -66,19 +67,21 @@ public abstract class AbstractLayoutCache // Do nothing here. } - /** - * getNodeDimensions - * - * @param value0 TODO - * @param value1 TODO - * @param value2 TODO - * @param value3 TODO - * @param value4 TODO - * @return Rectangle - */ - public abstract Rectangle getNodeDimensions(Object value0, int value1, - int value2, boolean value3, - Rectangle value4); + /** + * Get the node dimensions. The NodeDimensions property must be set (unless + * the method is overridden, like if {@link FixedHeightLayoutCache}. If the + * method is not overridden and the property is not set, the InternalError is + * thrown. + * + * @param value the last node in the path + * @param row the node row + * @param depth the indentation depth + * @param expanded true if this node is expanded, false otherwise + * @param bounds the area where the tree is displayed + */ + public abstract Rectangle getNodeDimensions(Object value, int row, + int depth, boolean expanded, + Rectangle bounds); } /** @@ -204,6 +207,7 @@ public abstract class AbstractLayoutCache public void setRowHeight(int height) { rowHeight = height; + invalidateSizes(); } /** @@ -237,29 +241,51 @@ public abstract class AbstractLayoutCache } /** - * getPreferredHeight - * - * @return int + * Get the sum of heights for all rows. This class provides a general not + * optimized implementation that is overridded in derived classes + * ({@link VariableHeightLayoutCache}, {@link FixedHeightLayoutCache}) for + * the better performance. */ - public int getPreferredHeight() - throws NotImplementedException + public int getPreferredHeight() { - return 0; // TODO + int height = 0; + int n = getRowCount(); + Rectangle r = new Rectangle(); + for (int i = 0; i < n; i++) + { + TreePath path = getPathForRow(i); + height += getBounds(path, r).height; + } + return height; } /** - * getPreferredWidth + * Get the maximal width. This class provides a general not + * optimized implementation that is overridded in derived classes + * ({@link VariableHeightLayoutCache}, {@link FixedHeightLayoutCache}) for + * the better performance. * - * @param value0 TODO - * - * @return int + * @param rect the rectangle that is used during the method work */ - public int getPreferredWidth(Rectangle value0) - throws NotImplementedException + public int getPreferredWidth(Rectangle rect) { - return 0; // TODO + int maximalWidth = 0; + Rectangle r = new Rectangle(); + int n = getRowCount(); + for (int i = 0; i < n; i++) + { + TreePath path = getPathForRow(i); + r.setBounds(0,0,0,0); + r = getBounds(path, r); + if (r.x + r.width > maximalWidth) + maximalWidth = r.x + r.width; + // Invalidate the cached value as this may be the very early call + // before the heigth is properly set (the vertical coordinate may + // not be correct). + invalidatePathBounds(path); + } + return maximalWidth; } - /** * isExpanded * @@ -409,13 +435,14 @@ public abstract class AbstractLayoutCache } /** - * isFixedRowHeight + * Returns true if this layout supposes that all rows have the fixed + * height. * - * @return boolean + * @return boolean true if all rows in the tree must have the fixed + * height (false by default). */ protected boolean isFixedRowHeight() - throws NotImplementedException { - return false; // TODO + return false; } } diff --git a/javax/swing/tree/DefaultMutableTreeNode.java b/javax/swing/tree/DefaultMutableTreeNode.java index 3569ebdbb..389101be1 100644 --- a/javax/swing/tree/DefaultMutableTreeNode.java +++ b/javax/swing/tree/DefaultMutableTreeNode.java @@ -154,6 +154,8 @@ public class DefaultMutableTreeNode /** * Adds a new child node to this node and sets this node as the parent of * the child node. The child node must not be an ancestor of this node. + * If the tree uses the {@link DefaultTreeModel}, you must subsequently + * call {@link DefaultTreeModel#reload(TreeNode)}. * * @param child the child node (null not permitted). * diff --git a/javax/swing/tree/DefaultTreeCellEditor.java b/javax/swing/tree/DefaultTreeCellEditor.java index e28c9261b..cc19501d2 100644 --- a/javax/swing/tree/DefaultTreeCellEditor.java +++ b/javax/swing/tree/DefaultTreeCellEditor.java @@ -76,17 +76,6 @@ import javax.swing.event.TreeSelectionListener; public class DefaultTreeCellEditor implements ActionListener, TreeCellEditor, TreeSelectionListener { - /** - * The gap between the icon and editing component during editing. - */ - static int ICON_TEXT_GAP = 3; - - /** - * The left margin of the editing container (the gap between the tree and - * the editing component of the editing icon. - */ - static int TREE_ICON_GAP = ICON_TEXT_GAP; - /** * The number of the fast mouse clicks, required to start the editing * session. @@ -141,7 +130,7 @@ public class DefaultTreeCellEditor { // From the previous version, the left margin is taken as half // of the icon width. - editingIcon.paintIcon(this, g, TREE_ICON_GAP, 0); + editingIcon.paintIcon(this, g, 0, 0); } super.paint(g); } @@ -157,7 +146,7 @@ public class DefaultTreeCellEditor // Move the component to the left, leaving room for the editing icon: if (editingIcon != null) - eOffset = TREE_ICON_GAP + editingIcon.getIconWidth() + ICON_TEXT_GAP; + eOffset = editingIcon.getIconWidth(); else eOffset = 0; @@ -166,7 +155,7 @@ public class DefaultTreeCellEditor c.setLocation(eOffset, 0); // Span the editing component near over all window width. - c.setSize(bounds.width - eOffset - TREE_ICON_GAP, bounds.height); + c.setSize(bounds.width - eOffset, bounds.height); /* * @specnote the Sun sets some more narrow editing component width (it is * not documented how does it is calculated). However as our text field is @@ -542,7 +531,8 @@ public class DefaultTreeCellEditor * If the realEditor returns true to this message, prepareForEditing * is messaged and true is returned. * - * @param event - the event the editor should use to consider whether to begin editing or not + * @param event - the event the editor should use to consider whether to + * begin editing or not * @return true if editing can be started */ public boolean isCellEditable(EventObject event) diff --git a/javax/swing/tree/DefaultTreeCellRenderer.java b/javax/swing/tree/DefaultTreeCellRenderer.java index df70ba7fb..5e93145ae 100644 --- a/javax/swing/tree/DefaultTreeCellRenderer.java +++ b/javax/swing/tree/DefaultTreeCellRenderer.java @@ -407,7 +407,7 @@ public class DefaultTreeCellRenderer this.hasFocus = hasFocus; setHorizontalAlignment(LEFT); setOpaque(false); - setVerticalAlignment(TOP); + setVerticalAlignment(CENTER); setEnabled(true); super.setFont(UIManager.getFont("Tree.font")); @@ -445,8 +445,7 @@ public class DefaultTreeCellRenderer /** * Paints the value. The background is filled based on selected. * - * @param g - * the graphics device. + * @param g the graphics device. */ public void paint(Graphics g) { @@ -468,17 +467,27 @@ public class DefaultTreeCellRenderer getHorizontalTextPosition(), vr, ir, tr, getIconTextGap()); + // Reusing one rectangle. + Rectangle bounds = getBounds(ir); + + bounds.x = tr.x - insets.left; + bounds.width = tr.width + insets.left+insets.right; + g.setColor(super.getBackground()); - g.fillRect(tr.x, tr.y, tr.width, tr.height - insets.top - insets.bottom); + g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height); - // paint border - Color b = getBorderSelectionColor(); - if (b != null) + super.paint(g); + + // Paint the border of the focused element only (lead selection) + if (hasFocus) { - g.setColor(b); - g.drawRect(tr.x, tr.y, tr.width, tr.height - insets.top - insets.bottom); + Color b = getBorderSelectionColor(); + if (b != null) + { + g.setColor(b); + g.drawRect(bounds.x, bounds.y, bounds.width, bounds.height - 1); + } } - super.paint(g); } /** diff --git a/javax/swing/tree/DefaultTreeModel.java b/javax/swing/tree/DefaultTreeModel.java index e462b1c8b..713343811 100644 --- a/javax/swing/tree/DefaultTreeModel.java +++ b/javax/swing/tree/DefaultTreeModel.java @@ -223,27 +223,60 @@ public class DefaultTreeModel } /** - * Invoke this method if you've modified the TreeNodes upon - * which this model depends. The model will notify all of its - * listeners that the model has changed. + *

+ * Invoke this method if you've modified the TreeNodes upon which this model + * depends. The model will notify all of its listeners that the model has + * changed. It will fire the events, necessary to update the layout caches and + * repaint the tree. The tree will not be properly refreshed if you + * call the JTree.repaint instead. + *

+ *

+ * This method will refresh the information about whole tree from the root. If + * only part of the tree should be refreshed, it is more effective to call + * {@link #reload(TreeNode)}. + *

*/ public void reload() - throws NotImplementedException { - // TODO + // Need to duplicate the code because the root can formally be + // no an instance of the TreeNode. + int n = getChildCount(root); + int[] childIdx = new int[n]; + Object[] children = new Object[n]; + + for (int i = 0; i < n; i++) + { + childIdx[i] = i; + children[i] = getChild(root, i); + } + + fireTreeStructureChanged(this, new Object[] { root }, childIdx, children); } /** - * Invoke this method if you've modified the TreeNodes upon - * which this model depends. The model will notify all of its - * listeners that the model has changed. + * Invoke this method if you've modified the TreeNodes upon which this model + * depends. The model will notify all of its listeners that the model has + * changed. It will fire the events, necessary to update the layout caches and + * repaint the tree. The tree will not be properly refreshed if you + * call the JTree.repaint instead. * - * @param node - TODO + * @param node - the tree node, from which the tree nodes have changed + * (inclusive). If you do not know this node, call {@link #reload()} + * instead. */ public void reload(TreeNode node) - throws NotImplementedException { - // TODO + int n = getChildCount(node); + int[] childIdx = new int[n]; + Object[] children = new Object[n]; + + for (int i = 0; i < n; i++) + { + childIdx[i] = i; + children[i] = getChild(node, i); + } + + fireTreeStructureChanged(this, getPathToRoot(node), childIdx, children); } /** @@ -392,9 +425,18 @@ public class DefaultTreeModel * @param node that had its children and grandchildren changed. */ public void nodeStructureChanged(TreeNode node) - throws NotImplementedException { - // TODO + int n = getChildCount(root); + int[] childIdx = new int[n]; + Object[] children = new Object[n]; + + for (int i = 0; i < n; i++) + { + childIdx[i] = i; + children[i] = getChild(root, i); + } + + fireTreeStructureChanged(this, new Object[] { root }, childIdx, children); } /** diff --git a/javax/swing/tree/DefaultTreeSelectionModel.java b/javax/swing/tree/DefaultTreeSelectionModel.java index f0e8f4932..e38850af8 100644 --- a/javax/swing/tree/DefaultTreeSelectionModel.java +++ b/javax/swing/tree/DefaultTreeSelectionModel.java @@ -38,14 +38,15 @@ exception statement from your version. */ package javax.swing.tree; -import gnu.classpath.NotImplementedException; - import java.beans.PropertyChangeListener; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.util.Arrays; import java.util.EventListener; +import java.util.HashSet; +import java.util.Iterator; import java.util.Vector; import javax.swing.DefaultListSelectionModel; @@ -61,6 +62,7 @@ import javax.swing.event.TreeSelectionListener; * expansion events. * * @author Andrew Selkirk + * @author Audrius Meskauskas */ public class DefaultTreeSelectionModel implements Cloneable, Serializable, TreeSelectionModel @@ -145,19 +147,33 @@ public class DefaultTreeSelectionModel // Clone the selection and the list selection model. cloned.selection = (TreePath[]) selection.clone(); - cloned.listSelectionModel = - (DefaultListSelectionModel) listSelectionModel.clone(); + if (listSelectionModel!=null) + cloned.listSelectionModel = + (DefaultListSelectionModel) listSelectionModel.clone(); return cloned; } /** * Returns a string that shows this object's properties. + * The returned string lists the selected tree rows, if any. * * @return a string that shows this object's properties */ - public String toString() throws NotImplementedException + public String toString() { - return null; // TODO + if (isSelectionEmpty()) + return "[selection empty]"; + else + { + StringBuffer b = new StringBuffer("selected rows: ["); + for (int i = 0; i < selection.length; i++) + { + b.append(getRow(selection[i])); + b.append(' '); + } + b.append(", lead "+getLeadSelectionRow()); + return b.toString(); + } } /** @@ -221,6 +237,7 @@ public class DefaultTreeSelectionModel public void setSelectionMode(int mode) { selectionMode = mode; + insureRowContinuity(); } /** @@ -245,7 +262,60 @@ public class DefaultTreeSelectionModel */ public void setSelectionPath(TreePath path) { + // The most frequently only one cell in the tree is selected. + TreePath[] ose = selection; selection = new TreePath[] { path }; + TreePath oldLead = leadPath; + leadIndex = 0; + leadRow = getRow(path); + leadPath = path; + + TreeSelectionEvent event; + + if (ose != null && ose.length > 0) + { + // The first item in the path list is the selected path. + // The remaining items are unselected pathes. + TreePath[] changed = new TreePath[ose.length + 1]; + boolean[] news = new boolean[changed.length]; + news[0] = true; + changed[0] = path; + System.arraycopy(ose, 0, changed, 1, ose.length); + event = new TreeSelectionEvent(this, changed, news, oldLead, path); + } + else + { + event = new TreeSelectionEvent(this, path, true, oldLead, path); + } + fireValueChanged(event); + } + + /** + * Get the number of the tree row for the given path. + * + * @param path the tree path + * @return the tree row for this path or -1 if the path is not visible. + */ + int getRow(TreePath path) + { + RowMapper mapper = getRowMapper(); + + if (mapper instanceof AbstractLayoutCache) + { + // The absolute majority of cases, unless the TreeUI is very + // seriously rewritten + AbstractLayoutCache ama = (AbstractLayoutCache) mapper; + return ama.getRowForPath(path); + } + else + { + // Generic non optimized implementation. + int[] rows = mapper.getRowsForPaths(new TreePath[] { path }); + if (rows.length == 0) + return - 1; + else + return rows[0]; + } } /** @@ -256,11 +326,11 @@ public class DefaultTreeSelectionModel * @param paths the paths to set as selection */ public void setSelectionPaths(TreePath[] paths) - throws NotImplementedException { // Must be called, as defined in JDK API 1.4. insureUniqueness(); - // TODO + clearSelection(); + addSelectionPaths(paths); } /** @@ -268,13 +338,17 @@ public class DefaultTreeSelectionModel * is already selected and doesn't add the same path twice. If this changes * the selection the registered TreeSelectionListeners are notified. * + * The lead path is changed to the added path. This also happen if the + * passed path was already selected before. + * * @param path the path to add to the selection */ public void addSelectionPath(TreePath path) { if (! isPathSelected(path)) { - if (isSelectionEmpty()) + if (selectionMode == SINGLE_TREE_SELECTION || isSelectionEmpty() + || ! canPathBeAdded(path)) setSelectionPath(path); else { @@ -284,9 +358,16 @@ public class DefaultTreeSelectionModel selection = new TreePath[temp.length]; System.arraycopy(temp, 0, selection, 0, temp.length); } + } + + if (path!=leadPath) + { + TreePath oldLead = leadPath; leadPath = path; - fireValueChanged(new TreeSelectionEvent(this, path, true, leadPath, - path)); + leadRow = getRow(path); + leadIndex = selection.length - 1; + fireValueChanged(new TreeSelectionEvent(this, path, true, oldLead, + leadPath)); } } @@ -301,7 +382,7 @@ public class DefaultTreeSelectionModel { // Must be called, as defined in JDK API 1.4. insureUniqueness(); - + if (paths != null) { TreePath v0 = null; @@ -320,11 +401,16 @@ public class DefaultTreeSelectionModel selection = new TreePath[temp.length]; System.arraycopy(temp, 0, selection, 0, temp.length); } + TreePath oldLead = leadPath; leadPath = paths[paths.length - 1]; + leadRow = getRow(leadPath); + leadIndex = selection.length - 1; + fireValueChanged(new TreeSelectionEvent(this, v0, true, - leadPath, paths[0])); + oldLead, leadPath)); } } + insureRowContinuity(); } } @@ -336,6 +422,9 @@ public class DefaultTreeSelectionModel */ public void removeSelectionPath(TreePath path) { + if (isSelectionEmpty()) + return; + int index = - 1; if (isPathSelected(path)) { @@ -353,9 +442,15 @@ public class DefaultTreeSelectionModel - index - 1); selection = new TreePath[temp.length]; System.arraycopy(temp, 0, selection, 0, temp.length); - - fireValueChanged(new TreeSelectionEvent(this, path, false, leadPath, - path)); + + // If the removed path was the lead path, set the lead path to null. + TreePath oldLead = leadPath; + if (path!=null && leadPath!=null && path.equals(leadPath)) + leadPath = null; + + fireValueChanged(new TreeSelectionEvent(this, path, false, oldLead, + leadPath)); + insureRowContinuity(); } } @@ -367,10 +462,13 @@ public class DefaultTreeSelectionModel */ public void removeSelectionPaths(TreePath[] paths) { + if (isSelectionEmpty()) + return; if (paths != null) { int index = - 1; TreePath v0 = null; + TreePath oldLead = leadPath; for (int i = 0; i < paths.length; i++) { v0 = paths[i]; @@ -383,6 +481,8 @@ public class DefaultTreeSelectionModel index = x; break; } + if (leadPath != null && leadPath.equals(v0)) + leadPath = null; } TreePath[] temp = new TreePath[selection.length - 1]; System.arraycopy(selection, 0, temp, 0, index); @@ -392,9 +492,10 @@ public class DefaultTreeSelectionModel System.arraycopy(temp, 0, selection, 0, temp.length); fireValueChanged(new TreeSelectionEvent(this, v0, false, - leadPath, paths[0])); + oldLead, leadPath)); } } + insureRowContinuity(); } } @@ -467,12 +568,23 @@ public class DefaultTreeSelectionModel } /** - * Removes all paths from the selection. + * Removes all paths from the selection. Fire the unselection event. */ public void clearSelection() { - leadPath = null; - selection = null; + if (! isSelectionEmpty()) + { + TreeSelectionEvent event = new TreeSelectionEvent( + this, selection, new boolean[selection.length], leadPath, null); + leadPath = null; + selection = null; + fireValueChanged(event); + } + else + { + leadPath = null; + selection = null; + } } /** @@ -588,18 +700,43 @@ public class DefaultTreeSelectionModel * @param row the index of the row to check * @return true if the row is in this selection, * false otherwise + * @throws NullPointerException if the row mapper is not set (can only happen + * if the user has plugged in the custom incorrect TreeUI + * implementation. */ - public boolean isRowSelected(int row) throws NotImplementedException + public boolean isRowSelected(int row) { - return false; // TODO + // Return false if nothing is selected. + if (isSelectionEmpty()) + return false; + + RowMapper mapper = getRowMapper(); + + if (mapper instanceof AbstractLayoutCache) + { + // The absolute majority of cases, unless the TreeUI is very + // seriously rewritten + AbstractLayoutCache ama = (AbstractLayoutCache) mapper; + TreePath path = ama.getPathForRow(row); + return isPathSelected(path); + } + else + { + // Generic non optimized implementation. + int[] rows = mapper.getRowsForPaths(selection); + for (int i = 0; i < rows.length; i++) + if (rows[i] == row) + return true; + return false; + } } /** * Updates the mappings from TreePaths to row indices. */ - public void resetRowSelection() throws NotImplementedException + public void resetRowSelection() { - // TODO + // Nothing to do here. } /** @@ -609,10 +746,7 @@ public class DefaultTreeSelectionModel */ public int getLeadSelectionRow() { - if ((rowMapper == null) || (leadPath == null)) - return - 1; - else - return rowMapper.getRowsForPaths(new TreePath[] { leadPath })[0]; + return leadRow; } /** @@ -665,23 +799,93 @@ public class DefaultTreeSelectionModel * has more than one path, the selection is reset to the contain only the * first path. */ - protected void insureRowContinuity() throws NotImplementedException + protected void insureRowContinuity() { - // TODO + if (selection == null || selection.length < 2) + return; + else if (selectionMode == CONTIGUOUS_TREE_SELECTION) + { + if (rowMapper == null) + // This is the best we can do without the row mapper: + selectOne(); + else + { + int[] rows = rowMapper.getRowsForPaths(selection); + Arrays.sort(rows); + int i; + for (i = 1; i < rows.length; i++) + { + if (rows[i - 1] != rows[i] - 1) + // Break if no longer continuous. + break; + } + + if (i < rows.length) + { + TreePath[] ns = new TreePath[i]; + for (int j = 0; j < ns.length; j++) + ns[i] = getPath(j); + setSelectionPaths(ns); + } + } + } + else if (selectionMode == SINGLE_TREE_SELECTION) + selectOne(); + } + + /** + * Keep only one (normally last or leading) path in the selection. + */ + private void selectOne() + { + if (leadIndex > 0 && leadIndex < selection.length) + setSelectionPath(selection[leadIndex]); + else + setSelectionPath(selection[selection.length -1]); + } + + /** + * Get path for the given row that must be in the current selection. + */ + private TreePath getPath(int row) + { + if (rowMapper instanceof AbstractLayoutCache) + return ((AbstractLayoutCache) rowMapper).getPathForRow(row); + else + { + int[] rows = rowMapper.getRowsForPaths(selection); + for (int i = 0; i < rows.length; i++) + if (rows[i] == row) + return selection[i]; + } + throw new InternalError(row + " not in selection"); } /** - * Returns true if the paths are contiguous or we have no - * RowMapper assigned. + * Returns true if the paths are contiguous (take subsequent + * rows in the diplayed tree view. The method returns true if + * we have no RowMapper assigned. * * @param paths the paths to check for continuity * @return true if the paths are contiguous or we have no * RowMapper assigned */ protected boolean arePathsContiguous(TreePath[] paths) - throws NotImplementedException { - return false; // STUB + if (rowMapper == null || paths.length < 2) + return true; + + int[] rows = rowMapper.getRowsForPaths(paths); + + // The patches may not be sorted. + Arrays.sort(rows); + + for (int i = 1; i < rows.length; i++) + { + if (rows[i-1] != rows[i] - 1) + return false; + } + return true; } /** @@ -699,9 +903,32 @@ public class DefaultTreeSelectionModel * selectionMode */ protected boolean canPathsBeAdded(TreePath[] paths) - throws NotImplementedException { - return false; // STUB + if (rowMapper == null || isSelectionEmpty() + || selectionMode == DISCONTIGUOUS_TREE_SELECTION) + return true; + + TreePath [] all = new TreePath[paths.length + selection.length]; + System.arraycopy(paths, 0, all, 0, paths.length); + System.arraycopy(selection, 0, all, paths.length, selection.length); + + return arePathsContiguous(all); + } + + /** + * Checks if the single path can be added to selection. + */ + private boolean canPathBeAdded(TreePath path) + { + if (rowMapper == null || isSelectionEmpty() + || selectionMode == DISCONTIGUOUS_TREE_SELECTION) + return true; + + TreePath[] all = new TreePath[selection.length + 1]; + System.arraycopy(selection, 0, all, 0, selection.length); + all[all.length - 1] = path; + + return arePathsContiguous(all); } /** @@ -713,29 +940,74 @@ public class DefaultTreeSelectionModel * selectionMode */ protected boolean canPathsBeRemoved(TreePath[] paths) - throws NotImplementedException { - return false; // STUB + if (rowMapper == null || isSelectionEmpty() + || selectionMode == DISCONTIGUOUS_TREE_SELECTION) + return true; + + HashSet set = new HashSet(); + for (int i = 0; i < selection.length; i++) + set.add(selection[i]); + + for (int i = 0; i < paths.length; i++) + set.remove(paths[i]); + + TreePath[] remaining = new TreePath[set.size()]; + Iterator iter = set.iterator(); + + for (int i = 0; i < remaining.length; i++) + remaining[i] = (TreePath) iter.next(); + + return arePathsContiguous(remaining); } /** - * notifyPathChange + * Notify the installed listeners that the given patches have changed. This + * method will call listeners if invoked, but it is not called from the + * implementation of this class. * - * @param value0 TODO - * @param value1 TODO + * @param vPathes the vector of the changed patches + * @param oldLeadSelection the old selection index */ - protected void notifyPathChange(Vector value0, TreePath value1) - throws NotImplementedException + protected void notifyPathChange(Vector vPathes, TreePath oldLeadSelection) { - // STUB + TreePath[] pathes = new TreePath[vPathes.size()]; + for (int i = 0; i < pathes.length; i++) + pathes[i] = (TreePath) vPathes.get(i); + + boolean[] news = new boolean[pathes.length]; + for (int i = 0; i < news.length; i++) + news[i] = isPathSelected(pathes[i]); + + TreeSelectionEvent event = new TreeSelectionEvent(this, pathes, news, + oldLeadSelection, + leadPath); + fireValueChanged(event); } /** - * Updates the lead index instance field. + * Updates the lead selection row number after changing the lead selection + * path. */ - protected void updateLeadIndex() throws NotImplementedException + protected void updateLeadIndex() { - // STUB + if (isSelectionEmpty()) + { + leadRow = leadIndex = - 1; + } + else + { + leadRow = getRow(leadPath); + for (int i = 0; i < selection.length; i++) + { + if (selection[i].equals(leadPath)) + { + leadIndex = i; + break; + } + } + leadIndex = leadRow; + } } /** diff --git a/javax/swing/tree/FixedHeightLayoutCache.java b/javax/swing/tree/FixedHeightLayoutCache.java index c4cc560fc..b8192211d 100644 --- a/javax/swing/tree/FixedHeightLayoutCache.java +++ b/javax/swing/tree/FixedHeightLayoutCache.java @@ -37,6 +37,8 @@ exception statement from your version. */ package javax.swing.tree; +import gnu.javax.swing.tree.GnuPath; + import java.awt.Rectangle; import java.util.Enumeration; import java.util.HashSet; @@ -45,22 +47,21 @@ import java.util.LinkedList; import java.util.Set; import java.util.Vector; -import javax.swing.UIManager; import javax.swing.event.TreeModelEvent; + /** * The fixed height tree layout. This class assumes that all cells in the tree * have the same fixed height. This may be not the case, for instance, if leaves * and branches have different height, of if the tree rows may have arbitrary * variable height. This class will also work if the NodeDimensions are not - * set. If they are set, the size calculations are just forwarded to the set - * instance. + * set. * * @author Audrius Meskauskas * @author Andrew Selkirk */ public class FixedHeightLayoutCache - extends AbstractLayoutCache + extends VariableHeightLayoutCache { /** * The cached node record. @@ -114,26 +115,61 @@ public class FixedHeightLayoutCache */ private TreePath path; + /** + * Get the path for this node. The derived class is returned, + * making check for the last child of some parent easier. + */ TreePath getPath() { if (path == null) { + boolean lastChild = false; + if (parent != null) + { + int nc = treeModel.getChildCount(parent); + if (nc > 0) + { + int n = treeModel.getIndexOfChild(parent, node); + if (n == nc - 1) + lastChild = true; + } + } + LinkedList lpath = new LinkedList(); NodeRecord rp = this; while (rp != null) { lpath.addFirst(rp.node); if (rp.parent != null) - rp = (NodeRecord) nodes.get(rp.parent); + { + Object parent = rp.parent; + rp = (NodeRecord) nodes.get(parent); + // Add the root node, even if it is not visible. + if (rp == null) + lpath.addFirst(parent); + } else rp = null; } - path = new TreePath(lpath.toArray()); + path = new GnuPath(lpath.toArray(), lastChild); } return path; } + + /** + * Get the rectangle bounds (compute, if required). + */ + Rectangle getBounds() + { + // This method may be called in the context when the tree rectangle is + // not known. To work around this, it is assumed near infinitely large. + if (bounds==null) + bounds = getNodeDimensions(node, row, depth, isExpanded, + new Rectangle()); + return bounds; + } } - + /** * The set of all expanded tree nodes. */ @@ -153,6 +189,16 @@ public class FixedHeightLayoutCache * If true, the row map must be recomputed before using. */ boolean dirty; + + /** + * The cumulative height of all rows. + */ + int totalHeight; + + /** + * The maximal width. + */ + int maximalWidth; /** * Creates the unitialised instance. Before using the class, the row height @@ -184,6 +230,8 @@ public class FixedHeightLayoutCache { nodes.clear(); row2node.clear(); + + totalHeight = maximalWidth = 0; Object root = treeModel.getRoot(); @@ -197,7 +245,7 @@ public class FixedHeightLayoutCache for (int i = 0; i < sc; i++) { Object child = treeModel.getChild(root, i); - countRows(child, root, 1); + countRows(child, root, 0); } } dirty = false; @@ -211,9 +259,11 @@ public class FixedHeightLayoutCache Integer n = new Integer(row2node.size()); row2node.put(n, node); - nodes.put(node, new NodeRecord(n.intValue(), depth, node, parent)); - - if (expanded.contains(node) || parent == null) + NodeRecord nr = new NodeRecord(n.intValue(), depth, node, parent); + nodes.put(node, nr); + + // For expanded nodes and for the root node. + if (expanded.contains(node)) { int sc = treeModel.getChildCount(node); int deeper = depth+1; @@ -226,14 +276,15 @@ public class FixedHeightLayoutCache } /** - * This should invalidate the width of the last path component, but - * following the JDK 1.4 API it is not cached and the method should return - * without action. - * @param path the path being invalidated, ignored. + * Discard the bound information for the given path. + * + * @param path the path, for that the bound information must be recomputed. */ public void invalidatePathBounds(TreePath path) { - // Following JDK 1.4 API, should return without action. + NodeRecord r = (NodeRecord) nodes.get(path.getLastPathComponent()); + if (r!=null) + r.bounds = null; } /** @@ -277,29 +328,34 @@ public class FixedHeightLayoutCache * Get bounds for the given tree path. * * @param path the tree path - * @param rect the rectangle, specifying the area where the path should be - * displayed. + * @param rect the rectangle that will be reused to return the result. * @return Rectangle the bounds of the last line, defined by the given path. */ public Rectangle getBounds(TreePath path, Rectangle rect) { + if (path == null) + return null; if (dirty) update(); Object last = path.getLastPathComponent(); NodeRecord r = (NodeRecord) nodes.get(last); if (r == null) - // This node is not visible. - return new Rectangle(); + // This node is not visible. + { + rect.x = rect.y = rect.width = rect.height = 0; + } else { if (r.bounds == null) { - Rectangle dim = getNodeDimensions(last, r.row, r.depth, r.isExpanded, - rect); + Rectangle dim = getNodeDimensions(last, r.row, r.depth, + r.isExpanded, rect); r.bounds = dim; } - return r.bounds; + + rect.setRect(r.bounds); } + return rect; } /** @@ -330,6 +386,9 @@ public class FixedHeightLayoutCache */ public int getRowForPath(TreePath path) { + if (path == null) + return -1; + if (dirty) update(); NodeRecord r = (NodeRecord) nodes.get(path.getLastPathComponent()); @@ -351,28 +410,59 @@ public class FixedHeightLayoutCache if (dirty) update(); - // We do not need to iterate because all rows have the same height. - int row = y / rowHeight; - if (row < 0) - row = 0; - if (row > getRowCount()) - row = getRowCount() - 1; + // As the rows have arbitrary height, we need to iterate. + NodeRecord best = null; + NodeRecord r; + Enumeration en = nodes.elements(); - if (row < 0) - return null; // Empty tree - nothing to return. - - Object node = row2node.get(new Integer(row)); - NodeRecord nr = (NodeRecord) nodes.get(node); - return nr.getPath(); + int dist = Integer.MAX_VALUE; + + while (en.hasMoreElements() && dist > 0) + { + r = (NodeRecord) en.nextElement(); + if (best == null) + { + best = r; + dist = distance(r.getBounds(), x, y); + } + else + { + int rr = distance(r.getBounds(), x, y); + if (rr < dist) + { + best = r; + dist = rr; + } + } + } + + if (best == null) + return null; + else + return best.getPath(); } + + /** + * Get the closest distance from this point till the given rectangle. Only + * vertical distance is taken into consideration. + */ + int distance(Rectangle r, int x, int y) + { + if (y < r.y) + return r.y - y; + else if (y > r.y + r.height) + return y - (r.y + r.height); + else + return 0; + } /** - * Get the number of the visible childs for the given tree path. If the - * node is not expanded, 0 is returned. Otherwise, the number of children - * is obtained from the model as the number of children for the last path + * Get the number of the visible childs for the given tree path. If the node + * is not expanded, 0 is returned. Otherwise, the number of children is + * obtained from the model as the number of children for the last path * component. * - * @param path the tree path + * @param path the tree path * @return int the number of the visible childs (for row). */ public int getVisibleChildCount(TreePath path) @@ -466,7 +556,9 @@ public class FixedHeightLayoutCache */ public void setModel(TreeModel newModel) { - super.setModel(newModel); + treeModel = newModel; + // The root node is expanded by default. + expanded.add(treeModel.getRoot()); dirty = true; } @@ -484,32 +576,53 @@ public class FixedHeightLayoutCache } /** - * Get the node dimensions. If the NodeDimensions are not set, this method - * calculates dimensions assuming the fixed row height. - * - * @param value the last node in the path - * @param row the node row - * @param depth the indentation depth - * @param expanded true if this node is expanded, false otherwise - * @param bounds the area where the tree is displayed - */ - protected Rectangle getNodeDimensions(Object value, int row, int depth, - boolean expanded, Rectangle bounds) + * Get the sum of heights for all rows. + */ + public int getPreferredHeight() { - if (nodeDimensions != null) - return nodeDimensions.getNodeDimensions(value, row, depth, expanded, - bounds); - else + if (dirty) + update(); + totalHeight = 0; + Enumeration en = nodes.elements(); + while (en.hasMoreElements()) { - Rectangle r = new Rectangle(bounds); - - int indent = depth * UIManager.getInt("Tree.rightChildIndent"); + NodeRecord nr = (NodeRecord) en.nextElement(); + Rectangle r = nr.getBounds(); + totalHeight += r.height; + } + return totalHeight; + } - r.x = indent; - r.y = row * getRowHeight(); - r.width = bounds.width = r.x; - r.height = getRowHeight(); - return r; + /** + * Get the maximal width. + */ + public int getPreferredWidth(Rectangle value) + { + if (dirty) + update(); + + maximalWidth = 0; + Enumeration en = nodes.elements(); + while (en.hasMoreElements()) + { + NodeRecord nr = (NodeRecord) en.nextElement(); + Rectangle r = nr.getBounds(); + if (r.x + r.width > maximalWidth) + maximalWidth = r.x + r.width; } + return maximalWidth; + } + + /** + * Returns true if this layout supposes that all rows have the fixed + * height. + * + * @return boolean true if all rows in the tree must have the fixed + * height (true by default). + */ + protected boolean isFixedRowHeight() + { + return true; } + } diff --git a/javax/swing/tree/TreePath.java b/javax/swing/tree/TreePath.java index 89f36f0ff..4671c4be5 100644 --- a/javax/swing/tree/TreePath.java +++ b/javax/swing/tree/TreePath.java @@ -57,6 +57,11 @@ public class TreePath implements Serializable * assumes that the TreePath is immutable, so it is marked final here. */ private final Object[] path; + + /** + * The parent path (to be reused). + */ + private transient TreePath parentPath; /** @@ -294,7 +299,12 @@ public class TreePath implements Serializable // is what the JDK does. if (path.length <= 1) return null; - - return new TreePath(this.getPath(), path.length - 1); + + // Reuse the parent path, if possible. The parent path is requested + // during the tree repainting, so reusing generates a lot less garbage. + if (parentPath == null) + parentPath = new TreePath(this.getPath(), path.length - 1); + + return parentPath; } } diff --git a/javax/swing/tree/VariableHeightLayoutCache.java b/javax/swing/tree/VariableHeightLayoutCache.java index 3758a4fc0..302fb0e45 100644 --- a/javax/swing/tree/VariableHeightLayoutCache.java +++ b/javax/swing/tree/VariableHeightLayoutCache.java @@ -115,31 +115,38 @@ public class VariableHeightLayoutCache private TreePath path; /** - * Get the path for this node. The derived class is returned, - * making check for the last child of some parent easier. + * Get the path for this node. The derived class is returned, making check + * for the last child of some parent easier. */ TreePath getPath() { - boolean lastChild = false; - if (parent!=null) + if (path == null) { - int nc = treeModel.getChildCount(parent); - if (nc > 0) + boolean lastChild = false; + if (parent != null) { - int n = treeModel.getIndexOfChild(parent, node); - if (n == nc-1) - lastChild = true; + int nc = treeModel.getChildCount(parent); + if (nc > 0) + { + int n = treeModel.getIndexOfChild(parent, node); + if (n == nc - 1) + lastChild = true; + } } - } - if (path == null) - { + LinkedList lpath = new LinkedList(); NodeRecord rp = this; while (rp != null) { lpath.addFirst(rp.node); if (rp.parent != null) - rp = (NodeRecord) nodes.get(rp.parent); + { + Object parent = rp.parent; + rp = (NodeRecord) nodes.get(parent); + // Add the root node, even if it is not visible. + if (rp == null) + lpath.addFirst(parent); + } else rp = null; } @@ -157,8 +164,7 @@ public class VariableHeightLayoutCache // not known. To work around this, it is assumed near infinitely large. if (bounds==null) bounds = getNodeDimensions(node, row, depth, isExpanded, - new Rectangle(Integer.MAX_VALUE/2, - Integer.MAX_VALUE/2)); + new Rectangle()); return bounds; } } @@ -238,7 +244,7 @@ public class VariableHeightLayoutCache for (int i = 0; i < sc; i++) { Object child = treeModel.getChild(root, i); - countRows(child, root, 1); + countRows(child, root, 0); } } dirty = false; @@ -255,8 +261,8 @@ public class VariableHeightLayoutCache NodeRecord nr = new NodeRecord(n.intValue(), depth, node, parent); nodes.put(node, nr); - // For expanded nodes and for the root node. - if (expanded.contains(node) || parent == null) + // For expanded nodes + if (expanded.contains(node)) { int sc = treeModel.getChildCount(node); int deeper = depth+1; @@ -326,6 +332,8 @@ public class VariableHeightLayoutCache */ public Rectangle getBounds(TreePath path, Rectangle rect) { + if (path == null) + return null; if (dirty) update(); Object last = path.getLastPathComponent(); @@ -377,6 +385,8 @@ public class VariableHeightLayoutCache */ public int getRowForPath(TreePath path) { + if (path == null) + return -1; if (dirty) update(); NodeRecord r = (NodeRecord) nodes.get(path.getLastPathComponent()); @@ -545,6 +555,8 @@ public class VariableHeightLayoutCache public void setModel(TreeModel newModel) { treeModel = newModel; + // The root node is expanded by default. + expanded.add(treeModel.getRoot()); dirty = true; } diff --git a/javax/xml/datatype/DatatypeFactory.java b/javax/xml/datatype/DatatypeFactory.java index c5bc96ed2..14f507416 100644 --- a/javax/xml/datatype/DatatypeFactory.java +++ b/javax/xml/datatype/DatatypeFactory.java @@ -37,15 +37,23 @@ exception statement from your version. */ package javax.xml.datatype; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; import java.math.BigDecimal; import java.math.BigInteger; import java.util.GregorianCalendar; +import java.util.Iterator; +import java.util.Properties; +import gnu.classpath.ServiceFactory; /** * Factory class to create new datatype objects mapping XML to and from Java * objects. * - * @author (a href='mailto:dog@gnu.org'>Chris Burdess