diff options
Diffstat (limited to 'libjava/classpath/javax/swing/plaf/basic')
52 files changed, 6693 insertions, 4319 deletions
diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java b/libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java index 836ef223494..69d4415371f 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java @@ -39,42 +39,30 @@ exception statement from your version. */ package javax.swing.plaf.basic; import java.awt.Color; -import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics; -import java.awt.Insets; import java.awt.Polygon; import java.awt.Rectangle; +import javax.swing.ButtonModel; import javax.swing.JButton; import javax.swing.SwingConstants; -import javax.swing.border.Border; /** - * This class draws simple arrow buttons for the Basic Look and Feel. + * A button that displays an arrow (triangle) that points {@link #NORTH}, + * {@link #SOUTH}, {@link #EAST} or {@link #WEST}. This button is used by + * the {@link BasicComboBoxUI} class. + * + * @see BasicComboBoxUI#createArrowButton */ public class BasicArrowButton extends JButton implements SwingConstants { - /** The default size of the Arrow buttons. */ - private static int defaultSize = 12; - /** The Polygon that points up. */ - private static Polygon upIcon = new Polygon(new int[] { 0, 5, 9 }, - new int[] { 7, 2, 7 }, 3); - - /** The Polygon that points down. */ - private static Polygon downIcon = new Polygon(new int[] { 1, 5, 9 }, - new int[] { 3, 7, 3 }, 3); - - /** The Polygon that points left. */ - private static Polygon leftIcon = new Polygon(new int[] { 7, 3, 7 }, - new int[] { 1, 5, 9 }, 3); - - /** The Polygon that points right. */ - private static Polygon rightIcon = new Polygon(new int[] { 3, 7, 3 }, - new int[] { 1, 5, 9 }, 3); - - /** The direction to point in. */ + /** + * The direction that the arrow points. + * + * @see #getDirection() + */ protected int direction; /** @@ -89,7 +77,7 @@ public class BasicArrowButton extends JButton implements SwingConstants * edges of the button. * This is package-private to avoid an accessor method. */ - transient Color darkShadow = Color.DARK_GRAY; + transient Color darkShadow = new Color(102, 102, 102); /** * The top and left edges of the button. @@ -97,51 +85,15 @@ public class BasicArrowButton extends JButton implements SwingConstants */ transient Color highlight = Color.WHITE; - /** The border around the ArrowButton. */ - private transient Border buttonBorder = new Border() - { - public Insets getBorderInsets(Component c) - { - return new Insets(2, 2, 2, 2); - } - - public boolean isBorderOpaque() - { - return true; - } - - public void paintBorder(Component c, Graphics g, int x, int y, int w, - int h) - { - Color saved = g.getColor(); - g.setColor(highlight); - - g.drawLine(x + 1, y + 1, x + w - 1, y + 1); - g.drawLine(x + 1, y + 1, x + 1, y + h - 1); - - g.setColor(shadow); - - g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1); - g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1); - - g.setColor(darkShadow); - - g.drawLine(x, y + h, x + w, y + h); - g.drawLine(x + w, y, x + w, y + h); - - g.setColor(saved); - } - }; - /** - * Creates a new BasicArrowButton object. + * Creates a new <code>BasicArrowButton</code> object. * - * @param direction The direction the arrow points in. + * @param direction The direction the arrow points in (one of: + * {@link #NORTH}, {@link #SOUTH}, {@link #EAST} and {@link #WEST}). */ public BasicArrowButton(int direction) { super(); - setBorder(buttonBorder); setDirection(direction); } @@ -149,7 +101,8 @@ public class BasicArrowButton extends JButton implements SwingConstants * Creates a new BasicArrowButton object with the given colors and * direction. * - * @param direction The direction to point in. + * @param direction The direction to point in (one of: + * {@link #NORTH}, {@link #SOUTH}, {@link #EAST} and {@link #WEST}). * @param background The background color. * @param shadow The shadow color. * @param darkShadow The dark shadow color. @@ -166,9 +119,10 @@ public class BasicArrowButton extends JButton implements SwingConstants } /** - * This method returns whether the focus can traverse to this component. + * Returns whether the focus can traverse to this component. This method + * always returns <code>false</code>. * - * @return Whether the focus can traverse to this component. + * @return <code>false</code>. */ public boolean isFocusTraversable() { @@ -176,7 +130,8 @@ public class BasicArrowButton extends JButton implements SwingConstants } /** - * This method returns the direction of the arrow. + * Returns the direction of the arrow (one of: {@link #NORTH}, + * {@link #SOUTH}, {@link #EAST} and {@link #WEST}). * * @return The direction of the arrow. */ @@ -186,9 +141,10 @@ public class BasicArrowButton extends JButton implements SwingConstants } /** - * This method changes the direction of the arrow. + * Sets the direction of the arrow. * - * @param dir The new direction of the arrow. + * @param dir The new direction of the arrow (one of: {@link #NORTH}, + * {@link #SOUTH}, {@link #EAST} and {@link #WEST}). */ public void setDirection(int dir) { @@ -196,7 +152,7 @@ public class BasicArrowButton extends JButton implements SwingConstants } /** - * This method paints the arrow button. The painting is delegated to the + * Paints the arrow button. The painting is delegated to the * paintTriangle method. * * @param g The Graphics object to paint with. @@ -204,147 +160,257 @@ public class BasicArrowButton extends JButton implements SwingConstants public void paint(Graphics g) { super.paint(g); - Insets insets = getInsets(); Rectangle bounds = getBounds(); - int x = insets.left - + (bounds.width - insets.left - insets.right - defaultSize) / 2; - int y = insets.top - + (bounds.height - insets.left - insets.right - defaultSize) / 2; - paintTriangle(g, x, y, defaultSize, direction, isEnabled()); + int size = bounds.height / 4; + int x = (bounds.width - size) / 2; + int y = (bounds.height - size) / 2; + ButtonModel m = getModel(); + if (m.isArmed()) + { + x++; + y++; + } + paintTriangle(g, x, y, size, direction, isEnabled()); } + /** The preferred size for the button. */ + private static final Dimension PREFERRED_SIZE = new Dimension(16, 16); + + /** The minimum size for the button. */ + private static final Dimension MINIMUM_SIZE = new Dimension(5, 5); + + /** The maximum size for the button. */ + private static final Dimension MAXIMUM_SIZE + = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + /** - * This method returns the preferred size of the arrow button. + * Returns the preferred size of the arrow button. * - * @return The preferred size. + * @return The preferred size (always 16 x 16). */ public Dimension getPreferredSize() { - Insets insets = getInsets(); - int w = defaultSize + insets.left + insets.right; - int h = defaultSize + insets.top + insets.bottom; - - return new Dimension(w, h); + return PREFERRED_SIZE; } /** - * This method returns the minimum size of the arrow button. + * Returns the minimum size of the arrow button. * - * @return The minimum size. + * @return The minimum size (always 5 x 5). */ public Dimension getMinimumSize() { - return getPreferredSize(); + return MINIMUM_SIZE; } /** - * This method returns the maximum size of the arrow button. + * Returns the maximum size of the arrow button. * * @return The maximum size. */ public Dimension getMaximumSize() { - return getPreferredSize(); + return MAXIMUM_SIZE; } /** - * The method paints a triangle with the given size and direction at the - * given x and y coordinates. + * Paints a triangle with the given size, location and direction. It is + * difficult to explain the rationale behind the positioning of the triangle + * relative to the given (x, y) position - by trial and error we seem to + * match the behaviour of the reference implementation (which is missing a + * specification for this method). * - * @param g The Graphics object to paint with. - * @param x The x coordinate to paint at. - * @param y The y coordinate to paint at. - * @param size The size of the icon. - * @param direction The direction of the icon. - * @param isEnabled Whether it is enabled. + * @param g the graphics device. + * @param x the x-coordinate for the triangle's location. + * @param y the y-coordinate for the triangle's location. + * @param size the arrow size (depth). + * @param direction the direction of the arrow (one of: {@link #NORTH}, + * {@link #SOUTH}, {@link #EAST} and {@link #WEST}). + * @param isEnabled if <code>true</code> the arrow is drawn in the enabled + * state, otherwise it is drawn in the disabled state. */ public void paintTriangle(Graphics g, int x, int y, int size, int direction, boolean isEnabled) { - Polygon arrow = null; - switch (direction) - { - case NORTH: - arrow = upIcon; - break; - case SOUTH: - arrow = downIcon; - break; - case EAST: - case RIGHT: - arrow = rightIcon; - break; - case WEST: - case LEFT: - arrow = leftIcon; - break; - } - - int[] xPoints = arrow.xpoints; - int[] yPoints = arrow.ypoints; - int x1; - int y1; - int x2; - int y2; - x1 = y1 = x2 = y2 = 0; - - if (size != defaultSize) - { - float scale = size * 1f / defaultSize; - for (int i = 0; i < 3; i++) - { - xPoints[i] *= scale; - yPoints[i] *= scale; - } - } - g.translate(x, y); - + Color savedColor = g.getColor(); switch (direction) { case NORTH: - x1 = xPoints[0] + 2; - y1 = yPoints[0]; - y2 = y1; - x2 = xPoints[2] - 1; - break; + paintTriangleNorth(g, x, y, size, isEnabled); + break; case SOUTH: - x1 = xPoints[1]; - y1 = yPoints[1] + 1; - x2 = xPoints[2] - 1; - y2 = yPoints[2]; - break; + paintTriangleSouth(g, x, y, size, isEnabled); + break; case LEFT: case WEST: - x1 = xPoints[0] + 1; - y1 = yPoints[0] + 1; - x2 = x1; - y2 = yPoints[2] + 1; - break; + paintTriangleWest(g, x, y, size, isEnabled); + break; case RIGHT: case EAST: - x1 = xPoints[2]; - y1 = yPoints[2] + 1; - x2 = xPoints[1] - 1; - y2 = yPoints[1] + 1; - break; + paintTriangleEast(g, x, y, size, isEnabled); + break; } - Color saved = g.getColor(); - + g.setColor(savedColor); + } + + /** + * Paints an upward-pointing triangle. This method is called by the + * {@link #paintTriangle(Graphics, int, int, int, int, boolean)} method. + * + * @param g the graphics device. + * @param x the x-coordinate for the anchor point. + * @param y the y-coordinate for the anchor point. + * @param size the arrow size (depth). + * @param isEnabled if <code>true</code> the arrow is drawn in the enabled + * state, otherwise it is drawn in the disabled state. + */ + private void paintTriangleNorth(Graphics g, int x, int y, int size, + boolean isEnabled) + { + int tipX = x + (size - 2) / 2; + int tipY = y; + int baseX1 = tipX - (size - 1); + int baseX2 = tipX + (size - 1); + int baseY = y + (size - 1); + Polygon triangle = new Polygon(); + triangle.addPoint(tipX, tipY); + triangle.addPoint(baseX1, baseY); + triangle.addPoint(baseX2, baseY); if (isEnabled) - { - g.setColor(Color.DARK_GRAY); - - if (arrow != null) - g.fillPolygon(xPoints, yPoints, 3); - } + { + g.setColor(Color.DARK_GRAY); + g.fillPolygon(triangle); + g.drawPolygon(triangle); + } else - { - g.setColor(Color.GRAY); - g.fillPolygon(xPoints, yPoints, 3); - g.setColor(Color.WHITE); - g.drawLine(x1, y1, x2, y2); - } - g.setColor(saved); - g.translate(-x, -y); + { + g.setColor(Color.GRAY); + g.fillPolygon(triangle); + g.drawPolygon(triangle); + g.setColor(Color.WHITE); + g.drawLine(baseX1 + 1, baseY + 1, baseX2 + 1, baseY + 1); + } + } + + /** + * Paints an downward-pointing triangle. This method is called by the + * {@link #paintTriangle(Graphics, int, int, int, int, boolean)} method. + * + * @param g the graphics device. + * @param x the x-coordinate for the anchor point. + * @param y the y-coordinate for the anchor point. + * @param size the arrow size (depth). + * @param isEnabled if <code>true</code> the arrow is drawn in the enabled + * state, otherwise it is drawn in the disabled state. + */ + private void paintTriangleSouth(Graphics g, int x, int y, int size, + boolean isEnabled) + { + int tipX = x + (size - 2) / 2; + int tipY = y + (size - 1); + int baseX1 = tipX - (size - 1); + int baseX2 = tipX + (size - 1); + int baseY = y; + Polygon triangle = new Polygon(); + triangle.addPoint(tipX, tipY); + triangle.addPoint(baseX1, baseY); + triangle.addPoint(baseX2, baseY); + if (isEnabled) + { + g.setColor(Color.DARK_GRAY); + g.fillPolygon(triangle); + g.drawPolygon(triangle); + } + else + { + g.setColor(Color.GRAY); + g.fillPolygon(triangle); + g.drawPolygon(triangle); + g.setColor(Color.WHITE); + g.drawLine(tipX + 1, tipY, baseX2, baseY + 1); + g.drawLine(tipX + 1, tipY + 1, baseX2 + 1, baseY + 1); + } + } + + /** + * Paints a right-pointing triangle. This method is called by the + * {@link #paintTriangle(Graphics, int, int, int, int, boolean)} method. + * + * @param g the graphics device. + * @param x the x-coordinate for the anchor point. + * @param y the y-coordinate for the anchor point. + * @param size the arrow size (depth). + * @param isEnabled if <code>true</code> the arrow is drawn in the enabled + * state, otherwise it is drawn in the disabled state. + */ + private void paintTriangleEast(Graphics g, int x, int y, int size, + boolean isEnabled) + { + int tipX = x + (size - 1); + int tipY = y + (size - 2) / 2; + int baseX = x; + int baseY1 = tipY - (size - 1); + int baseY2 = tipY + (size - 1); + + Polygon triangle = new Polygon(); + triangle.addPoint(tipX, tipY); + triangle.addPoint(baseX, baseY1); + triangle.addPoint(baseX, baseY2); + if (isEnabled) + { + g.setColor(Color.DARK_GRAY); + g.fillPolygon(triangle); + g.drawPolygon(triangle); + } + else + { + g.setColor(Color.GRAY); + g.fillPolygon(triangle); + g.drawPolygon(triangle); + g.setColor(Color.WHITE); + g.drawLine(baseX + 1, baseY2, tipX, tipY + 1); + g.drawLine(baseX + 1, baseY2 + 1, tipX + 1, tipY + 1); + } + } + + /** + * Paints a left-pointing triangle. This method is called by the + * {@link #paintTriangle(Graphics, int, int, int, int, boolean)} method. + * + * @param g the graphics device. + * @param x the x-coordinate for the anchor point. + * @param y the y-coordinate for the anchor point. + * @param size the arrow size (depth). + * @param isEnabled if <code>true</code> the arrow is drawn in the enabled + * state, otherwise it is drawn in the disabled state. + */ + private void paintTriangleWest(Graphics g, int x, int y, int size, + boolean isEnabled) + { + int tipX = x; + int tipY = y + (size - 2) / 2; + int baseX = x + (size - 1); + int baseY1 = tipY - (size - 1); + int baseY2 = tipY + (size - 1); + + Polygon triangle = new Polygon(); + triangle.addPoint(tipX, tipY); + triangle.addPoint(baseX, baseY1); + triangle.addPoint(baseX, baseY2); + if (isEnabled) + { + g.setColor(Color.DARK_GRAY); + g.fillPolygon(triangle); + g.drawPolygon(triangle); + } + else + { + g.setColor(Color.GRAY); + g.fillPolygon(triangle); + g.drawPolygon(triangle); + g.setColor(Color.WHITE); + g.drawLine(baseX + 1, baseY1 + 1, baseX + 1, baseY2 + 1); + } } + } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java b/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java index e7d6e433877..cec7bec8501 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java @@ -806,9 +806,9 @@ public class BasicBorders */ public MarginBorder() { + // Nothing to do here. } - /** * Measures the width of this border. * @@ -1313,33 +1313,32 @@ public class BasicBorders * * @author Sascha Brawer (brawer@dandelis.ch) */ - public static class SplitPaneBorder - implements Border, UIResource + public static class SplitPaneBorder implements Border, UIResource { /** * Indicates that the top edge shall be not be painted - * by {@link #paintRect(java.awt.Graphics, int, int, int, int, int)}. + * by {@link #paintRect}. */ private static final int SUPPRESS_TOP = 1; /** * Indicates that the left edge shall be not be painted - * by {@link #paintRect(java.awt.Graphics, int, int, int, int, int)}. + * by {@link #paintRect}. */ private static final int SUPPRESS_LEFT = 2; /** * Indicates that the bottom edge shall be not be painted - * by {@link #paintRect(java.awt.Graphics, int, int, int, int, int)}. + * by {@link #paintRect}. */ private static final int SUPPRESS_BOTTOM = 4; /** * Indicates that the right edge shall be not be painted - * by {@link #paintRect(java.awt.Graphics, int, int, int, int, int)}. + * by {@link #paintRect}. */ private static final int SUPPRESS_RIGHT = 8; diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java b/libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java index 5349f524049..1fca694519f 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java @@ -55,9 +55,8 @@ import javax.swing.JComponent; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -public class BasicButtonListener - implements MouseListener, MouseMotionListener, FocusListener, - ChangeListener, PropertyChangeListener +public class BasicButtonListener implements MouseListener, MouseMotionListener, + FocusListener, ChangeListener, PropertyChangeListener { public BasicButtonListener(AbstractButton b) { @@ -66,10 +65,12 @@ public class BasicButtonListener public void propertyChange(PropertyChangeEvent e) { + // TODO: What should be done here, if anything? } protected void checkOpacity(AbstractButton b) { + // TODO: What should be done here? } public void focusGained(FocusEvent e) @@ -129,18 +130,22 @@ public class BasicButtonListener public void stateChanged(ChangeEvent e) { + // TODO: What should be done here, if anything? } public void mouseMoved(MouseEvent e) { + // TODO: What should be done here, if anything? } public void mouseDragged(MouseEvent e) { + // TODO: What should be done here, if anything? } public void mouseClicked(MouseEvent e) { + // TODO: What should be done here, if anything? } /** diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java index 6c80f14b6fc..2d3dbd350e0 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java @@ -38,7 +38,6 @@ exception statement from your version. */ package javax.swing.plaf.basic; -import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; @@ -49,13 +48,19 @@ import javax.swing.AbstractButton; import javax.swing.ButtonModel; import javax.swing.Icon; import javax.swing.InputMap; +import javax.swing.JButton; import javax.swing.JComponent; +import javax.swing.LookAndFeel; import javax.swing.SwingUtilities; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.plaf.ButtonUI; import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.UIResource; +/** + * A UI delegate for the {@link JButton} component. + */ public class BasicButtonUI extends ButtonUI { /** @@ -72,13 +77,11 @@ public class BasicButtonUI extends ButtonUI private int textShiftOffset; - private Color focusColor; - /** * Factory method to create an instance of BasicButtonUI for a given * {@link JComponent}, which should be an {@link AbstractButton}. * - * @param c The component to create a UI got + * @param c The component. * * @return A new UI capable of drawing the component */ @@ -87,21 +90,46 @@ public class BasicButtonUI extends ButtonUI return new BasicButtonUI(); } + /** + * Returns the default gap between the button's text and icon (in pixels). + * + * @param b the button (ignored). + * + * @return The gap. + */ public int getDefaultTextIconGap(AbstractButton b) { return defaultTextIconGap; } + /** + * Sets the text shift offset to zero. + * + * @see #setTextShiftOffset() + */ protected void clearTextShiftOffset() { textShiftOffset = 0; } + /** + * Returns the text shift offset. + * + * @return The text shift offset. + * + * @see #clearTextShiftOffset() + * @see #setTextShiftOffset() + */ protected int getTextShiftOffset() { return textShiftOffset; } + /** + * Sets the text shift offset to the value in {@link #defaultTextShiftOffset}. + * + * @see #clearTextShiftOffset() + */ protected void setTextShiftOffset() { textShiftOffset = defaultTextShiftOffset; @@ -118,23 +146,33 @@ public class BasicButtonUI extends ButtonUI return "Button."; } + /** + * Installs the default settings. + * + * @param b the button (<code>null</code> not permitted). + */ protected void installDefaults(AbstractButton b) { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); String prefix = getPropertyPrefix(); - focusColor = defaults.getColor(prefix + "focus"); - b.setForeground(defaults.getColor(prefix + "foreground")); - b.setBackground(defaults.getColor(prefix + "background")); - b.setMargin(defaults.getInsets(prefix + "margin")); - b.setBorder(defaults.getBorder(prefix + "border")); - b.setIconTextGap(defaults.getInt(prefix + "textIconGap")); + LookAndFeel.installColorsAndFont(b, prefix + "background", + prefix + "foreground", prefix + "font"); + LookAndFeel.installBorder(b, prefix + "border"); + b.setMargin(UIManager.getInsets(prefix + "margin")); + b.setIconTextGap(UIManager.getInt(prefix + "textIconGap")); b.setInputMap(JComponent.WHEN_FOCUSED, - (InputMap) defaults.get(prefix + "focusInputMap")); - b.setOpaque(true); + (InputMap) UIManager.get(prefix + "focusInputMap")); + b.setRolloverEnabled(UIManager.getBoolean(prefix + "rollover")); } + /** + * Removes the defaults added by {@link #installDefaults(AbstractButton)}. + * + * @param b the button (<code>null</code> not permitted). + */ protected void uninstallDefaults(AbstractButton b) { + if (b.getFont() instanceof UIResource) + b.setFont(null); b.setForeground(null); b.setBackground(null); b.setBorder(null); @@ -144,11 +182,25 @@ public class BasicButtonUI extends ButtonUI protected BasicButtonListener listener; + /** + * Creates and returns a new instance of {@link BasicButtonListener}. This + * method provides a hook to make it easy for subclasses to install a + * different listener. + * + * @param b the button. + * + * @return A new listener. + */ protected BasicButtonListener createButtonListener(AbstractButton b) { return new BasicButtonListener(b); } + /** + * Installs listeners for the button. + * + * @param b the button (<code>null</code> not permitted). + */ protected void installListeners(AbstractButton b) { listener = createButtonListener(b); @@ -159,6 +211,11 @@ public class BasicButtonUI extends ButtonUI b.addMouseMotionListener(listener); } + /** + * Uninstalls listeners for the button. + * + * @param b the button (<code>null</code> not permitted). + */ protected void uninstallListeners(AbstractButton b) { b.removeChangeListener(listener); @@ -215,12 +272,12 @@ public class BasicButtonUI extends ButtonUI return d; } - private static Icon currentIcon(AbstractButton b) + static Icon currentIcon(AbstractButton b) { Icon i = b.getIcon(); ButtonModel model = b.getModel(); - if (model.isPressed() && b.getPressedIcon() != null) + if (model.isPressed() && b.getPressedIcon() != null && b.isEnabled()) i = b.getPressedIcon(); else if (model.isRollover()) @@ -231,7 +288,7 @@ public class BasicButtonUI extends ButtonUI i = b.getRolloverIcon(); } - else if (b.isSelected()) + else if (b.isSelected() && b.isEnabled()) { if (b.isEnabled() && b.getSelectedIcon() != null) i = b.getSelectedIcon(); @@ -264,7 +321,10 @@ public class BasicButtonUI extends ButtonUI g.setFont(f); - SwingUtilities.calculateInnerArea(b, vr); + if (b.isBorderPainted()) + SwingUtilities.calculateInnerArea(b, vr); + else + vr = SwingUtilities.getLocalBounds(b); String text = SwingUtilities.layoutCompoundLabel(c, g.getFontMetrics(f), b.getText(), currentIcon(b), @@ -279,13 +339,11 @@ public class BasicButtonUI extends ButtonUI if ((b.getModel().isArmed() && b.getModel().isPressed()) || b.isSelected()) paintButtonPressed(g, b); - else - paintButtonNormal(g, vr, c); paintIcon(g, c, ir); if (text != null) paintText(g, b, tr, text); - if (b.isFocusOwner()) + if (b.isFocusOwner() && b.isFocusPainted()) paintFocus(g, b, vr, tr, ir); } @@ -331,44 +389,25 @@ public class BasicButtonUI extends ButtonUI /** * Paints the background area of an {@link AbstractButton} in the pressed - * state. This means filling the supplied area with the {@link - * pressedBackgroundColor}. + * state. This means filling the supplied area with a darker than normal + * background. * * @param g The graphics context to paint with * @param b The button to paint the state of */ protected void paintButtonPressed(Graphics g, AbstractButton b) { - if (b.isContentAreaFilled()) - { - Rectangle area = new Rectangle(); - SwingUtilities.calculateInnerArea(b, area); - g.setColor(b.getBackground().darker()); - g.fillRect(area.x, area.y, area.width, area.height); - } - } - - /** - * Paints the background area of an {@link AbstractButton} in the normal, - * non-pressed state. This means filling the supplied area with the - * {@link normalBackgroundColor}. - * - * @param g The graphics context to paint with - * @param area The area in which to paint - * @param b The component to paint the state of - */ - private void paintButtonNormal(Graphics g, Rectangle area, JComponent b) - { - if (((AbstractButton)b).isContentAreaFilled() && b.isOpaque()) + if (b.isContentAreaFilled() && b.isOpaque()) { - g.setColor(b.getBackground()); + Rectangle area = new Rectangle(); + SwingUtilities.calculateInnerArea(b, area); + g.setColor(UIManager.getColor(getPropertyPrefix() + "shadow")); g.fillRect(area.x, area.y, area.width, area.height); } } /** - * Paints the "text" property of an {@link AbstractButton}, using the - * {@link textColor} color. + * Paints the "text" property of an {@link AbstractButton}. * * @param g The graphics context to paint with * @param c The component to paint the state of @@ -382,8 +421,7 @@ public class BasicButtonUI extends ButtonUI } /** - * Paints the "text" property of an {@link AbstractButton}, using the - * {@link textColor} color. + * Paints the "text" property of an {@link AbstractButton}. * * @param g The graphics context to paint with * @param b The button to paint the state of @@ -401,15 +439,15 @@ public class BasicButtonUI extends ButtonUI if (b.isEnabled()) { - g.setColor(b.getForeground()); - g.drawString(text, textRect.x, textRect.y + fm.getAscent()); + g.setColor(b.getForeground()); + g.drawString(text, textRect.x, textRect.y + fm.getAscent()); } else { - g.setColor(b.getBackground().brighter()); - g.drawString(text, textRect.x, textRect.y + fm.getAscent()); - g.setColor(b.getBackground().darker()); - g.drawString(text, textRect.x + 1, textRect.y + fm.getAscent() + 1); + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + String prefix = getPropertyPrefix(); + g.setColor(defaults.getColor(prefix + "disabledText")); + g.drawString(text, textRect.x, textRect.y + fm.getAscent()); } } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java index 945aea53dc3..95e0dc98257 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java @@ -53,6 +53,15 @@ import javax.swing.plaf.ComponentUI; */ public class BasicCheckBoxMenuItemUI extends BasicMenuItemUI { + + /** + * Creates a new BasicCheckBoxMenuItemUI object. + */ + public BasicCheckBoxMenuItemUI() + { + super(); + } + /** * Factory method to create a BasicCheckBoxMenuItemUI for the given {@link * JComponent}, which should be a JCheckBoxMenuItem @@ -77,18 +86,6 @@ public class BasicCheckBoxMenuItemUI extends BasicMenuItemUI } /** - * This method installs the defaults that are defined in the Basic look and - * feel for this JRadioButtonMenuItem - */ - protected void installDefaults() - { - super.installDefaults(); - - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - checkIcon = defaults.getIcon("CheckBoxMenuItem.checkIcon"); - } - - /** * DOCUMENT ME! * * @param item DOCUMENT ME! @@ -100,5 +97,7 @@ public class BasicCheckBoxMenuItemUI extends BasicMenuItemUI MenuElement[] path, MenuSelectionManager manager) { + // TODO: May not be implemented properly. + item.processMouseEvent(e, path, manager); } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java index 4e6d3815453..5a872ae6368 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java @@ -47,8 +47,7 @@ import javax.swing.JColorChooser; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JTabbedPane; -import javax.swing.UIDefaults; -import javax.swing.UIManager; +import javax.swing.LookAndFeel; import javax.swing.colorchooser.AbstractColorChooserPanel; import javax.swing.colorchooser.ColorChooserComponentFactory; import javax.swing.event.ChangeEvent; @@ -243,12 +242,21 @@ public class BasicColorChooserUI extends ColorChooserUI { uninstallListeners(); uninstallDefaults(); + uninstallDefaultChoosers(); pane = null; chooser = null; } /** + * Uninstalls the default color choosers that have been installed by this UI. + */ + protected void uninstallDefaultChoosers() + { + defaultChoosers = null; + } + + /** * This method installs the preview panel for the JColorChooser. */ protected void installPreviewPanel() @@ -281,11 +289,9 @@ public class BasicColorChooserUI extends ColorChooserUI */ protected void installDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - chooser.setFont(defaults.getFont("ColorChooser.font")); - chooser.setForeground(defaults.getColor("ColorChooser.foreground")); - chooser.setBackground(defaults.getColor("ColorChooser.background")); + LookAndFeel.installColorsAndFont(chooser, "ColorChooser.background", + "ColorChooser.foreground", + "ColorChooser.font"); } /** diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java index dd867f0dc55..831dde8c336 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java @@ -45,35 +45,34 @@ import java.awt.event.FocusListener; import javax.swing.ComboBoxEditor; import javax.swing.JTextField; -import javax.swing.border.EmptyBorder; /** - * This is a component that is responsible for displaying/editting selected - * item in comboBox. By default, the JTextField is returned as - * BasicComboBoxEditor. + * An editor used by the {@link BasicComboBoxUI} class. This editor uses a + * {@link JTextField} as the editor component. * * @author Olga Rodimina */ public class BasicComboBoxEditor extends Object implements ComboBoxEditor, FocusListener { + /** The editor component. */ protected JTextField editor; /** - * Creates a new BasicComboBoxEditor object. + * Creates a new <code>BasicComboBoxEditor</code> instance. */ public BasicComboBoxEditor() { editor = new JTextField(); - editor.setBorder(new EmptyBorder(1, 1, 1, 1)); + editor.setBorder(null); + editor.setColumns(9); } /** - * This method returns textfield that will be used by the combo box to - * display/edit currently selected item in the combo box. + * Returns the component that will be used by the combo box to display and + * edit the currently selected item in the combo box. * - * @return textfield that will be used by the combo box to display/edit - * currently selected item + * @return The editor component, which is a {@link JTextField} in this case. */ public Component getEditorComponent() { @@ -98,15 +97,18 @@ public class BasicComboBoxEditor extends Object implements ComboBoxEditor, } /** - * This method returns item that is currently editable. + * Returns the text from the editor component. * - * @return item in the combo box that is currently editable + * @return The text from the editor component. */ public Object getItem() { return editor.getText(); } + /** + * Selects all the text in the editor component. + */ public void selectAll() { editor.selectAll(); @@ -136,8 +138,8 @@ public class BasicComboBoxEditor extends Object implements ComboBoxEditor, } /** - * This method adds actionListener to the editor. If the user will edit - * currently selected item in the textfield and pressEnter, then action + * Adds an {@link ActionListener} to the editor component. If the user will + * edit currently selected item in the textfield and pressEnter, then action * will be performed. The actionPerformed of this ActionListener should * change the selected item of the comboBox to the newly editted selected * item. @@ -147,27 +149,32 @@ public class BasicComboBoxEditor extends Object implements ComboBoxEditor, */ public void addActionListener(ActionListener l) { - // FIXME: Need to implement + editor.addActionListener(l); } /** - * This method removes actionListener from the textfield. + * Removes the {@link ActionListener} from the editor component. * - * @param l the ActionListener to remove from the textfield. + * @param l the listener to remove. */ public void removeActionListener(ActionListener l) { - // FIXME: Need to implement + editor.removeActionListener(l); } + /** + * A subclass of {@link BasicComboBoxEditor} that implements the + * {@link UIResource} interface. + */ public static class UIResource extends BasicComboBoxEditor implements javax.swing.plaf.UIResource { /** - * Creates a new UIResource object. + * Creates a new <code>BasicComboBoxEditor.UIResource</code> instance. */ public UIResource() { + // Nothing to do here. } } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java index e4fbb8352a9..8115605b77a 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java @@ -1,5 +1,5 @@ /* BasicComboBoxRenderer.java -- - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -40,36 +40,39 @@ package javax.swing.plaf.basic; import java.awt.Component; import java.awt.Dimension; +import java.awt.FontMetrics; import java.io.Serializable; +import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.ListCellRenderer; import javax.swing.SwingConstants; -import javax.swing.UIDefaults; -import javax.swing.UIManager; +import javax.swing.SwingUtilities; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; /** - * This class is renderer for the combo box. + * A renderer for a {@link JComboBox}. * * @author Olga Rodimina */ -public class BasicComboBoxRenderer extends JLabel implements ListCellRenderer, - Serializable +public class BasicComboBoxRenderer + extends JLabel + implements ListCellRenderer, Serializable { /** - * This border is used whenever renderer doesn't have a focus. + * A shared border instance for all renderers. */ protected static Border noFocusBorder = new EmptyBorder(0, 0, 0, 0); /** - * Creates a new BasicComboBoxRenderer object. + * Creates a new <code>BasicComboBoxRenderer</code> object. */ public BasicComboBoxRenderer() { setHorizontalAlignment(SwingConstants.LEFT); + setBorder(noFocusBorder); } /** @@ -83,7 +86,8 @@ public class BasicComboBoxRenderer extends JLabel implements ListCellRenderer, } /** - * getListCellRendererComponent + * Returns a component that has been configured to display the given + * <code>value</code>. * * @param list List of items for which to the background and foreground * colors @@ -100,43 +104,59 @@ public class BasicComboBoxRenderer extends JLabel implements ListCellRenderer, boolean cellHasFocus) { String s = value.toString(); - setText(s); + + // String maybe larger than comboBox. + FontMetrics fm = getToolkit().getFontMetrics(list.getFont()); + int strWidth = SwingUtilities.computeStringWidth(fm, s); + int cbWidth = getSize().width; + if (cbWidth != 0 && strWidth > cbWidth) + { + char[] str = s.toCharArray(); + int currWidth = 0; + int i = 0; + String postStr = "... "; + cbWidth -= SwingUtilities.computeStringWidth(fm, postStr); + while (i < str.length && currWidth < cbWidth) + { + ++i; + currWidth = SwingUtilities.computeStringWidth(fm, new String(str, 0, i)); + } + setText(new String(str, 0, i) + postStr); + } + else + setText(s); + setOpaque(true); - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - if (isSelected) + if (isSelected || cellHasFocus) { - setBackground(list.getSelectionBackground()); - setForeground(list.getSelectionForeground()); + setBackground(list.getSelectionBackground()); + setForeground(list.getSelectionForeground()); } else { - setBackground(list.getBackground()); - setForeground(list.getForeground()); + setBackground(list.getBackground()); + setForeground(list.getForeground()); } setEnabled(list.isEnabled()); setFont(list.getFont()); - - // Use focusCellHighlightBorder when renderer has focus and - // noFocusBorder otherwise - if (cellHasFocus) - setBorder(UIManager.getBorder("List.focusCellHighlightBorder")); - else - setBorder(noFocusBorder); - return this; } + /** + * A subclass of {@link BasicComboBoxRenderer} that implements the + * {@link javax.swing.plaf.UIResource} interface. + */ public static class UIResource extends BasicComboBoxRenderer implements javax.swing.plaf.UIResource { /** - * Creates a new UIResource object. + * Creates a new <code>UIResource</code> object. */ public UIResource() { + // Nothing to do here. } } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java index 68e18a6ab01..464c8dd9f63 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java @@ -42,6 +42,8 @@ import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Insets; import java.awt.LayoutManager; @@ -69,15 +71,17 @@ import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JList; import javax.swing.ListCellRenderer; -import javax.swing.UIDefaults; +import javax.swing.LookAndFeel; +import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; import javax.swing.plaf.ComboBoxUI; import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.UIResource; /** - * UI Delegate for JComboBox + * A UI delegate for the {@link JComboBox} component. * * @author Olga Rodimina * @author Robert Schuster @@ -85,52 +89,54 @@ import javax.swing.plaf.ComponentUI; public class BasicComboBoxUI extends ComboBoxUI { /** - * This arrow button that is displayed in the rigth side of JComboBox. This - * button is used to hide and show combo box's list of items + * The arrow button that is displayed in the right side of JComboBox. This + * button is used to hide and show combo box's list of items. */ protected JButton arrowButton; /** - * The combo box for which this UI delegate is for + * The combo box represented by this UI delegate. */ protected JComboBox comboBox; /** - * Component that is responsible for displaying/editting selected item of - * the combo box. By default JTextField is used as an editor for the - * JComboBox + * The component that is responsible for displaying/editing the selected + * item of the combo box. + * + * @see BasicComboBoxEditor#getEditorComponent() */ protected Component editor; /** - * Listener listening to focus events occuring in the JComboBox + * A listener listening to focus events occurring in the {@link JComboBox}. */ protected FocusListener focusListener; /** - * tells whether JComboBox currently has focus + * A flag indicating whether JComboBox currently has the focus. */ protected boolean hasFocus; /** - * Listener listening to item events fired by the JComboBox + * A listener listening to item events fired by the {@link JComboBox}. */ protected ItemListener itemListener; /** - * KeyListener listening to key events that occur while JComboBox has focus + * A listener listening to key events that occur while {@link JComboBox} has + * the focus. */ protected KeyListener keyListener; /** - * MouseListener listening to mouse events occuring in the combo box + * A listener listening to mouse events occuring in the {@link JComboBox}. */ private MouseListener mouseListener; /** * List used when rendering selected item of the combo box. The selection - * and foreground colors for combo box renderer are configured from this - * list + * and foreground colors for combo box renderer are configured from this + * list. */ protected JList listBox; @@ -140,11 +146,14 @@ public class BasicComboBoxUI extends ComboBoxUI protected ListDataListener listDataListener; /** - * Popup list containing combo box's menu items + * Popup list containing the combo box's menu items. */ protected ComboPopup popup; + protected KeyListener popupKeyListener; + protected MouseListener popupMouseListener; + protected MouseMotionListener popupMouseMotionListener; /** @@ -152,30 +161,34 @@ public class BasicComboBoxUI extends ComboBoxUI */ protected PropertyChangeListener propertyChangeListener; + /** + * The button background. + * @see #installDefaults() + */ + private Color buttonBackground; + + /** + * The button shadow. + * @see #installDefaults() + */ + private Color buttonShadow; + /** - * Colors that are used to render selected item in the combo box. + * The button dark shadow. + * @see #installDefaults() */ - private Color shadow; - private Color darkShadow; - private Color highlight; - private Color lightHighlight; + private Color buttonDarkShadow; + + /** + * The button highlight. + * @see #installDefaults() + */ + private Color buttonHighlight; /* Size of the largest item in the comboBox * This is package-private to avoid an accessor method. */ - Dimension largestItemSize; - - // It seems that JComboBox doesn't have a border set explicitely. So we just - // paint the border everytime combo box is displayed. - - /* border insets for this JComboBox - * This is package-private to avoid an accessor method. */ - static final Insets borderInsets = new Insets(2, 2, 2, 2); - - // Width of the arrow button - // This is package-private to avoid an accessor method. - // FIXME: has wrong name for a constant. - static final int arrowButtonWidth = 15; + Dimension displaySize; // FIXME: This fields aren't used anywhere at this moment. protected Dimension cachedMinimumSize; @@ -183,19 +196,20 @@ public class BasicComboBoxUI extends ComboBoxUI protected boolean isMinimumSizeDirty; /** - * Creates a new BasicComboBoxUI object. + * Creates a new <code>BasicComboBoxUI</code> object. */ public BasicComboBoxUI() { + // Nothing to do here. } /** - * Factory method to create a BasicComboBoxUI for the given {@link - * JComponent}, which should be a {@link JComboBox}. + * A factory method to create a UI delegate for the given + * {@link JComponent}, which should be a {@link JComboBox}. * * @param c The {@link JComponent} a UI is being created for. * - * @return A BasicComboBoxUI for the {@link JComponent}. + * @return A UI delegate for the {@link JComponent}. */ public static ComponentUI createUI(JComponent c) { @@ -203,9 +217,11 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method installs the UI for the given JComponent. + * Installs the UI for the given {@link JComponent}. * - * @param c The JComponent to install a UI for. + * @param c the JComponent to install a UI for. + * + * @see #uninstallUI(JComponent) */ public void installUI(JComponent c) { @@ -213,20 +229,22 @@ public class BasicComboBoxUI extends ComboBoxUI if (c instanceof JComboBox) { - comboBox = (JComboBox) c; - comboBox.setOpaque(true); - comboBox.setLayout(createLayoutManager()); - installDefaults(); - installComponents(); - installListeners(); - installKeyboardActions(); + comboBox = (JComboBox) c; + comboBox.setOpaque(true); + comboBox.setLayout(createLayoutManager()); + installDefaults(); + installComponents(); + installListeners(); + installKeyboardActions(); } } /** - * This method uninstalls the UI. + * Uninstalls the UI for the given {@link JComponent}. * * @param c The JComponent that is having this UI removed. + * + * @see #installUI(JComponent) */ public void uninstallUI(JComponent c) { @@ -238,27 +256,27 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method installs the defaults that are defined in the Basic look and - * feel for this {@link JComboBox}. + * Installs the defaults that are defined in the {@link BasicLookAndFeel} + * for this {@link JComboBox}. + * + * @see #uninstallDefaults() */ protected void installDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - comboBox.setBackground(defaults.getColor("ComboBox.background")); - comboBox.setFont(defaults.getFont("ComboBox.font")); - comboBox.setForeground(defaults.getColor("ComboBox.foreground")); - - // Set default color that should be used to to render selected item - // of the combo box. - shadow = defaults.getColor("Button.shadow"); - darkShadow = defaults.getColor("Button.darkShadow"); - lightHighlight = defaults.getColor("Button.light"); - highlight = defaults.getColor("Button.highlight"); + LookAndFeel.installColorsAndFont(comboBox, "ComboBox.background", + "ComboBox.foreground", "ComboBox.font"); + + // fetch the button color scheme + buttonBackground = UIManager.getColor("ComboBox.buttonBackground"); + buttonShadow = UIManager.getColor("ComboBox.buttonShadow"); + buttonDarkShadow = UIManager.getColor("ComboBox.buttonDarkShadow"); + buttonHighlight = UIManager.getColor("ComboBox.buttonHighlight"); } /** - * This method creates and installs the listeners for this UI. + * Creates and installs the listeners for this UI. + * + * @see #uninstallListeners() */ protected void installListeners() { @@ -268,6 +286,7 @@ public class BasicComboBoxUI extends ComboBoxUI focusListener = createFocusListener(); comboBox.addFocusListener(focusListener); + listBox.addFocusListener(focusListener); itemListener = createItemListener(); comboBox.addItemListener(itemListener); @@ -276,35 +295,40 @@ public class BasicComboBoxUI extends ComboBoxUI comboBox.addKeyListener(keyListener); mouseListener = createMouseListener(); - comboBox.addMouseListener(mouseListener); + arrowButton.addMouseListener(mouseListener); // install listeners that listen to combo box model listDataListener = createListDataListener(); comboBox.getModel().addListDataListener(listDataListener); - - configureArrowButton(); } /** - * This method uninstalls the defaults and sets any objects created during - * install to null + * Uninstalls the defaults and sets any objects created during + * install to <code>null</code>. + * + * @see #installDefaults() */ protected void uninstallDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - comboBox.setBackground(null); - comboBox.setFont(null); - comboBox.setForeground(null); - - shadow = null; - darkShadow = null; - lightHighlight = null; - highlight = null; + if (comboBox.getFont() instanceof UIResource) + comboBox.setFont(null); + + if (comboBox.getForeground() instanceof UIResource) + comboBox.setForeground(null); + + if (comboBox.getBackground() instanceof UIResource) + comboBox.setBackground(null); + + buttonBackground = null; + buttonShadow = null; + buttonDarkShadow = null; + buttonHighlight = null; } /** * Detaches all the listeners we attached in {@link #installListeners}. + * + * @see #installListeners() */ protected void uninstallListeners() { @@ -312,6 +336,7 @@ public class BasicComboBoxUI extends ComboBoxUI propertyChangeListener = null; comboBox.removeFocusListener(focusListener); + listBox.removeFocusListener(focusListener); focusListener = null; comboBox.removeItemListener(itemListener); @@ -320,17 +345,15 @@ public class BasicComboBoxUI extends ComboBoxUI comboBox.removeKeyListener(keyListener); keyListener = null; - comboBox.removeMouseListener(mouseListener); + arrowButton.removeMouseListener(mouseListener); mouseListener = null; comboBox.getModel().removeListDataListener(listDataListener); listDataListener = null; - - unconfigureArrowButton(); } /** - * This method creates popup that will contain list of combo box's items + * Creates the popup that will contain list of combo box's items. * * @return popup containing list of combo box's items */ @@ -340,7 +363,7 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * Creates KeyListener to listen to key events. + * Creates a {@link KeyListener} to listen to key events. * * @return KeyListener that listens to key events. */ @@ -350,8 +373,8 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method create MouseListener that will listen to mouse event occuring - * in combo box. + * Creates a {@link MouseListener} that will listen to mouse events occurring + * in the combo box. * * @return the MouseListener */ @@ -361,10 +384,10 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method create FocusListener that will listen to changes in this + * Creates the {@link FocusListener} that will listen to changes in this * JComboBox's focus. * - * @return theFocusListener + * @return the FocusListener. */ protected FocusListener createFocusListener() { @@ -372,9 +395,9 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method create ListDataListener to listen to ComboBox's data model + * Creates a {@link ListDataListener} to listen to the combo box's data model. * - * @return ListDataListener + * @return The new listener. */ protected ListDataListener createListDataListener() { @@ -382,10 +405,10 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method creates ItemListener that will listen to to the changes in + * Creates an {@link ItemListener} that will listen to the changes in * the JComboBox's selection. * - * @return the ItemListener + * @return The ItemListener */ protected ItemListener createItemListener() { @@ -393,10 +416,10 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method creates PropertyChangeListener to listen to the changes in + * Creates a {@link PropertyChangeListener} to listen to the changes in * the JComboBox's bound properties. * - * @return the PropertyChangeListener + * @return The PropertyChangeListener */ protected PropertyChangeListener createPropertyChangeListener() { @@ -404,9 +427,10 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method returns layout manager for the combo box. + * Creates and returns a layout manager for the combo box. Subclasses can + * override this method to provide a different layout. * - * @return layout manager for the combo box + * @return a layout manager for the combo box. */ protected LayoutManager createLayoutManager() { @@ -414,10 +438,10 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method creates component that will be responsible for rendering the + * Creates a component that will be responsible for rendering the * selected component in the combo box. * - * @return render for the combo box + * @return A renderer for the combo box. */ protected ListCellRenderer createRenderer() { @@ -425,58 +449,54 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * Creates component that will be responsible for displaying/editting - * selected item in the combo box. This editor is used only when combo box - * is editable. + * Creates the component that will be responsible for displaying/editing + * the selected item in the combo box. This editor is used only when combo + * box is editable. * - * @return component that will be responsible for displaying/editting - * selected item in the combo box. + * @return A new component that will be responsible for displaying/editing + * the selected item in the combo box. */ protected ComboBoxEditor createEditor() { - return new BasicComboBoxEditor(); + return new BasicComboBoxEditor.UIResource(); } /** - * This method installs components for this JComboBox. ArrowButton, main - * part of combo box (upper part) and popup list of items are created and + * Installs the components for this JComboBox. ArrowButton, main + * part of combo box (upper part) and popup list of items are created and * configured here. */ protected void installComponents() { - // create and install arrow button - arrowButton = createArrowButton(); - - comboBox.add(arrowButton); - - // Set list that will be used by BasicComboBoxRender - // in order to determine the right colors when rendering - listBox = new JList(); - - Color background = arrowButton.getBackground(); - listBox.setBackground(background); - listBox.setSelectionBackground(background.darker()); - - Color foreground = arrowButton.getForeground(); - listBox.setForeground(foreground); - listBox.setSelectionForeground(foreground); + // create drop down list of items + popup = createPopup(); + listBox = popup.getList(); // set editor and renderer for the combo box. Editor is used // only if combo box becomes editable, otherwise renderer is used // to paint the selected item; combobox is not editable by default. comboBox.setRenderer(createRenderer()); - comboBox.setEditor(createEditor()); - editor = comboBox.getEditor().getEditorComponent(); + // create and install arrow button + arrowButton = createArrowButton(); + configureArrowButton(); + comboBox.add(arrowButton); - // create drop down list of items - popup = createPopup(); + ComboBoxEditor currentEditor = comboBox.getEditor(); + if (currentEditor == null || currentEditor instanceof UIResource) + { + currentEditor = createEditor(); + comboBox.setEditor(currentEditor); + } + editor = currentEditor.getEditorComponent(); comboBox.revalidate(); } /** - * This method uninstalls components from this JComboBox + * Uninstalls components from this {@link JComboBox}. + * + * @see #installComponents() */ protected void uninstallComponents() { @@ -490,12 +510,18 @@ public class BasicComboBoxUI extends ComboBoxUI comboBox.setRenderer(null); - comboBox.setEditor(null); - editor = null; + // if the editor is not an instanceof UIResource, it was not set by the + // UI delegate, so don't clear it... + ComboBoxEditor currentEditor = comboBox.getEditor(); + if (currentEditor instanceof UIResource) + { + comboBox.setEditor(null); + editor = null; + } } /** - * This method adds editor to the combo box + * Adds the current editor to the combo box. */ public void addEditor() { @@ -503,7 +529,7 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method removes editor from the combo box + * Removes the current editor from the combo box. */ public void removeEditor() { @@ -511,15 +537,17 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method configures editor for this combo box. + * Configures the editor for this combo box. */ protected void configureEditor() { + editor.setFont(comboBox.getFont()); + comboBox.getEditor().setItem(comboBox.getSelectedItem()); // FIXME: Need to implement. Set font and add listeners. } /** - * This method removes all the listeners for the editor. + * Unconfigures the editor for this combo nox. This method is not implemented. */ protected void unconfigureEditor() { @@ -527,42 +555,50 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method adds listeners to the arrow button part of the combo box. + * Configures the arrow button. + * + * @see #configureArrowButton() */ public void configureArrowButton() { - arrowButton.addMouseListener(mouseListener); + arrowButton.setEnabled(comboBox.isEnabled()); + arrowButton.setFont(comboBox.getFont()); } /** - * This method removes listeners from the arrow button part of the combo - * box. + * Unconfigures the arrow button. + * + * @see #configureArrowButton() + * + * @specnote The specification says this method is implementation specific + * and should not be used or overridden. */ public void unconfigureArrowButton() { - arrowButton.removeMouseListener(mouseListener); + // Nothing to do here yet. } /** - * This method create arrow button for this JComboBox. Arrow button is - * responsible for displaying / hiding drop down list of items when it is - * clicked. + * Creates an arrow button for this {@link JComboBox}. The arrow button is + * displayed at the right end of the combo box and is used to display/hide + * the drop down list of items. * - * @return JButton arrow button for this JComboBox. + * @return A new button. */ protected JButton createArrowButton() { - return new BasicArrowButton(BasicArrowButton.SOUTH); + return new BasicArrowButton(BasicArrowButton.SOUTH, buttonBackground, + buttonShadow, buttonDarkShadow, buttonHighlight); } /** - * This method checks if popup part of the combo box is visible on the - * screen + * Returns <code>true</code> if the popup is visible, and <code>false</code> + * otherwise. * * @param c The JComboBox to check * - * @return true if popup part of the JComboBox is visible and false - * otherwise. + * @return <code>true</code> if popup part of the JComboBox is visible and + * <code>false</code> otherwise. */ public boolean isPopupVisible(JComboBox c) { @@ -570,7 +606,7 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * Displays/Hides JComboBox's list of items on the screen. + * Displays/hides the {@link JComboBox}'s list of items on the screen. * * @param c The combo box, for which list of items should be * displayed/hidden @@ -579,7 +615,10 @@ public class BasicComboBoxUI extends ComboBoxUI public void setPopupVisible(JComboBox c, boolean v) { if (v) - popup.show(); + { + popup.show(); + popup.getList().requestFocus(); + } else popup.hide(); } @@ -593,7 +632,7 @@ public class BasicComboBoxUI extends ComboBoxUI */ public boolean isFocusTraversable(JComboBox c) { - if (comboBox.isEditable()) + if (!comboBox.isEditable()) return true; return false; @@ -607,56 +646,28 @@ public class BasicComboBoxUI extends ComboBoxUI */ public void paint(Graphics g, JComponent c) { - if (c instanceof JComboBox) - { - JComboBox cb = (JComboBox) c; - - paintBorder(g, comboBox.getBounds(), hasFocus); - - Rectangle rect = rectangleForCurrentValue(); - paintCurrentValueBackground(g, rect, hasFocus); - paintCurrentValue(g, rect, hasFocus); - } - } - - private void paintBorder(Graphics g, Rectangle bounds, boolean hasFocus) - { - int x = 0; - int y = 0; - int width = bounds.width; - int height = bounds.height; - - Color oldColor = g.getColor(); - - if (! arrowButton.getModel().isPressed()) - BasicGraphicsUtils.drawEtchedRect(g, x, y, width, height, Color.gray, - Color.white, Color.gray, Color.white); - else - { - g.setColor(darkShadow); - g.drawRect(x, y, width, height); - g.setColor(shadow); - g.drawRect(x + 1, y + 1, width - 3, height - 3); - } - g.setColor(oldColor); + Rectangle rect = rectangleForCurrentValue(); + paintCurrentValueBackground(g, rect, hasFocus); + paintCurrentValue(g, rect, hasFocus); } /** - * Returns preferred size for the given menu item. + * Returns preferred size for the combo box. * * @param c comboBox for which to get preferred size * - * @return $Dimension$ preferred size for the given combo box + * @return The preferred size for the given combo box */ public Dimension getPreferredSize(JComponent c) { - // return null to indicate that combo box's layout will determin its - // preferred size - return null; + // note: overriding getMinimumSize() (for example in the MetalComboBoxUI + // class) affects the getPreferredSize() result, so it seems logical that + // this method is implemented by delegating to the getMinimumSize() method + return getMinimumSize(c); } /** - * This method returns the minimum size for this {@link JComboBox} for this + * Returns the minimum size for this {@link JComboBox} for this * look and feel. * * @param c The {@link JComponent} to find the minimum size for. @@ -665,20 +676,26 @@ public class BasicComboBoxUI extends ComboBoxUI */ public Dimension getMinimumSize(JComponent c) { - return null; + Dimension d = getDisplaySize(); + int arrowButtonWidth = d.height; + Dimension result = new Dimension(d.width + arrowButtonWidth, d.height); + return result; } + /** The value returned by the getMaximumSize() method. */ + private static final Dimension MAXIMUM_SIZE = new Dimension(32767, 32767); + /** - * This method returns the maximum size for this {@link JComboBox} for this + * Returns the maximum size for this {@link JComboBox} for this * look and feel. * * @param c The {@link JComponent} to find the maximum size for * - * @return The dimensions of the minimum size. + * @return The maximum size (<code>Dimension(32767, 32767)</code>). */ public Dimension getMaximumSize(JComponent c) { - return null; + return MAXIMUM_SIZE; } public int getAccessibleChildrenCount(JComponent c) @@ -707,7 +724,7 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method selects next possible item relative to the current selection + * Selects next possible item relative to the current selection * to be next selected item in the combo box. */ protected void selectNextPossibleValue() @@ -718,7 +735,7 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method selects previous item relative to current selection to be + * Selects previous item relative to current selection to be * next selected item. */ protected void selectPreviousPossibleValue() @@ -729,8 +746,8 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method displays combo box popup if the popup is not currently shown - * on the screen and hides it if it is currently shown + * Displays combo box popup if the popup is not currently shown + * on the screen and hides it if it is currently shown */ protected void toggleOpenClose() { @@ -738,34 +755,23 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method returns bounds in which comboBox's selected Item will be - * displayed + * Returns the bounds in which comboBox's selected item will be + * displayed. * * @return rectangle bounds in which comboBox's selected Item will be * displayed */ protected Rectangle rectangleForCurrentValue() { - Rectangle cbBounds = comboBox.getBounds(); - - // Subtract width or the arrow button and border insets - Rectangle rectForCurrentValue = new Rectangle(cbBounds.x - + borderInsets.left, - cbBounds.y - + borderInsets.top, - cbBounds.width - - arrowButtonWidth - - borderInsets.left - - borderInsets.right, - cbBounds.height - - borderInsets.top - - borderInsets.bottom); - + Rectangle cbBounds = SwingUtilities.getLocalBounds(comboBox); + Rectangle abBounds = arrowButton.getBounds(); + Rectangle rectForCurrentValue = new Rectangle(cbBounds.x, cbBounds.y, + cbBounds.width - abBounds.width, cbBounds.height); return rectForCurrentValue; } /** - * This method returns insets of the current border. + * Returns the insets of the current border. * * @return Insets representing space between combo box and its border */ @@ -775,7 +781,7 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method paints currently selected value in the main part of the combo + * Paints currently selected value in the main part of the combo * box (part without popup). * * @param g graphics context @@ -794,28 +800,29 @@ public class BasicComboBoxUI extends ComboBoxUI * If there is currently no selected item we will take an empty * String as replacement. */ - Component comp = comboBox.getRenderer() - .getListCellRendererComponent(listBox, - (currentValue != null ? currentValue : ""), - -1, - isPressed, - hasFocus); - if (! comboBox.isEnabled()) - comp.setEnabled(false); - - g.translate(borderInsets.left, borderInsets.top); - comp.setBounds(0, 0, bounds.width, bounds.height); - comp.paint(g); - g.translate(-borderInsets.left, -borderInsets.top); - - comboBox.revalidate(); + Component comp = comboBox.getRenderer().getListCellRendererComponent( + listBox, (currentValue != null ? currentValue : ""), -1, + isPressed, hasFocus); + if (! comboBox.isEnabled()) + { + comp.setBackground(UIManager.getLookAndFeelDefaults().getColor( + "ComboBox.disabledBackground")); + comp.setForeground(UIManager.getLookAndFeelDefaults().getColor( + "ComboBox.disabledForeground")); + comp.setEnabled(false); + } + comp.setBounds(0, 0, bounds.width, bounds.height); + comp.setFont(comboBox.getFont()); + comp.paint(g); + + comboBox.revalidate(); } else comboBox.getEditor().setItem(comboBox.getSelectedItem()); } /** - * This method paints background of part of the combo box, where currently + * Paints the background of part of the combo box, where currently * selected value is displayed. If the combo box has focus this method * should also paint focus rectangle around the combo box. * @@ -832,58 +839,102 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * Returns default size for the combo box that doesn't contain any elements - * in it + * Returns the default size for the display area of a combo box that does + * not contain any elements. This method returns the width and height of + * a single space in the current font, plus a margin of 1 pixel. * - * @return Default size of the combo box with no elements in it. + * @return The default display size. + * + * @see #getDisplaySize() */ protected Dimension getDefaultSize() { - return new Dimension(6, 17); + // There is nothing in the spec to say how this method should be + // implemented...so I've done some guessing, written some Mauve tests, + // and written something that gives dimensions that are close to the + // reference implementation. + FontMetrics fm = comboBox.getFontMetrics(comboBox.getFont()); + int w = fm.charWidth(' ') + 2; + int h = fm.getHeight() + 2; + return new Dimension(w, h); } /** - * Returns size of the largest item in the combo box. This size will be the - * size of the combo box, not including the arrowButton. + * Returns the size of the display area for the combo box. This size will be + * the size of the combo box, not including the arrowButton. * - * @return dimensions of the largest item in the combo box. + * @return The size of the display area for the combo box. */ - protected Dimension getLargestItemSize() + protected Dimension getDisplaySize() { - ComboBoxModel model = comboBox.getModel(); - int numItems = model.getSize(); - - // if combo box doesn't have any items then simply - // return its default size - if (numItems == 0) + if (!comboBox.isEditable()) { - largestItemSize = getDefaultSize(); - return largestItemSize; + Object prototype = comboBox.getPrototypeDisplayValue(); + if (prototype != null) + { + // calculate result based on prototype + ListCellRenderer renderer = comboBox.getRenderer(); + Component comp = renderer.getListCellRendererComponent(listBox, + prototype, -1, false, false); + Dimension compSize = comp.getPreferredSize(); + compSize.width += 2; // add 1 pixel margin around area + compSize.height += 2; + return compSize; + } + else + { + ComboBoxModel model = comboBox.getModel(); + int numItems = model.getSize(); + + // if combo box doesn't have any items then simply + // return its default size + if (numItems == 0) + { + displaySize = getDefaultSize(); + return displaySize; + } + + Dimension size = new Dimension(0, 0); + + // ComboBox's display size should be equal to the + // size of the largest item in the combo box. + ListCellRenderer renderer = comboBox.getRenderer(); + + for (int i = 0; i < numItems; i++) + { + Object item = model.getElementAt(i); + Component comp = renderer.getListCellRendererComponent(listBox, + item, -1, false, false); + + Dimension compSize = comp.getPreferredSize(); + if (compSize.width + 2 > size.width) + size.width = compSize.width + 2; + if (compSize.height + 2 > size.height) + size.height = compSize.height + 2; + } + displaySize = size; + return displaySize; + } } - - Dimension size = new Dimension(0, 0); - - // ComboBox's display size should be equal to the - // size of the largest item in the combo box. - ListCellRenderer renderer = comboBox.getRenderer(); - - for (int i = 0; i < numItems; i++) + else // an editable combo, { - Object item = model.getElementAt(i); - String s = item.toString(); - Component comp = renderer.getListCellRendererComponent(listBox, item, - -1, false, false); - - if (comp.getPreferredSize().getWidth() > size.getWidth()) - size = comp.getPreferredSize(); + Component comp = comboBox.getEditor().getEditorComponent(); + Dimension prefSize = comp.getPreferredSize(); + int width = prefSize.width; + int height = prefSize.height + 2; + Object prototype = comboBox.getPrototypeDisplayValue(); + if (prototype != null) + { + FontMetrics fm = comboBox.getFontMetrics(comboBox.getFont()); + width = Math.max(width, fm.stringWidth(prototype.toString()) + 2); + } + displaySize = new Dimension(width, height); + return displaySize; } - - largestItemSize = size; - return largestItemSize; } /** - * This method installs the keyboard actions for the JComboBox as specified + * Installs the keyboard actions for the {@link JComboBox} as specified * by the look and feel. */ protected void installKeyboardActions() @@ -892,7 +943,7 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method uninstalls the keyboard actions for the JComboBox there were + * Uninstalls the keyboard actions for the {@link JComboBox} there were * installed by in {@link #installListeners}. */ protected void uninstallKeyboardActions() @@ -901,22 +952,39 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This class is Layout Manager for this combo box. + * A {@link LayoutManager} used to position the sub-components of the + * {@link JComboBox}. + * + * @see BasicComboBoxUI#createLayoutManager() */ - public class ComboBoxLayoutManager extends Object implements LayoutManager + public class ComboBoxLayoutManager implements LayoutManager { /** * Creates a new ComboBoxLayoutManager object. */ public ComboBoxLayoutManager() { + // Nothing to do here. } + /** + * Adds a component to the layout. This method does nothing, since the + * layout manager doesn't need to track the components. + * + * @param name the name to associate the component with (ignored). + * @param comp the component (ignored). + */ public void addLayoutComponent(String name, Component comp) { // Do nothing } + /** + * Removes a component from the layout. This method does nothing, since + * the layout manager doesn't need to track the components. + * + * @param comp the component. + */ public void removeLayoutComponent(Component comp) { // Do nothing @@ -925,43 +993,30 @@ public class BasicComboBoxUI extends ComboBoxUI /** * Returns preferred layout size of the JComboBox. * - * @param parent Container for which preferred size should be calculated + * @param parent the Container for which the preferred size should be + * calculated. * - * @return preferred size for the given container + * @return The preferred size for the given container */ public Dimension preferredLayoutSize(Container parent) { - Dimension d = new Dimension(0, 0); - - if (largestItemSize == null) - largestItemSize = getLargestItemSize(); - - // add size for the area that will display selected item - d.width += largestItemSize.getWidth(); - d.height += largestItemSize.getHeight(); - - // add size of the arrow button - d.width += arrowButtonWidth; - - // add width and height of the border - d.width += borderInsets.left + borderInsets.right; - d.height += borderInsets.left + borderInsets.right; - - // Add combo box's insets - Insets insets = parent.getInsets(); - d.width += insets.left + insets.right; - d.width += insets.left + insets.right; - - return d; + return getPreferredSize((JComponent) parent); } + /** + * Returns the minimum layout size. + * + * @param parent the container. + * + * @return The minimum size. + */ public Dimension minimumLayoutSize(Container parent) { return preferredLayoutSize(parent); } /** - * This method layouts out the components in the container. It puts arrow + * Arranges the components in the container. It puts arrow * button right end part of the comboBox. If the comboBox is editable * then editor is placed to the left of arrow button, starting from the * beginning. @@ -972,21 +1027,19 @@ public class BasicComboBoxUI extends ComboBoxUI { // Position editor component to the left of arrow button if combo box is // editable - int editorWidth = comboBox.getBounds().width - arrowButtonWidth - 2; + int arrowSize = comboBox.getHeight(); + int editorWidth = comboBox.getBounds().width - arrowSize; if (comboBox.isEditable()) - editor.setBounds(borderInsets.left, borderInsets.top, editorWidth, - comboBox.getBounds().height - borderInsets.left - - borderInsets.top); - - arrowButton.setBounds(editorWidth, 2, arrowButtonWidth, - comboBox.getBounds().height - 4); + editor.setBounds(0, 0, editorWidth, comboBox.getBounds().height); + + arrowButton.setBounds(editorWidth, 0, arrowSize, arrowSize); comboBox.revalidate(); } } /** - * This class handles focus changes occuring in the combo box. This class is + * Handles focus changes occuring in the combo box. This class is * responsible for repainting combo box whenever focus is gained or lost * and also for hiding popup list of items whenever combo box loses its * focus. @@ -998,11 +1051,12 @@ public class BasicComboBoxUI extends ComboBoxUI */ public FocusHandler() { + // Nothing to do here. } /** - * This mehtod is invoked when combo box gains focus. It repaints main - * part of combo box accordingally. + * Invoked when combo box gains focus. It repaints main + * part of combo box accordingly. * * @param e the FocusEvent */ @@ -1013,22 +1067,22 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method is invoked when combo box loses focus It repaint main part - * of combo box accordingally and hides popup list of items. + * Invoked when the combo box loses focus. It repaints the main part + * of the combo box accordingly and hides the popup list of items. * * @param e the FocusEvent */ public void focusLost(FocusEvent e) { hasFocus = false; + setPopupVisible(comboBox, false); comboBox.repaint(); - popup.hide(); } } /** - * This class handles ItemEvent fired by the JComboBox when its selected - * item changes. + * Handles {@link ItemEvent}s fired by the {@link JComboBox} when its + * selected item changes. */ public class ItemHandler extends Object implements ItemListener { @@ -1037,16 +1091,19 @@ public class BasicComboBoxUI extends ComboBoxUI */ public ItemHandler() { + // Nothing to do here. } /** - * This method is invoked when selected item becomes deselected or when + * Invoked when selected item becomes deselected or when * new item becomes selected. * * @param e the ItemEvent representing item's state change. */ public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED && comboBox.isEditable()) + comboBox.getEditor().setItem(e.getItem()); comboBox.repaint(); } } @@ -1058,11 +1115,11 @@ public class BasicComboBoxUI extends ComboBoxUI { public KeyHandler() { + // Nothing to do here. } - /* - * This method is invoked whenever key is pressed while JComboBox is in - * focus. + /** + * Invoked whenever key is pressed while JComboBox is in focus. */ public void keyPressed(KeyEvent e) { @@ -1072,7 +1129,7 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This class handles to the changes occuring in the JComboBox's data model + * Handles the changes occurring in the JComboBox's data model. */ public class ListDataHandler extends Object implements ListDataListener { @@ -1081,10 +1138,11 @@ public class BasicComboBoxUI extends ComboBoxUI */ public ListDataHandler() { + // Nothing to do here. } /** - * This method is invoked content's of JComboBox's data model are changed + * Invoked if the content's of JComboBox's data model are changed. * * @param e ListDataEvent describing the change. */ @@ -1094,36 +1152,27 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method is invoked when items were added to the JComboBox's data - * model. + * Invoked when items are added to the JComboBox's data model. * * @param e ListDataEvent describing the change. */ public void intervalAdded(ListDataEvent e) { - // must determine if the size of the combo box should change - int start = e.getIndex0(); - int end = e.getIndex1(); - ComboBoxModel model = comboBox.getModel(); ListCellRenderer renderer = comboBox.getRenderer(); - if (largestItemSize == null) - largestItemSize = new Dimension(0, 0); + if (displaySize == null) + displaySize = getDisplaySize(); + if (displaySize.width < getDefaultSize().width) + displaySize.width = getDefaultSize().width; + if (displaySize.height < getDefaultSize().height) + displaySize.height = getDefaultSize().height; - for (int i = start; i < end; i++) - { - Object item = model.getElementAt(i); - Component comp = renderer.getListCellRendererComponent(new JList(), - item, -1, - false, false); - if (comp.getPreferredSize().getWidth() > largestItemSize.getWidth()) - largestItemSize = comp.getPreferredSize(); - } + comboBox.repaint(); } /** - * This method is invoked when items were removed from the JComboBox's + * Invoked when items are removed from the JComboBox's * data model. * * @param e ListDataEvent describing the change. @@ -1131,23 +1180,29 @@ public class BasicComboBoxUI extends ComboBoxUI public void intervalRemoved(ListDataEvent e) { // recalculate display size of the JComboBox. - largestItemSize = getLargestItemSize(); + displaySize = getDisplaySize(); comboBox.repaint(); } } /** - * This class handles PropertyChangeEvents fired by JComboBox. + * Handles {@link PropertyChangeEvent}s fired by the {@link JComboBox}. */ public class PropertyChangeHandler extends Object implements PropertyChangeListener { + /** + * Creates a new instance. + */ public PropertyChangeHandler() { + // Nothing to do here. } /** - * This method is invoked whenever bound property of JComboBox changes. + * Invoked whenever bound property of JComboBox changes. + * + * @param e the event. */ public void propertyChange(PropertyChangeEvent e) { @@ -1185,59 +1240,36 @@ public class BasicComboBoxUI extends ComboBoxUI if ((ComboBoxModel) e.getNewValue() != null) comboBox.getModel().addListDataListener(listDataListener); } + else if (e.getPropertyName().equals("font")) + { + Font font = (Font) e.getNewValue(); + editor.setFont(font); + listBox.setFont(font); + arrowButton.setFont(font); + comboBox.revalidate(); + comboBox.repaint(); + } // FIXME: Need to handle changes in other bound properties. } } /** - * MouseHandler listens to mouse events occuring in the combo box. This - * class is responsible for repainting this JComboBox whenever the mouse is - * being pressed or released over it. + * A handler for mouse events occurring in the combo box. An instance of + * this class is returned by the <code>createMouseListener()</code> method. */ private class MouseHandler extends MouseAdapter { /** - * This method is invoked when mouse is pressed over the combo box. It - * repaints the combo box accordinglly + * Invoked when mouse is pressed over the combo box. It toggles the + * visibility of the popup list. * - * @param e the MouseEvent + * @param e the event */ public void mousePressed(MouseEvent e) { if (comboBox.isEnabled()) - { - if (e.getSource() instanceof JComboBox) - { - arrowButton.getModel().setPressed(true); - arrowButton.getModel().setArmed(true); - } - - comboBox.repaint(); - - if (e.getSource() instanceof BasicArrowButton) - toggleOpenClose(); - } - } - - /** - * This method is invoked when mouse is released over the combo box. It - * repaints the combo box accordinglly - * - * @param e the MouseEvent - */ - public void mouseReleased(MouseEvent e) - { - if (comboBox.isEnabled()) - { - if (e.getSource() instanceof JComboBox) - { - arrowButton.getModel().setPressed(false); - arrowButton.getModel().setArmed(false); - } - - comboBox.repaint(); - } + toggleOpenClose(); } } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java index 73aac8d4e65..73979bb89c1 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java @@ -38,6 +38,7 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Point; @@ -55,6 +56,7 @@ import java.awt.event.MouseMotionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import javax.swing.BorderFactory; import javax.swing.ComboBoxModel; import javax.swing.JComboBox; import javax.swing.JLabel; @@ -178,8 +180,8 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup // to display number of rows equal to 'maximumRowCount' property int popupHeight = getPopupHeightForRowCount(comboBox.getMaximumRowCount()); - list.setPreferredSize(new Dimension(cbBounds.width, popupHeight)); - super.setPopupSize(cbBounds.width, popupHeight); + scroller.setPreferredSize(new Dimension(cbBounds.width, popupHeight)); + pack(); // Highlight selected item in the combo box's drop down list if (comboBox.getSelectedIndex() != -1) @@ -478,6 +480,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup */ protected void configureScroller() { + scroller.setBorder(null); scroller.getViewport().setView(list); scroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); } @@ -488,6 +491,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup */ protected void configurePopup() { + setBorder(BorderFactory.createLineBorder(Color.BLACK)); // initialize list that will be used to display combo box's items this.list = createList(); ((JLabel) list.getCellRenderer()).setHorizontalAlignment(SwingConstants.LEFT); @@ -714,7 +718,11 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup protected void updateListBoxSelectionForEvent(MouseEvent anEvent, boolean shouldScroll) { - // FIXME: Need to implement + // TODO: We need to handle the shouldScroll parameter somehow. + int index = list.locationToIndex(anEvent.getPoint()); + // Check for valid index. + if (index >= 0) + list.setSelectedIndex(index); } /** @@ -732,6 +740,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup */ protected InvocationMouseHandler() { + // Nothing to do here. } /** @@ -744,7 +753,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup public void mousePressed(MouseEvent e) { if (comboBox.isEnabled()) - togglePopup(); + togglePopup(); } /** @@ -768,15 +777,15 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup // then change selection and close popup if (! (releasedComponent instanceof JComboBox)) { - // List model contains the item over which mouse is released, - // since it is updated every time the mouse is moved over a different - // item in the list. Now that the mouse is released we need to - // update model of the combo box as well. - comboBox.setSelectedIndex(list.getSelectedIndex()); - - if (isAutoScrolling) - stopAutoScrolling(); - hide(); + // List model contains the item over which mouse is released, + // since it is updated every time the mouse is moved over a different + // item in the list. Now that the mouse is released we need to + // update model of the combo box as well. + comboBox.setSelectedIndex(list.getSelectedIndex()); + + if (isAutoScrolling) + stopAutoScrolling(); + hide(); } } } @@ -792,6 +801,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup */ protected InvocationMouseMotionHandler() { + // Nothing to do here. } /** @@ -868,6 +878,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup */ protected ItemHandler() { + // Nothing to do here. } /** @@ -877,6 +888,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup */ public void itemStateChanged(ItemEvent e) { + // TODO: What should be done here? } } @@ -890,16 +902,20 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { protected ListMouseHandler() { + // Nothing to do here. } public void mousePressed(MouseEvent e) { + // TODO: What should be do here? } public void mouseReleased(MouseEvent anEvent) { int index = list.locationToIndex(anEvent.getPoint()); - comboBox.setSelectedIndex(index); + // Check for valid index. + if (index >= 0) + comboBox.setSelectedIndex(index); hide(); } } @@ -913,15 +929,12 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { protected ListMouseMotionHandler() { + // Nothing to do here. } public void mouseMoved(MouseEvent anEvent) { - // Highlight list cells over which the mouse is located. - // This changes list model, but has no effect on combo box's data model - int index = list.locationToIndex(anEvent.getPoint()); - list.setSelectedIndex(index); - list.repaint(); + updateListBoxSelectionForEvent(anEvent, false); } } @@ -934,6 +947,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { protected PropertyChangeHandler() { + // Nothing to do here. } public void propertyChange(PropertyChangeEvent e) @@ -1009,18 +1023,22 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { public ListDataHandler() { + // Nothing to do here. } public void contentsChanged(ListDataEvent e) { + // Nothing to do here. } public void intervalAdded(ListDataEvent e) { + // Nothing to do here. } public void intervalRemoved(ListDataEvent e) { + // Nothing to do here. } } @@ -1032,10 +1050,12 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { protected ListSelectionHandler() { + // Nothing to do here. } public void valueChanged(ListSelectionEvent e) { + // Nothing to do here. } } @@ -1046,10 +1066,12 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { public InvocationKeyHandler() { + // Nothing to do here. } public void keyReleased(KeyEvent e) { + // Nothing to do here. } } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java index 561b497f1c3..3f8730249da 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java @@ -365,6 +365,7 @@ public class BasicDesktopIconUI extends DesktopIconUI */ public BasicDesktopIconUI() { + // Nothing to do here. } /** @@ -585,6 +586,7 @@ public class BasicDesktopIconUI extends DesktopIconUI } catch (PropertyVetoException pve) { + // We do nothing if the attempt has been vetoed. } } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java index b59261b17f3..4116858da9d 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java @@ -38,6 +38,7 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import java.awt.Color; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.beans.PropertyVetoException; @@ -49,10 +50,10 @@ import javax.swing.JComponent; import javax.swing.JDesktopPane; import javax.swing.JInternalFrame; import javax.swing.KeyStroke; -import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.DesktopPaneUI; +import javax.swing.plaf.UIResource; /** * This class is the UI delegate for JDesktopPane for the Basic look and feel. @@ -74,13 +75,14 @@ public class BasicDesktopPaneUI extends DesktopPaneUI { if (desktop.getSelectedFrame() != null) { - try - { - desktop.getSelectedFrame().setClosed(true); - } - catch (PropertyVetoException pve) - { - } + try + { + desktop.getSelectedFrame().setClosed(true); + } + catch (PropertyVetoException pve) + { + // We do nothing if the attempts has been vetoed. + } } } @@ -112,13 +114,14 @@ public class BasicDesktopPaneUI extends DesktopPaneUI { if (desktop.getSelectedFrame() != null) { - try - { - desktop.getSelectedFrame().setMaximum(true); - } - catch (PropertyVetoException pve) - { - } + try + { + desktop.getSelectedFrame().setMaximum(true); + } + catch (PropertyVetoException pve) + { + // We do nothing if the attempts has been vetoed. + } } } @@ -150,13 +153,14 @@ public class BasicDesktopPaneUI extends DesktopPaneUI { if (desktop.getSelectedFrame() != null) { - try - { - desktop.getSelectedFrame().setIcon(true); - } - catch (PropertyVetoException pve) - { - } + try + { + desktop.getSelectedFrame().setIcon(true); + } + catch (PropertyVetoException pve) + { + // We do nothing if the attempt has been vetoed. + } } } @@ -236,16 +240,17 @@ public class BasicDesktopPaneUI extends DesktopPaneUI JInternalFrame frame = desktop.getSelectedFrame(); if (frame != null) { - try - { - if (frame.isIcon()) - frame.setIcon(false); - else if (frame.isMaximum()) - frame.setMaximum(false); - } - catch (PropertyVetoException pve) - { - } + try + { + if (frame.isIcon()) + frame.setIcon(false); + else if (frame.isMaximum()) + frame.setMaximum(false); + } + catch (PropertyVetoException pve) + { + // We do nothing if the attempt has been vetoed. + } } } @@ -304,6 +309,7 @@ public class BasicDesktopPaneUI extends DesktopPaneUI */ public BasicDesktopPaneUI() { + // Nothing to do here. } /** @@ -361,9 +367,9 @@ public class BasicDesktopPaneUI extends DesktopPaneUI */ protected void installDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - desktop.setBackground(defaults.getColor("desktop")); + Color bg = desktop.getBackground(); + if (bg == null || bg instanceof UIResource) + desktop.setBackground(UIManager.getColor("desktop")); } /** @@ -381,7 +387,7 @@ public class BasicDesktopPaneUI extends DesktopPaneUI protected void installKeyboardActions() { // FIXME: create actions and keystrokes. - registerKeyboardAction(); + registerKeyboardActions(); } /** @@ -405,7 +411,7 @@ public class BasicDesktopPaneUI extends DesktopPaneUI * This method registers the actions to the appropriate Action and Input * maps. */ - protected void registerKeyboardAction() + protected void registerKeyboardActions() { // FIXME: Do the binding. // XXX: the gtk windows tend to intercept a lot of the diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java index f74e9229893..9c639656545 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java @@ -48,7 +48,6 @@ import java.awt.Point; import java.awt.Polygon; import java.awt.Window; import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseAdapter; @@ -60,9 +59,9 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Hashtable; + import javax.swing.AbstractAction; import javax.swing.Action; -import javax.swing.BoxLayout; import javax.swing.ButtonGroup; import javax.swing.Icon; import javax.swing.JButton; @@ -92,25 +91,31 @@ import javax.swing.plaf.FileChooserUI; /** - * DOCUMENT ME! + * A UI delegate for the {@link JFileChooser} component under the + * {@link BasicLookAndFeel}. */ public class BasicFileChooserUI extends FileChooserUI { /** - * DOCUMENT ME! + * A file filter that accepts all files. */ protected class AcceptAllFileFilter extends FileFilter { + /** + * Creates a new instance. + */ public AcceptAllFileFilter() { + // Nothing to do here. } /** - * DOCUMENT ME! + * Returns <code>true</code> always, as all files are accepted by this + * filter. * - * @param f DOCUMENT ME! + * @param f the file. * - * @return DOCUMENT ME! + * @return Always <code>true</code>. */ public boolean accept(File f) { @@ -118,9 +123,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns a description for this filter. * - * @return DOCUMENT ME! + * @return A description for the file filter. */ public String getDescription() { @@ -129,7 +134,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Handles a user action to approve the dialog selection. + * + * @see BasicFileChooserUI#getApproveSelectionAction() */ protected class ApproveSelectionAction extends AbstractAction { @@ -138,50 +145,55 @@ public class BasicFileChooserUI extends FileChooserUI */ protected ApproveSelectionAction() { + // Nothing to do here. } /** - * DOCUMENT ME! - * - * @param e DOCUMENT ME! + * Sets the current selection and closes the dialog. + * + * @param e the action event. */ public void actionPerformed(ActionEvent e) { - Object obj = filelist.getSelectedValue(); + Object obj = new String(parentPath + entry.getText()); if (obj != null) { - File f = filechooser.getFileSystemView().createFileObject(obj - .toString()); - if (filechooser.isTraversable(f) && - filechooser.getFileSelectionMode() == JFileChooser.FILES_ONLY) + File f = filechooser.getFileSystemView().createFileObject( + obj.toString()); + if (filechooser.isTraversable(f) + && filechooser.isDirectorySelectionEnabled()) filechooser.setCurrentDirectory(f); - else - { - filechooser.setSelectedFile(f); - filechooser.approveSelection(); - closeDialog(); - } + else + { + filechooser.setSelectedFile(f); + filechooser.approveSelection(); + closeDialog(); + } } } } /** - * DOCUMENT ME! + * Provides presentation information about files and directories. */ protected class BasicFileView extends FileView { - /** DOCUMENT ME! */ + /** Storage for cached icons. */ protected Hashtable iconCache = new Hashtable(); + /** + * Creates a new instance. + */ public BasicFileView() { + // Nothing to do here. } /** - * DOCUMENT ME! + * Adds an icon to the cache, associating it with the given file/directory. * - * @param f DOCUMENT ME! - * @param i DOCUMENT ME! + * @param f the file/directory. + * @param i the icon. */ public void cacheIcon(File f, Icon i) { @@ -189,7 +201,7 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Clears the icon cache. */ public void clearIconCache() { @@ -197,11 +209,12 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Retrieves the icon associated with the specified file/directory, if + * there is one. * - * @param f DOCUMENT ME! + * @param f the file/directory. * - * @return DOCUMENT ME! + * @return The cached icon (or <code>null</code>). */ public Icon getCachedIcon(File f) { @@ -209,11 +222,13 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns a description of the given file/directory. In this + * implementation, the description is the same as the name returned by + * {@link #getName(File)}. * - * @param f DOCUMENT ME! + * @param f the file/directory. * - * @return DOCUMENT ME! + * @return A description of the given file/directory. */ public String getDescription(File f) { @@ -221,11 +236,11 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns an icon appropriate for the given file or directory. * - * @param f DOCUMENT ME! + * @param f the file/directory. * - * @return DOCUMENT ME! + * @return An icon. */ public Icon getIcon(File f) { @@ -241,11 +256,11 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the name for the given file/directory. * - * @param f DOCUMENT ME! + * @param f the file/directory. * - * @return DOCUMENT ME! + * @return The name of the file/directory. */ public String getName(File f) { @@ -253,11 +268,11 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns a localised description for the type of file/directory. * - * @param f DOCUMENT ME! + * @param f the file/directory. * - * @return DOCUMENT ME! + * @return A type description for the given file/directory. */ public String getTypeDescription(File f) { @@ -268,34 +283,38 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns {@link Boolean#TRUE} if the given file/directory is hidden, + * and {@link Boolean#FALSE} otherwise. * - * @param f DOCUMENT ME! + * @param f the file/directory. * - * @return DOCUMENT ME! + * @return {@link Boolean#TRUE} or {@link Boolean#FALSE}. */ public Boolean isHidden(File f) { - return new Boolean(filechooser.getFileSystemView().isHiddenFile(f)); + return Boolean.valueOf(filechooser.getFileSystemView().isHiddenFile(f)); } } /** - * DOCUMENT ME! + * Handles an action to cancel the file chooser. + * + * @see BasicFileChooserUI#getCancelSelectionAction() */ protected class CancelSelectionAction extends AbstractAction { /** - * Creates a new CancelSelectionAction object. + * Creates a new <code>CancelSelectionAction</code> object. */ protected CancelSelectionAction() { + // Nothing to do here. } /** - * DOCUMENT ME! + * Cancels the selection and closes the dialog. * - * @param e DOCUMENT ME! + * @param e the action event (ignored). */ public void actionPerformed(ActionEvent e) { @@ -305,21 +324,25 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * An action to handle changes to the parent directory (for example, via + * a click on the "up folder" button). + * + * @see BasicFileChooserUI#getChangeToParentDirectoryAction() */ protected class ChangeToParentDirectoryAction extends AbstractAction { /** - * Creates a new ChangeToParentDirectoryAction object. + * Creates a new <code>ChangeToParentDirectoryAction</code> object. */ protected ChangeToParentDirectoryAction() { + // Nothing to do here. } /** - * DOCUMENT ME! + * Handles the action event. * - * @param e DOCUMENT ME! + * @param e the action event. */ public void actionPerformed(ActionEvent e) { @@ -330,11 +353,13 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * A mouse listener that handles double-click events. + * + * @see BasicFileChooserUI#createDoubleClickListener(JFileChooser, JList) */ protected class DoubleClickListener extends MouseAdapter { - /** DOCUMENT ME! */ + /** A timer. */ private Timer timer = null; /** DOCUMENT ME! */ @@ -358,54 +383,57 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! - * - * @param e DOCUMENT ME! + * Handles a mouse click event. + * + * @param e the event. */ public void mouseClicked(MouseEvent e) { if (list.getSelectedValue() == null) - return; + return; FileSystemView fsv = filechooser.getFileSystemView(); if (timer.isRunning() && list.getSelectedValue().toString().equals(lastSelected.toString())) { - File f = fsv.createFileObject(lastSelected.toString()); - timer.stop(); - if (filechooser.isTraversable(f)) - { - filechooser.setCurrentDirectory(f); - filechooser.rescanCurrentDirectory(); - } - else - { - filechooser.setSelectedFile(f); - filechooser.approveSelection(); - closeDialog(); - } + File f = fsv.createFileObject(lastSelected.toString()); + timer.stop(); + if (filechooser.isTraversable(f)) + { + filechooser.setCurrentDirectory(f); + filechooser.rescanCurrentDirectory(); + } + else + { + filechooser.setSelectedFile(f); + filechooser.approveSelection(); + closeDialog(); + } } else { - File f = fsv.createFileObject(list.getSelectedValue().toString()); - if (filechooser.isTraversable(f)) - { - setDirectorySelected(true); - setDirectory(f); - } - else - { - setDirectorySelected(false); - setDirectory(null); - } - lastSelected = list.getSelectedValue().toString(); - timer.restart(); + String path = list.getSelectedValue().toString(); + File f = fsv.createFileObject(path); + if (filechooser.isTraversable(f)) + { + setDirectorySelected(true); + setDirectory(f); + } + else + { + setDirectorySelected(false); + setDirectory(null); + } + lastSelected = path; + parentPath = path.substring(0, path.lastIndexOf("/") + 1); + entry.setText(path.substring(path.lastIndexOf("/") + 1)); + timer.restart(); } } /** - * DOCUMENT ME! - * - * @param e DOCUMENT ME! + * Handles a mouse entered event (NOT IMPLEMENTED). + * + * @param e the mouse event. */ public void mouseEntered(MouseEvent e) { @@ -414,21 +442,26 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * An action that changes the file chooser to display the user's home + * directory. + * + * @see BasicFileChooserUI#getGoHomeAction() */ protected class GoHomeAction extends AbstractAction { /** - * Creates a new GoHomeAction object. + * Creates a new <code>GoHomeAction</code> object. */ protected GoHomeAction() { + // Nothing to do here. } /** - * DOCUMENT ME! + * Sets the directory to the user's home directory, and repaints the + * file chooser component. * - * @param e DOCUMENT ME! + * @param e the action event (ignored). */ public void actionPerformed(ActionEvent e) { @@ -440,21 +473,24 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * An action that handles the creation of a new folder/directory. + * + * @see BasicFileChooserUI#getNewFolderAction() */ protected class NewFolderAction extends AbstractAction { /** - * Creates a new NewFolderAction object. + * Creates a new <code>NewFolderAction</code> object. */ protected NewFolderAction() { + // Nothing to do here. } /** - * DOCUMENT ME! + * Handles the event by creating a new folder. * - * @param e DOCUMENT ME! + * @param e the action event (ignored). */ public void actionPerformed(ActionEvent e) { @@ -473,15 +509,18 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * A listener for selection events in the file list. + * + * @see BasicFileChooserUI#createListSelectionListener(JFileChooser) */ protected class SelectionListener implements ListSelectionListener { /** - * Creates a new SelectionListener object. + * Creates a new <code>SelectionListener</code> object. */ protected SelectionListener() { + // Nothing to do here. } /** @@ -504,6 +543,8 @@ public class BasicFileChooserUI extends FileChooserUI /** * DOCUMENT ME! + * + * @see BasicFileChooserUI#getUpdateAction() */ protected class UpdateAction extends AbstractAction { @@ -512,28 +553,30 @@ public class BasicFileChooserUI extends FileChooserUI */ protected UpdateAction() { + // Nothing to do here. } /** - * DOCUMENT ME! + * NOT YET IMPLEMENTED. * - * @param e DOCUMENT ME! + * @param e the action event. */ public void actionPerformed(ActionEvent e) { + // FIXME: implement this } } - /** DOCUMENT ME! */ + /** The localised mnemonic for the cancel button. */ protected int cancelButtonMnemonic; - /** DOCUMENT ME! */ + /** The localised text for the cancel button. */ protected String cancelButtonText; - /** DOCUMENT ME! */ + /** The localised tool tip text for the cancel button. */ protected String cancelButtonToolTipText; - /** DOCUMENT ME! */ + /** An icon representing a computer. */ protected Icon computerIcon = new Icon() { public int getIconHeight() @@ -548,10 +591,11 @@ public class BasicFileChooserUI extends FileChooserUI public void paintIcon(Component c, Graphics g, int x, int y) { + // FIXME: is this not implemented, or is the icon intentionally blank? } }; - /** DOCUMENT ME! */ + /** An icon for the "details view" button. */ protected Icon detailsViewIcon = new Icon() { public int getIconHeight() @@ -580,7 +624,7 @@ public class BasicFileChooserUI extends FileChooserUI } }; - /** DOCUMENT ME! */ + /** An icon representing a directory. */ protected Icon directoryIcon = new Icon() { public int getIconHeight() @@ -619,16 +663,16 @@ public class BasicFileChooserUI extends FileChooserUI } }; - /** DOCUMENT ME! */ + /** The localised Mnemonic for the open button. */ protected int directoryOpenButtonMnemonic; - /** DOCUMENT ME! */ + /** The localised text for the open button. */ protected String directoryOpenButtonText; - /** DOCUMENT ME! */ + /** The localised tool tip text for the open button. */ protected String directoryOpenButtonToolTipText; - /** DOCUMENT ME! */ + /** An icon representing a file. */ protected Icon fileIcon = new Icon() { public int getIconHeight() @@ -668,7 +712,7 @@ public class BasicFileChooserUI extends FileChooserUI } }; - /** DOCUMENT ME! */ + /** An icon representing a floppy drive. */ protected Icon floppyDriveIcon = new Icon() { public int getIconHeight() @@ -683,10 +727,11 @@ public class BasicFileChooserUI extends FileChooserUI public void paintIcon(Component c, Graphics g, int x, int y) { + // FIXME: is this not implemented, or is the icon intentionally blank? } }; - /** DOCUMENT ME! */ + /** An icon representing a hard drive. */ protected Icon hardDriveIcon = new Icon() { public int getIconHeight() @@ -701,19 +746,20 @@ public class BasicFileChooserUI extends FileChooserUI public void paintIcon(Component c, Graphics g, int x, int y) { + // FIXME: is this not implemented, or is the icon intentionally blank? } }; - /** DOCUMENT ME! */ + /** The localised mnemonic for the "help" button. */ protected int helpButtonMnemonic; - /** DOCUMENT ME! */ + /** The localised text for the "help" button. */ protected String helpButtonText; - /** DOCUMENT ME! */ + /** The localised tool tip text for the help button. */ protected String helpButtonToolTipText; - /** DOCUMENT ME! */ + /** An icon representing the user's home folder. */ protected Icon homeFolderIcon = new Icon() { public int getIconHeight() @@ -753,7 +799,7 @@ public class BasicFileChooserUI extends FileChooserUI } }; - /** DOCUMENT ME! */ + /** An icon for the "list view" button. */ protected Icon listViewIcon = new Icon() { public int getIconHeight() @@ -795,37 +841,37 @@ public class BasicFileChooserUI extends FileChooserUI } }; - /** DOCUMENT ME! */ + /** An icon for the "new folder" button. */ protected Icon newFolderIcon = directoryIcon; - /** DOCUMENT ME! */ + /** The localised mnemonic for the "open" button. */ protected int openButtonMnemonic; - /** DOCUMENT ME! */ + /** The localised text for the "open" button. */ protected String openButtonText; - /** DOCUMENT ME! */ + /** The localised tool tip text for the "open" button. */ protected String openButtonToolTipText; - /** DOCUMENT ME! */ + /** The localised mnemonic for the "save" button. */ protected int saveButtonMnemonic; - /** DOCUMENT ME! */ + /** The localised text for the "save" button. */ protected String saveButtonText; - /** DOCUMENT ME! */ + /** The localised tool tip text for the save button. */ protected String saveButtonToolTipText; - /** DOCUMENT ME! */ + /** The localised mnemonic for the "update" button. */ protected int updateButtonMnemonic; - /** DOCUMENT ME! */ + /** The localised text for the "update" button. */ protected String updateButtonText; - /** DOCUMENT ME! */ + /** The localised tool tip text for the "update" button. */ protected String updateButtonToolTipText; - /** DOCUMENT ME! */ + /** An icon for the "up folder" button. */ protected Icon upFolderIcon = new Icon() { public int getIconHeight() @@ -876,77 +922,84 @@ public class BasicFileChooserUI extends FileChooserUI // -- begin private, but package local since used in inner classes -- + /** The file chooser component represented by this UI delegate. */ JFileChooser filechooser; - /** DOCUMENT ME! */ + /** The file list. */ JList filelist; - /** DOCUMENT ME! */ + /** The combo box used to display/select file filters. */ JComboBox filters; - /** DOCUMENT ME! */ + /** The model for the directory list. */ BasicDirectoryModel model; - /** DOCUMENT ME! */ + /** The file filter for all files. */ FileFilter acceptAll = new AcceptAllFileFilter(); - /** DOCUMENT ME! */ + /** The default file view. */ FileView fv = new BasicFileView(); - /** DOCUMENT ME! */ + /** The icon size. */ static final int ICON_SIZE = 24; - /** DOCUMENT ME! */ + /** A combo box for display/selection of parent directories. */ JComboBox parents; - /** DOCUMENT ME! */ + /** The current file name. */ String filename; - /** DOCUMENT ME! */ + /** The accept (open/save) button. */ JButton accept; - /** DOCUMENT ME! */ + /** The cancel button. */ JButton cancel; - /** DOCUMENT ME! */ + /** The button to move up to the parent directory. */ JButton upFolderButton; - /** DOCUMENT ME! */ + /** The button to create a new directory. */ JButton newFolderButton; - /** DOCUMENT ME! */ + /** The button to move to the user's home directory. */ JButton homeFolderButton; - /** DOCUMENT ME! */ + /** An optional accessory panel. */ JPanel accessoryPanel; - /** DOCUMENT ME! */ + /** A property change listener. */ PropertyChangeListener propertyChangeListener; - /** DOCUMENT ME! */ + /** The text describing the filter for "all files". */ String acceptAllFileFilterText; - /** DOCUMENT ME! */ + /** The text describing a directory type. */ String dirDescText; - /** DOCUMENT ME! */ + /** The text describing a file type. */ String fileDescText; - /** DOCUMENT ME! */ + /** Is a directory selected? */ boolean dirSelected = false; - /** DOCUMENT ME! */ + /** The current directory. */ File currDir = null; + // FIXME: describe what is contained in the bottom panel + /** The bottom panel. */ JPanel bottomPanel; - - /** DOCUMENT ME! */ + + /** The close panel. */ JPanel closePanel; + /** Text box that displays file name */ + JTextField entry; + + /** Current parent path */ + String parentPath; + // -- end private -- - private class ListLabelRenderer - extends JLabel - implements ListCellRenderer + private class ListLabelRenderer extends JLabel implements ListCellRenderer { /** DOCUMENT ME! */ final Color selected = new Color(153, 204, 255); @@ -988,45 +1041,8 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Closes the dialog. */ - public class CBLabelRenderer extends JLabel implements ListCellRenderer - { - /** - * Creates a new CBLabelRenderer object. - */ - public CBLabelRenderer() - { - super(); - setOpaque(true); - } - - /** - * DOCUMENT ME! - * - * @param list DOCUMENT ME! - * @param value DOCUMENT ME! - * @param index DOCUMENT ME! - * @param isSelected DOCUMENT ME! - * @param cellHasFocus DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - public Component getListCellRendererComponent(JList list, Object value, - int index, - boolean isSelected, - boolean cellHasFocus) - { - setHorizontalAlignment(SwingConstants.LEFT); - setIcon(directoryIcon); - setText(value.toString()); - setForeground(Color.BLACK); - setBackground(Color.WHITE); - - return this; - } - } - void closeDialog() { Window owner = SwingUtilities.windowForComponent(filechooser); @@ -1035,9 +1051,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * Creates a new BasicFileChooserUI object. + * Creates a new <code>BasicFileChooserUI</code> object. * - * @param b DOCUMENT ME! + * @param b the file chooser component. */ public BasicFileChooserUI(JFileChooser b) { @@ -1045,11 +1061,11 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns a UI delegate for the given component. * - * @param c DOCUMENT ME! + * @param c the component (should be a {@link JFileChooser}). * - * @return DOCUMENT ME! + * @return A new UI delegate. */ public static ComponentUI createUI(JComponent c) { @@ -1057,28 +1073,32 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! - * - * @param c DOCUMENT ME! + * Installs the UI for the specified component. + * + * @param c the component (should be a {@link JFileChooser}). */ public void installUI(JComponent c) { if (c instanceof JFileChooser) { - JFileChooser fc = (JFileChooser) c; - fc.resetChoosableFileFilters(); - createModel(); - clearIconCache(); - installDefaults(fc); - installComponents(fc); - installListeners(fc); + JFileChooser fc = (JFileChooser) c; + fc.resetChoosableFileFilters(); + createModel(); + clearIconCache(); + installDefaults(fc); + installComponents(fc); + installListeners(fc); + + Object path = filechooser.getCurrentDirectory(); + if (path != null) + parentPath = path.toString().substring(path.toString().lastIndexOf("/")); } } /** - * DOCUMENT ME! - * - * @param c DOCUMENT ME! + * Uninstalls this UI from the given component. + * + * @param c the component (should be a {@link JFileChooser}). */ public void uninstallUI(JComponent c) { @@ -1185,16 +1205,16 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates and install the subcomponents for the file chooser. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ public void installComponents(JFileChooser fc) { JLabel look = new JLabel("Look In:"); parents = new JComboBox(); - parents.setRenderer(new CBLabelRenderer()); + parents.setRenderer(new BasicComboBoxRenderer()); boxEntries(); look.setLabelFor(parents); JPanel parentsPanel = new JPanel(); @@ -1226,9 +1246,9 @@ public class BasicFileChooserUI extends FileChooserUI buttonPanel.add(detailsViewButton); JPanel topPanel = new JPanel(); - topPanel.setLayout(new java.awt.FlowLayout()); + parentsPanel.add(buttonPanel); + topPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0)); topPanel.add(parentsPanel); - topPanel.add(buttonPanel); accessoryPanel = new JPanel(); if (filechooser.getAccessory() != null) @@ -1260,7 +1280,7 @@ public class BasicFileChooserUI extends FileChooserUI JLabel fileNameLabel = new JLabel("File Name:"); JLabel fileTypesLabel = new JLabel("Files of Type:"); - JTextField entry = new JTextField(); + entry = new JTextField(); filters = new JComboBox(); filterEntries(); @@ -1309,9 +1329,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Uninstalls the components from the file chooser. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ public void uninstallComponents(JFileChooser fc) { @@ -1327,9 +1347,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Installs the listeners required by this UI delegate. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ protected void installListeners(JFileChooser fc) { @@ -1349,9 +1369,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Uninstalls the listeners previously installed by this UI delegate. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ protected void uninstallListeners(JFileChooser fc) { @@ -1360,9 +1380,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Installs the defaults for this UI delegate. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ protected void installDefaults(JFileChooser fc) { @@ -1371,9 +1391,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Uninstalls the defaults previously added by this UI delegate. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ protected void uninstallDefaults(JFileChooser fc) { @@ -1382,9 +1402,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Installs the icons for this UI delegate (NOT YET IMPLEMENTED). * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ protected void installIcons(JFileChooser fc) { @@ -1392,9 +1412,10 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Uninstalls the icons previously added by this UI delegate (NOT YET + * IMPLEMENTED). * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ protected void uninstallIcons(JFileChooser fc) { @@ -1402,9 +1423,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Installs the strings used by this UI delegate. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ protected void installStrings(JFileChooser fc) { @@ -1432,9 +1453,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Uninstalls the strings previously added by this UI delegate. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ protected void uninstallStrings(JFileChooser fc) { @@ -1460,7 +1481,7 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates a new directory model. */ protected void createModel() { @@ -1468,9 +1489,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the directory model. * - * @return DOCUMENT ME! + * @return The directory model. */ public BasicDirectoryModel getModel() { @@ -1478,115 +1499,131 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! - * - * @param fc DOCUMENT ME! - * - * @return DOCUMENT ME! + * Creates a listener to handle changes to the properties of the given + * file chooser component. + * + * @param fc the file chooser component. + * + * @return A new listener. */ public PropertyChangeListener createPropertyChangeListener(JFileChooser fc) { return new PropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent e) { - public void propertyChange(PropertyChangeEvent e) - { - // FIXME: Multiple file selection waiting on JList multiple selection bug. - if (e.getPropertyName().equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) - { - if (filechooser.getSelectedFile() == null) - setFileName(null); - else - setFileName(filechooser.getSelectedFile().toString()); - int index = -1; - File file = filechooser.getSelectedFile(); - for (index = 0; index < model.getSize(); index++) - if (((File) model.getElementAt(index)).equals(file)) - break; - if (index == -1) - return; - filelist.setSelectedIndex(index); - filelist.ensureIndexIsVisible(index); - filelist.revalidate(); - filelist.repaint(); - } - else if (e.getPropertyName().equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)) - { - filelist.clearSelection(); - filelist.revalidate(); - filelist.repaint(); - setDirectorySelected(false); - setDirectory(filechooser.getCurrentDirectory()); - boxEntries(); - } - else if (e.getPropertyName().equals(JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) - || e.getPropertyName().equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) - filterEntries(); - else if (e.getPropertyName().equals(JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY) - || e.getPropertyName().equals(JFileChooser.DIALOG_TITLE_CHANGED_PROPERTY)) - { - Window owner = SwingUtilities.windowForComponent(filechooser); - if (owner instanceof JDialog) - ((JDialog) owner).setTitle(getDialogTitle(filechooser)); - accept.setText(getApproveButtonText(filechooser)); - accept.setToolTipText(getApproveButtonToolTipText(filechooser)); - accept.setMnemonic(getApproveButtonMnemonic(filechooser)); - } - else if (e.getPropertyName().equals(JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY)) - accept.setText(getApproveButtonText(filechooser)); - else if (e.getPropertyName().equals(JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY)) - accept.setToolTipText(getApproveButtonToolTipText(filechooser)); - else if (e.getPropertyName().equals(JFileChooser.APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY)) - accept.setMnemonic(getApproveButtonMnemonic(filechooser)); - else if (e.getPropertyName().equals(JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY)) - { - if (filechooser.getControlButtonsAreShown()) - { - GridBagConstraints c = new GridBagConstraints(); - c.gridy = 1; - bottomPanel.add(filters, c); - - c.fill = GridBagConstraints.BOTH; - c.gridy = 2; - c.anchor = GridBagConstraints.EAST; - bottomPanel.add(closePanel, c); - bottomPanel.revalidate(); - bottomPanel.repaint(); - bottomPanel.doLayout(); - } - else - bottomPanel.remove(closePanel); - } - else if (e.getPropertyName().equals(JFileChooser.ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY)) - { - if (filechooser.isAcceptAllFileFilterUsed()) - filechooser.addChoosableFileFilter(getAcceptAllFileFilter(filechooser)); - else - filechooser.removeChoosableFileFilter(getAcceptAllFileFilter(filechooser)); - } - else if (e.getPropertyName().equals(JFileChooser.ACCESSORY_CHANGED_PROPERTY)) - { - JComponent old = (JComponent) e.getOldValue(); - if (old != null) - getAccessoryPanel().remove(old); - JComponent newval = (JComponent) e.getNewValue(); - if (newval != null) - getAccessoryPanel().add(newval); - } - if (e.getPropertyName().equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY) - || e.getPropertyName().equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY) - || e.getPropertyName().equals(JFileChooser.FILE_HIDING_CHANGED_PROPERTY)) - rescanCurrentDirectory(filechooser); - - filechooser.revalidate(); - filechooser.repaint(); - } - }; + // FIXME: Multiple file selection waiting on JList multiple selection + // bug. + if (e.getPropertyName().equals( + JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) + { + if (filechooser.getSelectedFile() == null) + setFileName(null); + else + setFileName(filechooser.getSelectedFile().toString()); + int index = -1; + File file = filechooser.getSelectedFile(); + for (index = 0; index < model.getSize(); index++) + if (((File) model.getElementAt(index)).equals(file)) + break; + if (index == -1) + return; + filelist.setSelectedIndex(index); + filelist.ensureIndexIsVisible(index); + filelist.revalidate(); + filelist.repaint(); + } + else if (e.getPropertyName().equals( + JFileChooser.DIRECTORY_CHANGED_PROPERTY)) + { + filelist.clearSelection(); + filelist.revalidate(); + filelist.repaint(); + setDirectorySelected(false); + setDirectory(filechooser.getCurrentDirectory()); + boxEntries(); + } + else if (e.getPropertyName().equals( + JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) + || e.getPropertyName().equals( + JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) + filterEntries(); + else if (e.getPropertyName().equals( + JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY) + || e.getPropertyName().equals( + JFileChooser.DIALOG_TITLE_CHANGED_PROPERTY)) + { + Window owner = SwingUtilities.windowForComponent(filechooser); + if (owner instanceof JDialog) + ((JDialog) owner).setTitle(getDialogTitle(filechooser)); + accept.setText(getApproveButtonText(filechooser)); + accept.setToolTipText(getApproveButtonToolTipText(filechooser)); + accept.setMnemonic(getApproveButtonMnemonic(filechooser)); + } + else if (e.getPropertyName().equals( + JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY)) + accept.setText(getApproveButtonText(filechooser)); + else if (e.getPropertyName().equals( + JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY)) + accept.setToolTipText(getApproveButtonToolTipText(filechooser)); + else if (e.getPropertyName().equals( + JFileChooser.APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY)) + accept.setMnemonic(getApproveButtonMnemonic(filechooser)); + else if (e.getPropertyName().equals( + JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY)) + { + if (filechooser.getControlButtonsAreShown()) + { + GridBagConstraints c = new GridBagConstraints(); + c.gridy = 1; + bottomPanel.add(filters, c); + + c.fill = GridBagConstraints.BOTH; + c.gridy = 2; + c.anchor = GridBagConstraints.EAST; + bottomPanel.add(closePanel, c); + bottomPanel.revalidate(); + bottomPanel.repaint(); + bottomPanel.doLayout(); + } + else + bottomPanel.remove(closePanel); + } + else if (e.getPropertyName().equals( + JFileChooser.ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY)) + { + if (filechooser.isAcceptAllFileFilterUsed()) + filechooser.addChoosableFileFilter(getAcceptAllFileFilter(filechooser)); + else + filechooser.removeChoosableFileFilter(getAcceptAllFileFilter(filechooser)); + } + else if (e.getPropertyName().equals( + JFileChooser.ACCESSORY_CHANGED_PROPERTY)) + { + JComponent old = (JComponent) e.getOldValue(); + if (old != null) + getAccessoryPanel().remove(old); + JComponent newval = (JComponent) e.getNewValue(); + if (newval != null) + getAccessoryPanel().add(newval); + } + if (e.getPropertyName().equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY) + || e.getPropertyName().equals( + JFileChooser.FILE_FILTER_CHANGED_PROPERTY) + || e.getPropertyName().equals( + JFileChooser.FILE_HIDING_CHANGED_PROPERTY)) + rescanCurrentDirectory(filechooser); + + filechooser.revalidate(); + filechooser.repaint(); + } + }; } /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! + * Returns the current file name. + * + * @return The current file name. */ public String getFileName() { @@ -1594,9 +1631,11 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the current directory name. * - * @return DOCUMENT ME! + * @return The directory name. + * + * @see #setDirectoryName(String) */ public String getDirectoryName() { @@ -1605,9 +1644,11 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Sets the file name. * - * @param filename DOCUMENT ME! + * @param filename the file name. + * + * @see #getFileName() */ public void setFileName(String filename) { @@ -1615,9 +1656,11 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Sets the directory name (NOT IMPLEMENTED). * - * @param dirname DOCUMENT ME! + * @param dirname the directory name. + * + * @see #getDirectoryName() */ public void setDirectoryName(String dirname) { @@ -1625,9 +1668,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Rescans the current directory. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ public void rescanCurrentDirectory(JFileChooser fc) { @@ -1636,10 +1679,10 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * NOT YET IMPLEMENTED. * - * @param fc DOCUMENT ME! - * @param f DOCUMENT ME! + * @param fc the file chooser. + * @param f the file. */ public void ensureFileIsVisible(JFileChooser fc, File f) { @@ -1647,9 +1690,10 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the {@link JFileChooser} component that this UI delegate + * represents. * - * @return DOCUMENT ME! + * @return The component represented by this UI delegate. */ public JFileChooser getFileChooser() { @@ -1657,9 +1701,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the optional accessory panel. * - * @return DOCUMENT ME! + * @return The optional accessory panel. */ public JPanel getAccessoryPanel() { @@ -1667,11 +1711,11 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates and returns an approve (open or save) button for the dialog. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. * - * @return DOCUMENT ME! + * @return The button. */ public JButton getApproveButton(JFileChooser fc) { @@ -1682,11 +1726,14 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the tool tip text for the approve (open/save) button. This first + * checks the file chooser to see if a value has been explicitly set - if + * not, a default value appropriate for the type of file chooser is + * returned. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. * - * @return DOCUMENT ME! + * @return The tool tip text. */ public String getApproveButtonToolTipText(JFileChooser fc) { @@ -1699,7 +1746,7 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Clears the icon cache. */ public void clearIconCache() { @@ -1708,11 +1755,11 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates a new listener to handle selections in the file list. * - * @param fc DOCUMENT ME! + * @param fc the file chooser component. * - * @return DOCUMENT ME! + * @return A new instance of {@link SelectionListener}. */ public ListSelectionListener createListSelectionListener(JFileChooser fc) { @@ -1720,12 +1767,12 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates a new listener to handle double-click events. * - * @param fc DOCUMENT ME! - * @param list DOCUMENT ME! + * @param fc the file chooser component. + * @param list the list. * - * @return DOCUMENT ME! + * @return A new instance of {@link DoubleClickListener}. */ protected MouseListener createDoubleClickListener(JFileChooser fc, JList list) { @@ -1733,9 +1780,10 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns <code>true</code> if a directory is selected, and + * <code>false</code> otherwise. * - * @return DOCUMENT ME! + * @return A boolean. */ protected boolean isDirectorySelected() { @@ -1743,9 +1791,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Sets the flag that indicates whether the current directory is selected. * - * @param selected DOCUMENT ME! + * @param selected the new flag value. */ protected void setDirectorySelected(boolean selected) { @@ -1753,9 +1801,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the current directory. * - * @return DOCUMENT ME! + * @return The current directory. */ protected File getDirectory() { @@ -1763,9 +1811,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Sets the current directory. * - * @param f DOCUMENT ME! + * @param f the directory. */ protected void setDirectory(File f) { @@ -1773,11 +1821,11 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the "accept all" file filter. * - * @param fc DOCUMENT ME! + * @param fc the file chooser component. * - * @return DOCUMENT ME! + * @return The "accept all" file filter. */ public FileFilter getAcceptAllFileFilter(JFileChooser fc) { @@ -1785,25 +1833,29 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the file view for the file chooser. This returns either the + * file view that has been explicitly set for the {@link JFileChooser}, or + * a default file view. * - * @param fc DOCUMENT ME! + * @param fc the file chooser component. * - * @return DOCUMENT ME! + * @return The file view. + * + * @see JFileChooser#getFileView() */ public FileView getFileView(JFileChooser fc) { - if (fc.getFileView() != null) - return fc.getFileView(); return fv; } /** - * DOCUMENT ME! + * Returns the dialog title. * - * @param fc DOCUMENT ME! + * @param fc the file chooser (<code>null</code> not permitted). * - * @return DOCUMENT ME! + * @return The dialog title. + * + * @see JFileChooser#getDialogTitle() */ public String getDialogTitle(JFileChooser fc) { @@ -1828,11 +1880,13 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the approve button mnemonic. * - * @param fc DOCUMENT ME! + * @param fc the file chooser (<code>null</code> not permitted). * - * @return DOCUMENT ME! + * @return The approve button mnemonic. + * + * @see JFileChooser#getApproveButtonMnemonic() */ public int getApproveButtonMnemonic(JFileChooser fc) { @@ -1845,11 +1899,13 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the approve button text. * - * @param fc DOCUMENT ME! + * @param fc the file chooser (<code>null</code> not permitted). * - * @return DOCUMENT ME! + * @return The approve button text. + * + * @see JFileChooser#getApproveButtonText() */ public String getApproveButtonText(JFileChooser fc) { @@ -1862,9 +1918,10 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates and returns a new action that will be used with the "new folder" + * button. * - * @return DOCUMENT ME! + * @return A new instance of {@link GoHomeAction}. */ public Action getNewFolderAction() { @@ -1872,9 +1929,10 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates and returns a new action that will be used with the "home folder" + * button. * - * @return DOCUMENT ME! + * @return A new instance of {@link GoHomeAction}. */ public Action getGoHomeAction() { @@ -1882,9 +1940,10 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates and returns a new action that will be used with the "up folder" + * button. * - * @return DOCUMENT ME! + * @return A new instance of {@link ChangeToParentDirectoryAction}. */ public Action getChangeToParentDirectoryAction() { @@ -1892,9 +1951,10 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates and returns a new action that will be used with the "approve" + * button. * - * @return DOCUMENT ME! + * @return A new instance of {@link ApproveSelectionAction}. */ public Action getApproveSelectionAction() { @@ -1902,9 +1962,10 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates and returns a new action that will be used with the "cancel" + * button. * - * @return DOCUMENT ME! + * @return A new instance of {@link CancelSelectionAction}. */ public Action getCancelSelectionAction() { @@ -1912,9 +1973,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates and returns a new instance of {@link UpdateAction}. * - * @return DOCUMENT ME! + * @return An action. */ public Action getUpdateAction() { diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java index 3abd76fe2d3..9c7f1c4c5d1 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java @@ -1,5 +1,5 @@ /* BasicFormattedTextFieldUI.java - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -39,6 +39,7 @@ exception statement from your version. */ package javax.swing.plaf.basic; import javax.swing.JComponent; +import javax.swing.UIDefaults; import javax.swing.plaf.ComponentUI; /** @@ -48,6 +49,7 @@ public class BasicFormattedTextFieldUI extends BasicTextFieldUI { public BasicFormattedTextFieldUI() { + // Nothing to do here. } public static ComponentUI createUI(JComponent c) @@ -55,6 +57,11 @@ public class BasicFormattedTextFieldUI extends BasicTextFieldUI return new BasicFormattedTextFieldUI(); } + /** + * Returns the prefix for entries in the {@link UIDefaults} table. + * + * @return "FormattedTextField" + */ protected String getPropertyPrefix() { return "FormattedTextField"; diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java b/libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java index 757ac47c903..068de345bec 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java @@ -71,6 +71,7 @@ public class BasicGraphicsUtils */ public BasicGraphicsUtils() { + // Nothing to do here. } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java b/libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java index 56a67b02935..6debd649509 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java @@ -41,7 +41,6 @@ package javax.swing.plaf.basic; import java.awt.Color; import java.awt.Component; import java.awt.Graphics; -import java.awt.Polygon; import java.io.Serializable; import javax.swing.Icon; @@ -241,34 +240,33 @@ public class BasicIconFactory implements Serializable { return new DummyIcon(); } + + /** + * Returns a new instance of a 4 x 8 icon showing a small black triangle that + * points to the right. This is displayed in menu items that have a + * sub menu. + * + * @return The icon. + */ public static Icon getMenuArrowIcon() { return new Icon() { public int getIconHeight() { - return 12; + return 8; } - public int getIconWidth() { - return 12; + return 4; } - public void paintIcon(Component c, Graphics g, int x, int y) { - g.translate(x, y); - Color saved = g.getColor(); - g.setColor(Color.BLACK); - - g.fillPolygon(new Polygon(new int[] { 3, 9, 3 }, - new int[] { 2, 6, 10 }, - 3)); - + for (int i = 0; i < 4; i++) + g.drawLine(x + i, y + i, x + i, y + 7 - i); g.setColor(saved); - g.translate(-x, -y); } }; } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java index cc262948ded..73d3e6173d3 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java @@ -84,6 +84,14 @@ public class BasicInternalFrameTitlePane extends JComponent public class CloseAction extends AbstractAction { /** + * Creates a new action. + */ + public CloseAction() + { + super("Close"); + } + + /** * This method is called when something closes the JInternalFrame. * * @param e The ActionEvent. @@ -92,13 +100,14 @@ public class BasicInternalFrameTitlePane extends JComponent { if (frame.isClosable()) { - try - { - frame.setClosed(true); - } - catch (PropertyVetoException pve) - { - } + try + { + frame.setClosed(true); + } + catch (PropertyVetoException pve) + { + // We do nothing if the attempt has been vetoed. + } } } } @@ -113,6 +122,14 @@ public class BasicInternalFrameTitlePane extends JComponent public class IconifyAction extends AbstractAction { /** + * Creates a new action. + */ + public IconifyAction() + { + super("Minimize"); + } + + /** * This method is called when the user wants to iconify the * JInternalFrame. * @@ -122,13 +139,14 @@ public class BasicInternalFrameTitlePane extends JComponent { if (frame.isIconifiable() && ! frame.isIcon()) { - try - { - frame.setIcon(true); - } - catch (PropertyVetoException pve) - { - } + try + { + frame.setIcon(true); + } + catch (PropertyVetoException pve) + { + // We do nothing if the attempt has been vetoed. + } } } } @@ -143,6 +161,13 @@ public class BasicInternalFrameTitlePane extends JComponent public class MaximizeAction extends AbstractAction { /** + * Creates a new action. + */ + public MaximizeAction() + { + super("Maximize"); + } + /** * This method is called when the user wants to maximize the * JInternalFrame. * @@ -152,13 +177,14 @@ public class BasicInternalFrameTitlePane extends JComponent { try { - if (frame.isMaximizable() && ! frame.isMaximum()) - frame.setMaximum(true); - else if (frame.isMaximum()) - frame.setMaximum(false); + if (frame.isMaximizable() && ! frame.isMaximum()) + frame.setMaximum(true); + else if (frame.isMaximum()) + frame.setMaximum(false); } catch (PropertyVetoException pve) { + // We do nothing if the attempt has been vetoed. } } } @@ -173,6 +199,13 @@ public class BasicInternalFrameTitlePane extends JComponent public class MoveAction extends AbstractAction { /** + * Creates a new action. + */ + public MoveAction() + { + super("Move"); + } + /** * This method is called when the user wants to drag the JInternalFrame. * * @param e The ActionEvent. @@ -194,6 +227,13 @@ public class BasicInternalFrameTitlePane extends JComponent public class RestoreAction extends AbstractAction { /** + * Creates a new action. + */ + public RestoreAction() + { + super("Restore"); + } + /** * This method is called when the user wants to restore the * JInternalFrame. * @@ -203,13 +243,14 @@ public class BasicInternalFrameTitlePane extends JComponent { if (frame.isMaximum()) { - try - { - frame.setMaximum(false); - } - catch (PropertyVetoException pve) - { - } + try + { + frame.setMaximum(false); + } + catch (PropertyVetoException pve) + { + // We do nothing if the attempt has been vetoed. + } } } } @@ -224,6 +265,13 @@ public class BasicInternalFrameTitlePane extends JComponent public class SizeAction extends AbstractAction { /** + * Creates a new action. + */ + public SizeAction() + { + super("Size"); + } + /** * This method is called when the user wants to resize the JInternalFrame. * * @param e The ActionEvent. @@ -377,24 +425,26 @@ public class BasicInternalFrameTitlePane extends JComponent int loc = width + insets.left - 1; int top = insets.top + 1; - int buttonWidth = height - 2; int buttonHeight = height - 4; if (closeButton.isVisible()) { - loc -= buttonWidth + 2; - closeButton.setBounds(loc, top, buttonWidth, buttonHeight); + int buttonWidth = closeIcon.getIconWidth(); + loc -= buttonWidth + 2; + closeButton.setBounds(loc, top, buttonWidth, buttonHeight); } if (maxButton.isVisible()) { - loc -= buttonWidth + 2; - maxButton.setBounds(loc, top, buttonWidth, buttonHeight); + int buttonWidth = maxIcon.getIconWidth(); + loc -= buttonWidth + 2; + maxButton.setBounds(loc, top, buttonWidth, buttonHeight); } if (iconButton.isVisible()) { - loc -= buttonWidth + 2; - iconButton.setBounds(loc, top, buttonWidth, buttonHeight); + int buttonWidth = iconIcon.getIconWidth(); + loc -= buttonWidth + 2; + iconButton.setBounds(loc, top, buttonWidth, buttonHeight); } if (title != null) @@ -435,6 +485,7 @@ public class BasicInternalFrameTitlePane extends JComponent */ public void removeLayoutComponent(Component c) { + // Nothing to do here. } } @@ -466,6 +517,7 @@ public class BasicInternalFrameTitlePane extends JComponent // These buttons cannot be given focus. return false; } + } /** The action command for the Close action. */ @@ -522,6 +574,9 @@ public class BasicInternalFrameTitlePane extends JComponent /** The icon displayed in the iconify button. */ protected Icon iconIcon = BasicIconFactory.createEmptyFrameIcon(); + /** The icon displayed in the close button. */ + protected Icon closeIcon; + /** The JInternalFrame that this TitlePane is used in. */ protected JInternalFrame frame; @@ -645,7 +700,7 @@ public class BasicInternalFrameTitlePane extends JComponent */ protected void installListeners() { - propertyChangeListener = new PropertyChangeHandler(); + propertyChangeListener = createPropertyChangeListener(); frame.addPropertyChangeListener(propertyChangeListener); } @@ -663,14 +718,17 @@ public class BasicInternalFrameTitlePane extends JComponent */ protected void installDefaults() { - // FIXME: move icons to defaults. UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - setFont(defaults.getFont("InternalFrame.titleFont")); + title.setFont(defaults.getFont("InternalFrame.titleFont")); selectedTextColor = defaults.getColor("InternalFrame.activeTitleForeground"); selectedTitleColor = defaults.getColor("InternalFrame.activeTitleBackground"); notSelectedTextColor = defaults.getColor("InternalFrame.inactiveTitleForeground"); notSelectedTitleColor = defaults.getColor("InternalFrame.inactiveTitleBackground"); + + closeIcon = UIManager.getIcon("InternalFrame.closeIcon"); + iconIcon = UIManager.getIcon("InternalFrame.iconifyIcon"); + maxIcon = UIManager.getIcon("InternalFrame.maximizeIcon"); } /** @@ -683,6 +741,10 @@ public class BasicInternalFrameTitlePane extends JComponent selectedTitleColor = null; notSelectedTextColor = null; notSelectedTitleColor = null; + + closeIcon = null; + iconIcon = null; + maxIcon = null; } /** @@ -691,12 +753,15 @@ public class BasicInternalFrameTitlePane extends JComponent protected void createButtons() { closeButton = new PaneButton(closeAction); + closeButton.setText(null); if (!frame.isClosable()) closeButton.setVisible(false); iconButton = new PaneButton(iconifyAction); + iconButton.setText(null); if (!frame.isIconifiable()) iconButton.setVisible(false); maxButton = new PaneButton(maximizeAction); + maxButton.setText(null); if (!frame.isMaximizable()) maxButton.setVisible(false); } @@ -706,15 +771,12 @@ public class BasicInternalFrameTitlePane extends JComponent */ protected void setButtonIcons() { - Icon icon = UIManager.getIcon("InternalFrame.closeIcon"); - if (icon != null) - closeButton.setIcon(icon); - icon = UIManager.getIcon("InternalFrame.iconifyIcon"); - if (icon != null) - iconButton.setIcon(icon); - icon = UIManager.getIcon("InternalFrame.maximizeIcon"); - if (icon != null) - maxButton.setIcon(icon); + if (closeIcon != null && closeButton != null) + closeButton.setIcon(closeIcon); + if (iconIcon != null && iconButton != null) + iconButton.setIcon(iconIcon); + if (maxIcon != null && maxButton != null) + maxButton.setIcon(maxIcon); } /** @@ -816,11 +878,12 @@ public class BasicInternalFrameTitlePane extends JComponent public void paintComponent(Graphics g) { paintTitleBackground(g); - Font f = g.getFont(); - FontMetrics fm = g.getFontMetrics(f); if (frame.getTitle() != null && title != null) { Color saved = g.getColor(); + Font f = title.getFont(); + g.setFont(f); + FontMetrics fm = g.getFontMetrics(f); if (frame.isSelected()) g.setColor(selectedTextColor); else diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java index 8f76ea0cc19..d9dadda688a 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java @@ -56,20 +56,17 @@ import java.beans.PropertyChangeListener; import java.beans.PropertyVetoException; import java.beans.VetoableChangeListener; -import javax.swing.BorderFactory; import javax.swing.DefaultDesktopManager; import javax.swing.DesktopManager; import javax.swing.JComponent; import javax.swing.JDesktopPane; import javax.swing.JInternalFrame; import javax.swing.KeyStroke; +import javax.swing.LookAndFeel; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; -import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.border.AbstractBorder; -import javax.swing.border.BevelBorder; -import javax.swing.border.Border; import javax.swing.event.InternalFrameEvent; import javax.swing.event.InternalFrameListener; import javax.swing.event.MouseInputAdapter; @@ -202,67 +199,66 @@ public class BasicInternalFrameUI extends InternalFrameUI */ public void mouseDragged(MouseEvent e) { - // If the frame is maximized, there is nothing that + // If the frame is maximized, there is nothing that // can be dragged around. if (frame.isMaximum()) - return; + return; DesktopManager dm = getDesktopManager(); Rectangle b = frame.getBounds(); Dimension min = frame.getMinimumSize(); if (min == null) - min = new Dimension(0, 0); + min = new Dimension(0, 0); Insets insets = frame.getInsets(); int x = e.getX(); int y = e.getY(); if (e.getSource() == frame && frame.isResizable()) { - switch (direction) - { - case NORTH: - cacheRect.setBounds(b.x, - Math.min(b.y + y, b.y + b.height - - min.height), b.width, b.height - - y); - break; - case NORTH_EAST: - cacheRect.setBounds(b.x, - Math.min(b.y + y, b.y + b.height - - min.height), x, b.height - y); - break; - case EAST: - cacheRect.setBounds(b.x, b.y, x, b.height); - break; - case SOUTH_EAST: - cacheRect.setBounds(b.x, b.y, x, y); - break; - case SOUTH: - cacheRect.setBounds(b.x, b.y, b.width, y); - break; - case SOUTH_WEST: - cacheRect.setBounds(Math.min(b.x + x, b.x + b.width - min.width), - b.y, b.width - x, y); - break; - case WEST: - cacheRect.setBounds(Math.min(b.x + x, b.x + b.width - min.width), - b.y, b.width - x, b.height); - break; - case NORTH_WEST: - cacheRect.setBounds(Math.min(b.x + x, b.x + b.width - min.width), - Math.min(b.y + y, b.y + b.height - - min.height), b.width - x, - b.height - y); - break; - } - dm.resizeFrame(frame, cacheRect.x, cacheRect.y, - Math.max(min.width, cacheRect.width), - Math.max(min.height, cacheRect.height)); + switch (direction) + { + case NORTH: + cacheRect.setBounds(b.x, Math.min(b.y + y, b.y + b.height + - min.height), + b.width, b.height - y); + break; + case NORTH_EAST: + cacheRect.setBounds(b.x, Math.min(b.y + y, b.y + b.height + - min.height), x, + b.height - y); + break; + case EAST: + cacheRect.setBounds(b.x, b.y, x, b.height); + break; + case SOUTH_EAST: + cacheRect.setBounds(b.x, b.y, x, y); + break; + case SOUTH: + cacheRect.setBounds(b.x, b.y, b.width, y); + break; + case SOUTH_WEST: + cacheRect.setBounds(Math.min(b.x + x, b.x + b.width - min.width), + b.y, b.width - x, y); + break; + case WEST: + cacheRect.setBounds(Math.min(b.x + x, b.x + b.width - min.width), + b.y, b.width - x, b.height); + break; + case NORTH_WEST: + cacheRect.setBounds( + Math.min(b.x + x, b.x + b.width - min.width), + Math.min(b.y + y, b.y + b.height - min.height), + b.width - x, b.height - y); + break; + } + dm.resizeFrame(frame, cacheRect.x, cacheRect.y, + Math.max(min.width, cacheRect.width), + Math.max(min.height, cacheRect.height)); } else if (e.getSource() == titlePane) { - Rectangle fBounds = frame.getBounds(); + Rectangle fBounds = frame.getBounds(); - dm.dragFrame(frame, e.getX() - xOffset + b.x, - e.getY() - yOffset + b.y); + dm.dragFrame(frame, e.getX() - xOffset + b.x, e.getY() - yOffset + + b.y); } } @@ -304,17 +300,17 @@ public class BasicInternalFrameUI extends InternalFrameUI if (e.getSource() == frame && frame.isResizable()) { - direction = sectionOfClick(x, y); - dm.beginResizingFrame(frame, direction); + direction = sectionOfClick(x, y); + dm.beginResizingFrame(frame, direction); } else if (e.getSource() == titlePane) { - Rectangle tBounds = titlePane.getBounds(); + Rectangle tBounds = titlePane.getBounds(); - xOffset = e.getX() - tBounds.x + insets.left; - yOffset = e.getY() - tBounds.y + insets.top; + xOffset = e.getX() - tBounds.x + insets.left; + yOffset = e.getY() - tBounds.y + insets.top; - dm.beginDraggingFrame(frame); + dm.beginDraggingFrame(frame); } } @@ -329,9 +325,9 @@ public class BasicInternalFrameUI extends InternalFrameUI xOffset = 0; yOffset = 0; if (e.getSource() == frame && frame.isResizable()) - dm.endResizingFrame(frame); + dm.endResizingFrame(frame); else if (e.getSource() == titlePane) - dm.endDraggingFrame(frame); + dm.endDraggingFrame(frame); } /** @@ -348,21 +344,21 @@ public class BasicInternalFrameUI extends InternalFrameUI Insets insets = frame.getInsets(); Rectangle b = frame.getBounds(); if (x < insets.left && y < insets.top) - return NORTH_WEST; + return NORTH_WEST; else if (x > b.width - insets.right && y < insets.top) - return NORTH_EAST; + return NORTH_EAST; else if (x > b.width - insets.right && y > b.height - insets.bottom) - return SOUTH_EAST; + return SOUTH_EAST; else if (x < insets.left && y > b.height - insets.bottom) - return SOUTH_WEST; + return SOUTH_WEST; else if (y < insets.top) - return NORTH; + return NORTH; else if (x < insets.left) - return WEST; + return WEST; else if (y > b.height - insets.bottom) - return SOUTH; + return SOUTH; else if (x > b.width - insets.right) - return EAST; + return EAST; return -1; } @@ -377,8 +373,9 @@ public class BasicInternalFrameUI extends InternalFrameUI { /** * This method is called when the JDesktopPane is hidden. - * - * @param e The ComponentEvent fired. + * + * @param e + * The ComponentEvent fired. */ public void componentHidden(ComponentEvent e) { @@ -387,8 +384,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method is called when the JDesktopPane is moved. - * - * @param e The ComponentEvent fired. + * + * @param e + * The ComponentEvent fired. */ public void componentMoved(ComponentEvent e) { @@ -397,22 +395,23 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method is called when the JDesktopPane is resized. - * - * @param e The ComponentEvent fired. + * + * @param e + * The ComponentEvent fired. */ public void componentResized(ComponentEvent e) { if (frame.isMaximum()) { - JDesktopPane pane = (JDesktopPane) e.getSource(); - Insets insets = pane.getInsets(); - Rectangle bounds = pane.getBounds(); - - frame.setBounds(bounds.x + insets.left, bounds.y + insets.top, - bounds.width - insets.left - insets.right, - bounds.height - insets.top - insets.bottom); - frame.revalidate(); - frame.repaint(); + JDesktopPane pane = (JDesktopPane) e.getSource(); + Insets insets = pane.getInsets(); + Rectangle bounds = pane.getBounds(); + + frame.setBounds(bounds.x + insets.left, bounds.y + insets.top, + bounds.width - insets.left - insets.right, + bounds.height - insets.top - insets.bottom); + frame.revalidate(); + frame.repaint(); } // Sun also resizes the icons. but it doesn't seem to do anything. @@ -420,8 +419,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method is called when the JDesktopPane is shown. - * - * @param e The ComponentEvent fired. + * + * @param e + * The ComponentEvent fired. */ public void componentShown(ComponentEvent e) { @@ -435,21 +435,25 @@ public class BasicInternalFrameUI extends InternalFrameUI public class InternalFrameLayout implements LayoutManager { /** - * This method is called when the given Component is added to the + * This method is called when the given Component is added to the * JInternalFrame. - * - * @param name The name of the Component. - * @param c The Component added. + * + * @param name + * The name of the Component. + * @param c + * The Component added. */ public void addLayoutComponent(String name, Component c) { + // Nothing to do here. } /** * This method is used to set the bounds of the children of the * JInternalFrame. - * - * @param c The Container to lay out. + * + * @param c + * The Container to lay out. */ public void layoutContainer(Container c) { @@ -468,38 +472,38 @@ public class BasicInternalFrameUI extends InternalFrameUI if (northPane != null) { - Dimension nDims = northPane.getPreferredSize(); - nh = Math.min(nDims.height, dims.height); + Dimension nDims = northPane.getPreferredSize(); + nh = Math.min(nDims.height, dims.height); - northPane.setBounds(insets.left, insets.top, dims.width, nh); + northPane.setBounds(insets.left, insets.top, dims.width, nh); } if (southPane != null) { - Dimension sDims = southPane.getPreferredSize(); - sh = Math.min(sDims.height, dims.height - nh); + Dimension sDims = southPane.getPreferredSize(); + sh = Math.min(sDims.height, dims.height - nh); - southPane.setBounds(insets.left, insets.top + dims.height - sh, - dims.width, sh); + southPane.setBounds(insets.left, insets.top + dims.height - sh, + dims.width, sh); } int remHeight = dims.height - sh - nh; if (westPane != null) { - Dimension wDims = westPane.getPreferredSize(); - ww = Math.min(dims.width, wDims.width); + Dimension wDims = westPane.getPreferredSize(); + ww = Math.min(dims.width, wDims.width); - westPane.setBounds(insets.left, insets.top + nh, ww, remHeight); + westPane.setBounds(insets.left, insets.top + nh, ww, remHeight); } if (eastPane != null) { - Dimension eDims = eastPane.getPreferredSize(); - ew = Math.min(eDims.width, dims.width - ww); + Dimension eDims = eastPane.getPreferredSize(); + ew = Math.min(eDims.width, dims.width - ww); - eastPane.setBounds(insets.left + dims.width - ew, insets.top + nh, - ew, remHeight); + eastPane.setBounds(insets.left + dims.width - ew, insets.top + nh, + ew, remHeight); } int remWidth = dims.width - ww - ew; @@ -510,9 +514,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method returns the minimum layout size. - * - * @param c The Container to find a minimum layout size for. - * + * + * @param c + * The Container to find a minimum layout size for. * @return The minimum dimensions for the JInternalFrame. */ public Dimension minimumLayoutSize(Container c) @@ -522,9 +526,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method returns the maximum layout size. - * - * @param c The Container to find a maximum layout size for. - * + * + * @param c + * The Container to find a maximum layout size for. * @return The maximum dimensions for the JInternalFrame. */ public Dimension maximumLayoutSize(Container c) @@ -534,9 +538,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * Th8is method returns the preferred layout size. - * - * @param c The Container to find a preferred layout size for. - * + * + * @param c + * The Container to find a preferred layout size for. * @return The preferred dimensions for the JInternalFrame. */ public Dimension preferredLayoutSize(Container c) @@ -546,10 +550,11 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * DOCUMENT ME! - * - * @param c DOCUMENT ME! - * @param min DOCUMENT ME! - * + * + * @param c + * DOCUMENT ME! + * @param min + * DOCUMENT ME! * @return DOCUMENT ME! */ private Dimension getSize(Container c, boolean min) @@ -558,7 +563,7 @@ public class BasicInternalFrameUI extends InternalFrameUI Dimension contentDims = frame.getContentPane().getPreferredSize(); if (min) - contentDims.width = contentDims.height = 0; + contentDims.width = contentDims.height = 0; int nWidth = 0; int nHeight = 0; int sWidth = 0; @@ -571,42 +576,42 @@ public class BasicInternalFrameUI extends InternalFrameUI if (northPane != null) { - dims = northPane.getPreferredSize(); - if (dims != null) - { - nWidth = dims.width; - nHeight = dims.height; - } + dims = northPane.getPreferredSize(); + if (dims != null) + { + nWidth = dims.width; + nHeight = dims.height; + } } if (southPane != null) { - dims = southPane.getPreferredSize(); - if (dims != null) - { - sWidth = dims.width; - sHeight = dims.height; - } + dims = southPane.getPreferredSize(); + if (dims != null) + { + sWidth = dims.width; + sHeight = dims.height; + } } if (eastPane != null) { - dims = eastPane.getPreferredSize(); - if (dims != null) - { - sWidth = dims.width; - sHeight = dims.height; - } + dims = eastPane.getPreferredSize(); + if (dims != null) + { + sWidth = dims.width; + sHeight = dims.height; + } } if (westPane != null) { - dims = westPane.getPreferredSize(); - if (dims != null) - { - wWidth = dims.width; - wHeight = dims.height; - } + dims = westPane.getPreferredSize(); + if (dims != null) + { + wWidth = dims.width; + wHeight = dims.height; + } } int width = Math.max(sWidth, nWidth); @@ -630,6 +635,7 @@ public class BasicInternalFrameUI extends InternalFrameUI */ public void removeLayoutComponent(Component c) { + // Nothing to do here. } } @@ -657,8 +663,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method is called when the mouse enters the glass pane. - * - * @param e The MouseEvent. + * + * @param e + * The MouseEvent. */ public void mouseEntered(MouseEvent e) { @@ -667,8 +674,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method is called when the mouse is clicked on the glass pane. - * - * @param e The MouseEvent. + * + * @param e + * The MouseEvent. */ public void mouseClicked(MouseEvent e) { @@ -677,8 +685,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method is called when the mouse is dragged in the glass pane. - * - * @param e The MouseEvent. + * + * @param e + * The MouseEvent. */ public void mouseDragged(MouseEvent e) { @@ -687,8 +696,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method is called when the mouse exits the glass pane. - * - * @param e The MouseEvent. + * + * @param e + * The MouseEvent. */ public void mouseExited(MouseEvent e) { @@ -697,8 +707,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method is called when the mouse is moved in the glass pane. - * - * @param e The MouseEvent. + * + * @param e + * The MouseEvent. */ public void mouseMoved(MouseEvent e) { @@ -706,9 +717,10 @@ public class BasicInternalFrameUI extends InternalFrameUI } /** - * This method is called when the mouse is pressed in the glass pane. - * - * @param e The MouseEvent. + * This method is called when the mouse is pressed in the glass pane. + * + * @param e + * The MouseEvent. */ public void mousePressed(MouseEvent e) { @@ -717,9 +729,10 @@ public class BasicInternalFrameUI extends InternalFrameUI } /** - * This method is called when the mouse is released in the glass pane. - * - * @param e The MouseEvent. + * This method is called when the mouse is released in the glass pane. + * + * @param e + * The MouseEvent. */ public void mouseReleased(MouseEvent e) { @@ -727,10 +740,10 @@ public class BasicInternalFrameUI extends InternalFrameUI } /** - * This method acquires a candidate component to dispatch the MouseEvent - * to. - * - * @param me The MouseEvent to acquire a component for. + * This method acquires a candidate component to dispatch the MouseEvent to. + * + * @param me + * The MouseEvent to acquire a component for. */ private void acquireComponentForMouseEvent(MouseEvent me) { @@ -738,134 +751,137 @@ public class BasicInternalFrameUI extends InternalFrameUI int y = me.getY(); // Find the candidate which should receive this event. - Component parent = frame.getContentPane(); + Component parent = frame.getLayeredPane(); if (parent == null) - return; + return; Component candidate = null; Point p = me.getPoint(); while (candidate == null && parent != null) { - candidate = SwingUtilities.getDeepestComponentAt(parent, p.x, p.y); - if (candidate == null) - { - p = SwingUtilities.convertPoint(parent, p.x, p.y, - parent.getParent()); - parent = parent.getParent(); - } + candidate = SwingUtilities.getDeepestComponentAt(parent, p.x, p.y); + if (candidate == null) + { + p = SwingUtilities.convertPoint(parent, p.x, p.y, + parent.getParent()); + parent = parent.getParent(); + } } // If the only candidate we found was the native container itself, - // don't dispatch any event at all. We only care about the lightweight + // don't dispatch any event at all. We only care about the lightweight // children here. if (candidate == frame.getContentPane()) - candidate = null; + candidate = null; // If our candidate is new, inform the old target we're leaving. if (lastComponentEntered != null && lastComponentEntered.isShowing() && lastComponentEntered != candidate) { - Point tp = SwingUtilities.convertPoint(frame.getContentPane(), x, y, - lastComponentEntered); - MouseEvent exited = new MouseEvent(lastComponentEntered, - MouseEvent.MOUSE_EXITED, - me.getWhen(), me.getModifiersEx(), - tp.x, tp.y, me.getClickCount(), - me.isPopupTrigger(), - me.getButton()); + Point tp = SwingUtilities.convertPoint(frame.getContentPane(), x, y, + lastComponentEntered); + MouseEvent exited = new MouseEvent(lastComponentEntered, + MouseEvent.MOUSE_EXITED, + me.getWhen(), me.getModifiersEx(), + tp.x, tp.y, me.getClickCount(), + me.isPopupTrigger(), + me.getButton()); tempComponent = lastComponentEntered; - lastComponentEntered = null; - tempComponent.dispatchEvent(exited); + lastComponentEntered = null; + tempComponent.dispatchEvent(exited); } // If we have a candidate, maybe enter it. if (candidate != null) { - mouseEventTarget = candidate; - if (candidate.isLightweight() && candidate.isShowing() - && candidate != frame.getContentPane() - && candidate != lastComponentEntered) - { - lastComponentEntered = mouseEventTarget; - Point cp = SwingUtilities.convertPoint(frame.getContentPane(), - x, y, lastComponentEntered); - MouseEvent entered = new MouseEvent(lastComponentEntered, - MouseEvent.MOUSE_ENTERED, - me.getWhen(), - me.getModifiersEx(), cp.x, - cp.y, me.getClickCount(), - me.isPopupTrigger(), - me.getButton()); - lastComponentEntered.dispatchEvent(entered); - } + mouseEventTarget = candidate; + if (candidate.isLightweight() && candidate.isShowing() + && candidate != frame.getContentPane() + && candidate != lastComponentEntered) + { + lastComponentEntered = mouseEventTarget; + Point cp = SwingUtilities.convertPoint(frame.getContentPane(), x, + y, lastComponentEntered); + MouseEvent entered = new MouseEvent(lastComponentEntered, + MouseEvent.MOUSE_ENTERED, + me.getWhen(), + me.getModifiersEx(), cp.x, + cp.y, me.getClickCount(), + me.isPopupTrigger(), + me.getButton()); + lastComponentEntered.dispatchEvent(entered); + } } if (me.getID() == MouseEvent.MOUSE_RELEASED || me.getID() == MouseEvent.MOUSE_PRESSED && pressCount > 0 || me.getID() == MouseEvent.MOUSE_DRAGGED) - // If any of the following events occur while a button is held down, - // they should be dispatched to the same component to which the - // original MOUSE_PRESSED event was dispatched: - // - MOUSE_RELEASED - // - MOUSE_PRESSED: another button pressed while the first is held down - // - MOUSE_DRAGGED - mouseEventTarget = pressedComponent; + // If any of the following events occur while a button is held down, + // they should be dispatched to the same component to which the + // original MOUSE_PRESSED event was dispatched: + // - MOUSE_RELEASED + // - MOUSE_PRESSED: another button pressed while the first is held down + // - MOUSE_DRAGGED + mouseEventTarget = pressedComponent; else if (me.getID() == MouseEvent.MOUSE_CLICKED) { - // Don't dispatch CLICKED events whose target is not the same as the - // target for the original PRESSED event. - if (candidate != pressedComponent) - mouseEventTarget = null; - else if (pressCount == 0) - pressedComponent = null; + // Don't dispatch CLICKED events whose target is not the same as the + // target for the original PRESSED event. + if (candidate != pressedComponent) + mouseEventTarget = null; + else if (pressCount == 0) + pressedComponent = null; } } /** - * This is a helper method that dispatches the GlassPane MouseEvents to - * the proper component. - * - * @param e The AWTEvent to be dispatched. Usually an instance of - * MouseEvent. + * This is a helper method that dispatches the GlassPane MouseEvents to the + * proper component. + * + * @param e + * The AWTEvent to be dispatched. Usually an instance of + * MouseEvent. */ private void handleEvent(AWTEvent e) { if (e instanceof MouseEvent) { - MouseEvent me = SwingUtilities.convertMouseEvent(frame.getRootPane() - .getGlassPane(), - (MouseEvent) e, - frame.getRootPane() - .getGlassPane()); - - acquireComponentForMouseEvent(me); - - // Avoid dispatching ENTERED and EXITED events twice. - if (mouseEventTarget != null && mouseEventTarget.isShowing() - && e.getID() != MouseEvent.MOUSE_ENTERED - && e.getID() != MouseEvent.MOUSE_EXITED) - { - MouseEvent newEvt = SwingUtilities.convertMouseEvent(frame - .getContentPane(), - me, - mouseEventTarget); - mouseEventTarget.dispatchEvent(newEvt); - - switch (e.getID()) - { - case MouseEvent.MOUSE_PRESSED: - if (pressCount++ == 0) - pressedComponent = mouseEventTarget; - break; - case MouseEvent.MOUSE_RELEASED: - // Clear our memory of the original PRESSED event, only if - // we're not expecting a CLICKED event after this. If - // there is a CLICKED event after this, it will do clean up. - if (--pressCount == 0 - && mouseEventTarget != pressedComponent) - pressedComponent = null; - break; - } - } + MouseEvent me = (MouseEvent) e; + acquireComponentForMouseEvent(me); + + //If there is no target, return + if (mouseEventTarget == null) + return; + + //Avoid re-dispatching to ourselves and causing an infinite loop + if (mouseEventTarget.equals(frame.getGlassPane())) + return; + + // Avoid dispatching ENTERED and EXITED events twice. + if (mouseEventTarget.isShowing() + && e.getID() != MouseEvent.MOUSE_ENTERED + && e.getID() != MouseEvent.MOUSE_EXITED) + { + MouseEvent newEvt = SwingUtilities.convertMouseEvent( + frame.getGlassPane(), + me, + mouseEventTarget); + mouseEventTarget.dispatchEvent(newEvt); + + switch (e.getID()) + { + case MouseEvent.MOUSE_PRESSED: + if (pressCount++ == 0) + pressedComponent = mouseEventTarget; + break; + case MouseEvent.MOUSE_RELEASED: + // Clear our memory of the original PRESSED event, only if + // we're not expecting a CLICKED event after this. If + // there is a CLICKED event after this, it will do clean up. + if (--pressCount == 0 && mouseEventTarget != pressedComponent) + pressedComponent = null; + break; + } + } } } } @@ -874,17 +890,18 @@ public class BasicInternalFrameUI extends InternalFrameUI * This helper class listens for PropertyChangeEvents from the * JInternalFrame. */ - public class InternalFramePropertyChangeListener - implements PropertyChangeListener, VetoableChangeListener + public class InternalFramePropertyChangeListener implements + PropertyChangeListener, VetoableChangeListener { /** - * This method is called when one of the JInternalFrame's properties - * change. This method is to allow JInternalFrame to veto an attempt - * to close the internal frame. This allows JInternalFrame to honour - * its defaultCloseOperation if that is DO_NOTHING_ON_CLOSE. + * This method is called when one of the JInternalFrame's properties change. + * This method is to allow JInternalFrame to veto an attempt to close the + * internal frame. This allows JInternalFrame to honour its + * defaultCloseOperation if that is DO_NOTHING_ON_CLOSE. */ - public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException + public void vetoableChange(PropertyChangeEvent e) + throws PropertyVetoException { if (e.getPropertyName().equals(JInternalFrame.IS_CLOSED_PROPERTY)) { @@ -892,75 +909,78 @@ public class BasicInternalFrameUI extends InternalFrameUI { frame.setVisible(false); frame.getDesktopPane().repaint(); - throw new PropertyVetoException ("close operation is HIDE_ON_CLOSE\n", e); + throw new PropertyVetoException( + "close operation is HIDE_ON_CLOSE\n", + e); } else if (frame.getDefaultCloseOperation() == JInternalFrame.DISPOSE_ON_CLOSE) closeFrame(frame); else - throw new PropertyVetoException ("close operation is DO_NOTHING_ON_CLOSE\n", e); + throw new PropertyVetoException( + "close operation is DO_NOTHING_ON_CLOSE\n", + e); } } - + /** - * This method is called when one of the JInternalFrame's properties - * change. - * - * @param evt The PropertyChangeEvent. + * This method is called when one of the JInternalFrame's properties change. + * + * @param evt + * The PropertyChangeEvent. */ public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName().equals(JInternalFrame.IS_MAXIMUM_PROPERTY)) { - if (frame.isMaximum()) - maximizeFrame(frame); - else - minimizeFrame(frame); + if (frame.isMaximum()) + maximizeFrame(frame); + else + minimizeFrame(frame); } else if (evt.getPropertyName().equals(JInternalFrame.IS_ICON_PROPERTY)) { - if (frame.isIcon()) - iconifyFrame(frame); - else - deiconifyFrame(frame); + if (frame.isIcon()) + iconifyFrame(frame); + else + deiconifyFrame(frame); } else if (evt.getPropertyName().equals(JInternalFrame.IS_SELECTED_PROPERTY)) { - if (frame.isSelected()) - activateFrame(frame); - else - getDesktopManager().deactivateFrame(frame); + if (frame.isSelected()) + activateFrame(frame); + else + deactivateFrame(frame); } else if (evt.getPropertyName().equals(JInternalFrame.ROOT_PANE_PROPERTY) - || evt.getPropertyName().equals(JInternalFrame.GLASS_PANE_PROPERTY)) + || evt.getPropertyName().equals( + JInternalFrame.GLASS_PANE_PROPERTY)) { - Component old = (Component) evt.getOldValue(); - old.removeMouseListener(glassPaneDispatcher); - old.removeMouseMotionListener(glassPaneDispatcher); + Component old = (Component) evt.getOldValue(); + old.removeMouseListener(glassPaneDispatcher); + old.removeMouseMotionListener(glassPaneDispatcher); - Component newPane = (Component) evt.getNewValue(); - newPane.addMouseListener(glassPaneDispatcher); - newPane.addMouseMotionListener(glassPaneDispatcher); + Component newPane = (Component) evt.getNewValue(); + newPane.addMouseListener(glassPaneDispatcher); + newPane.addMouseMotionListener(glassPaneDispatcher); - frame.revalidate(); + frame.revalidate(); } - /* FIXME: need to add ancestor properties to JComponents. - else if (evt.getPropertyName().equals(JComponent.ANCESTOR_PROPERTY)) - { - if (desktopPane != null) - desktopPane.removeComponentListener(componentListener); - desktopPane = frame.getDesktopPane(); - if (desktopPane != null) - desktopPane.addComponentListener(componentListener); - } - */ + /* + * FIXME: need to add ancestor properties to JComponents. else if + * (evt.getPropertyName().equals(JComponent.ANCESTOR_PROPERTY)) { if + * (desktopPane != null) + * desktopPane.removeComponentListener(componentListener); desktopPane = + * frame.getDesktopPane(); if (desktopPane != null) + * desktopPane.addComponentListener(componentListener); } + */ } } /** * This helper class is the border for the JInternalFrame. */ - private class InternalFrameBorder extends AbstractBorder - implements UIResource + private class InternalFrameBorder extends AbstractBorder implements + UIResource { /** The width of the border. */ private static final int bSize = 5; @@ -970,7 +990,7 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method returns whether the border is opaque. - * + * * @return Whether the border is opaque. */ public boolean isBorderOpaque() @@ -980,9 +1000,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method returns the insets of the border. - * - * @param c The Component to find border insets for. - * + * + * @param c + * The Component to find border insets for. * @return The border insets. */ public Insets getBorderInsets(Component c) @@ -992,13 +1012,19 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method paints the border. - * - * @param c The Component that owns the border. - * @param g The Graphics object to paint with. - * @param x The x coordinate to paint at. - * @param y The y coordinate to paint at. - * @param width The width of the Component. - * @param height The height of the Component. + * + * @param c + * The Component that owns the border. + * @param g + * The Graphics object to paint with. + * @param x + * The x coordinate to paint at. + * @param y + * The y coordinate to paint at. + * @param width + * The width of the Component. + * @param height + * The height of the Component. */ public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) @@ -1111,6 +1137,7 @@ public class BasicInternalFrameUI extends InternalFrameUI */ public BasicInternalFrameUI(JInternalFrame b) { + // Nothing to do here. } /** @@ -1135,21 +1162,21 @@ public class BasicInternalFrameUI extends InternalFrameUI { if (c instanceof JInternalFrame) { - frame = (JInternalFrame) c; + frame = (JInternalFrame) c; - internalFrameLayout = createLayoutManager(); - frame.setLayout(internalFrameLayout); + internalFrameLayout = createLayoutManager(); + frame.setLayout(internalFrameLayout); - ((JComponent) frame.getRootPane().getGlassPane()).setOpaque(false); - frame.getRootPane().getGlassPane().setVisible(true); + ((JComponent) frame.getRootPane().getGlassPane()).setOpaque(false); + frame.getRootPane().getGlassPane().setVisible(true); - installDefaults(); - installListeners(); - installComponents(); - installKeyboardActions(); + installDefaults(); + installListeners(); + installComponents(); + installKeyboardActions(); - frame.setOpaque(true); - frame.invalidate(); + frame.setOpaque(true); + frame.invalidate(); } } @@ -1177,10 +1204,8 @@ public class BasicInternalFrameUI extends InternalFrameUI */ protected void installDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - Border border = defaults.getBorder("InternalFrame.border"); - frame.setBorder(border); - frame.setFrameIcon(defaults.getIcon("InternalFrame.icon")); + LookAndFeel.installBorder(frame, "InternalFrame.border"); + frame.setFrameIcon(UIManager.getIcon("InternalFrame.icon")); // InternalFrames are invisible by default. frame.setVisible(false); } @@ -1343,14 +1368,14 @@ public class BasicInternalFrameUI extends InternalFrameUI { if (currentPane != null) { - deinstallMouseHandlers(currentPane); - frame.remove(currentPane); + deinstallMouseHandlers(currentPane); + frame.remove(currentPane); } if (newPane != null) { - installMouseHandlers(newPane); - frame.add(newPane); + installMouseHandlers(newPane); + frame.add(newPane); } } @@ -1678,6 +1703,16 @@ public class BasicInternalFrameUI extends InternalFrameUI } /** + * This is a convenience method that deactivates the JInternalFrame. + * + * @param f the JInternalFrame to deactivate + */ + protected void deactivateFrame(JInternalFrame f) + { + getDesktopManager().deactivateFrame(f); + } + + /** * This method returns a new ComponentListener for the JDesktopPane. * * @return A new ComponentListener. diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java index bb9ce6cb1d9..c8f677fa0a0 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java @@ -50,9 +50,8 @@ import java.beans.PropertyChangeListener; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JLabel; +import javax.swing.LookAndFeel; import javax.swing.SwingUtilities; -import javax.swing.UIDefaults; -import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.LabelUI; @@ -60,9 +59,7 @@ import javax.swing.plaf.LabelUI; * This is the Basic Look and Feel class for the JLabel. One BasicLabelUI * object is used to paint all JLabels that utilize the Basic Look and Feel. */ -public class BasicLabelUI - extends LabelUI - implements PropertyChangeListener +public class BasicLabelUI extends LabelUI implements PropertyChangeListener { /** The labelUI that is shared by all labels. */ protected static BasicLabelUI labelUI; @@ -345,11 +342,8 @@ public class BasicLabelUI */ protected void installDefaults(JLabel c) { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - c.setForeground(defaults.getColor("Label.foreground")); - c.setBackground(defaults.getColor("Label.background")); - c.setFont(defaults.getFont("Label.font")); + LookAndFeel.installColorsAndFont(c, "Label.background", "Label.foreground", + "Label.font"); //XXX: There are properties we don't use called disabledForeground //and disabledShadow. } @@ -417,8 +411,6 @@ public class BasicLabelUI */ public void propertyChange(PropertyChangeEvent e) { - JLabel c = (JLabel) e.getSource(); - c.revalidate(); - c.repaint(); + // What to do here? } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java index 841bd670f67..33932991473 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java @@ -38,31 +38,35 @@ exception statement from your version. */ package javax.swing.plaf.basic; -import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Point; import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; 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.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import javax.swing.AbstractAction; +import javax.swing.ActionMap; import javax.swing.CellRendererPane; +import javax.swing.DefaultListSelectionModel; +import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JList; import javax.swing.JViewport; +import javax.swing.KeyStroke; import javax.swing.ListCellRenderer; import javax.swing.ListModel; import javax.swing.ListSelectionModel; +import javax.swing.LookAndFeel; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.event.ListDataEvent; @@ -70,7 +74,9 @@ import javax.swing.event.ListDataListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ActionMapUIResource; import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.InputMapUIResource; import javax.swing.plaf.ListUI; /** @@ -125,8 +131,9 @@ public class BasicListUI extends ListUI * Helper method to repaint the focused cell's * lost or acquired focus state. */ - void repaintCellFocus() + protected void repaintCellFocus() { + // TODO: Implement this properly. } } @@ -183,141 +190,231 @@ public class BasicListUI extends ListUI */ public void valueChanged(ListSelectionEvent e) { + int index1 = e.getFirstIndex(); + int index2 = e.getLastIndex(); + Rectangle damaged = getCellBounds(list, index1, index2); + list.repaint(damaged); } } /** - * A helper class which listens for {@link KeyEvents}s - * from the {@link JList}. + * This class is used to mimmic the behaviour of the JDK when registering + * keyboard actions. It is the same as the private class used in JComponent + * for the same reason. This class receives an action event and dispatches + * it to the true receiver after altering the actionCommand property of the + * event. */ - private class KeyHandler extends KeyAdapter + private static class ActionListenerProxy + extends AbstractAction { - public KeyHandler() + ActionListener target; + String bindingCommandName; + + public ActionListenerProxy(ActionListener li, + String cmd) { + target = li; + bindingCommandName = cmd; } - - public void keyPressed( KeyEvent evt ) + + public void actionPerformed(ActionEvent e) + { + ActionEvent derivedEvent = new ActionEvent(e.getSource(), + e.getID(), + bindingCommandName, + e.getModifiers()); + target.actionPerformed(derivedEvent); + } + } + + class ListAction extends AbstractAction + { + public void actionPerformed (ActionEvent e) { - int lead = BasicListUI.this.list.getLeadSelectionIndex(); - int max = BasicListUI.this.list.getModel().getSize() - 1; + int lead = list.getLeadSelectionIndex(); + int max = list.getModel().getSize() - 1; + DefaultListSelectionModel selModel = (DefaultListSelectionModel)list.getSelectionModel(); + String command = e.getActionCommand(); // Do nothing if list is empty if (max == -1) return; - - // Process the key event. Bindings can be found in - // javax.swing.plaf.basic.BasicLookAndFeel.java - if ((evt.getKeyCode() == KeyEvent.VK_DOWN) - || (evt.getKeyCode() == KeyEvent.VK_KP_DOWN)) + + if (command.equals("selectNextRow")) { - if (evt.getModifiers() == 0) - { - BasicListUI.this.list.clearSelection(); - BasicListUI.this.list.setSelectedIndex(Math.min(lead+1,max)); - } - else if (evt.getModifiers() == InputEvent.SHIFT_MASK) + selectNextIndex(); + } + else if (command.equals("selectPreviousRow")) + { + selectPreviousIndex(); + } + else if (command.equals("clearSelection")) + { + list.clearSelection(); + } + else if (command.equals("selectAll")) + { + list.setSelectionInterval(0, max); + // this next line is to restore the lead selection index to the old + // position, because select-all should not change the lead index + list.addSelectionInterval(lead, lead); + } + else if (command.equals("selectLastRow")) + { + list.setSelectedIndex(list.getModel().getSize() - 1); + } + else if (command.equals("selectLastRowChangeLead")) + { + selModel.moveLeadSelectionIndex(list.getModel().getSize() - 1); + } + else if (command.equals("scrollDownExtendSelection")) + { + int target; + if (lead == list.getLastVisibleIndex()) { - BasicListUI.this.list.getSelectionModel(). - setLeadSelectionIndex(Math.min(lead+1,max)); + target = Math.min + (max, lead + (list.getLastVisibleIndex() - + list.getFirstVisibleIndex() + 1)); } + else + target = list.getLastVisibleIndex(); + selModel.setLeadSelectionIndex(target); } - else if ((evt.getKeyCode() == KeyEvent.VK_UP) - || (evt.getKeyCode() == KeyEvent.VK_KP_UP)) + else if (command.equals("scrollDownChangeLead")) { - if (evt.getModifiers() == 0) + int target; + if (lead == list.getLastVisibleIndex()) { - BasicListUI.this.list.clearSelection(); - BasicListUI.this.list.setSelectedIndex(Math.max(lead-1,0)); + target = Math.min + (max, lead + (list.getLastVisibleIndex() - + list.getFirstVisibleIndex() + 1)); } - else if (evt.getModifiers() == InputEvent.SHIFT_MASK) + else + target = list.getLastVisibleIndex(); + selModel.moveLeadSelectionIndex(target); + } + else if (command.equals("scrollUpExtendSelection")) + { + int target; + if (lead == list.getFirstVisibleIndex()) { - BasicListUI.this.list.getSelectionModel(). - setLeadSelectionIndex(Math.max(lead-1,0)); + target = Math.max + (0, lead - (list.getLastVisibleIndex() - + list.getFirstVisibleIndex() + 1)); } + else + target = list.getFirstVisibleIndex(); + selModel.setLeadSelectionIndex(target); } - else if (evt.getKeyCode() == KeyEvent.VK_PAGE_UP) + else if (command.equals("scrollUpChangeLead")) { int target; - if (lead == BasicListUI.this.list.getFirstVisibleIndex()) + if (lead == list.getFirstVisibleIndex()) { target = Math.max - (0, lead - (BasicListUI.this.list.getLastVisibleIndex() - - BasicListUI.this.list.getFirstVisibleIndex() + 1)); + (0, lead - (list.getLastVisibleIndex() - + list.getFirstVisibleIndex() + 1)); } else + target = list.getFirstVisibleIndex(); + selModel.moveLeadSelectionIndex(target); + } + else if (command.equals("selectNextRowExtendSelection")) + { + selModel.setLeadSelectionIndex(Math.min(lead + 1,max)); + } + else if (command.equals("selectFirstRow")) + { + list.setSelectedIndex(0); + } + else if (command.equals("selectFirstRowChangeLead")) + { + selModel.moveLeadSelectionIndex(0); + } + else if (command.equals("selectFirstRowExtendSelection")) + { + selModel.setLeadSelectionIndex(0); + } + else if (command.equals("selectPreviousRowExtendSelection")) + { + selModel.setLeadSelectionIndex(Math.max(0,lead - 1)); + } + else if (command.equals("scrollUp")) + { + int target; + if (lead == list.getFirstVisibleIndex()) { - target = BasicListUI.this.list.getFirstVisibleIndex(); + target = Math.max + (0, lead - (list.getLastVisibleIndex() - + list.getFirstVisibleIndex() + 1)); } - if (evt.getModifiers() == 0) - BasicListUI.this.list.setSelectedIndex(target); - else if (evt.getModifiers() == InputEvent.SHIFT_MASK) - BasicListUI.this.list.getSelectionModel(). - setLeadSelectionIndex(target); + else + target = list.getFirstVisibleIndex(); + list.setSelectedIndex(target); } - else if (evt.getKeyCode() == KeyEvent.VK_PAGE_DOWN) + else if (command.equals("selectLastRowExtendSelection")) + { + selModel.setLeadSelectionIndex(list.getModel().getSize() - 1); + } + else if (command.equals("scrollDown")) { int target; - if (lead == BasicListUI.this.list.getLastVisibleIndex()) + if (lead == list.getLastVisibleIndex()) { target = Math.min - (max, lead + (BasicListUI.this.list.getLastVisibleIndex() - - BasicListUI.this.list.getFirstVisibleIndex() + 1)); + (max, lead + (list.getLastVisibleIndex() - + list.getFirstVisibleIndex() + 1)); } else + target = list.getLastVisibleIndex(); + list.setSelectedIndex(target); + } + else if (command.equals("selectNextRowChangeLead")) + { + if (selModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) + selectNextIndex(); + else + { + selModel.moveLeadSelectionIndex(Math.min(max, lead + 1)); + } + } + else if (command.equals("selectPreviousRowChangeLead")) + { + if (selModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) + selectPreviousIndex(); + else { - target = BasicListUI.this.list.getLastVisibleIndex(); + selModel.moveLeadSelectionIndex(Math.max(0, lead - 1)); } - if (evt.getModifiers() == 0) - BasicListUI.this.list.setSelectedIndex(target); - else if (evt.getModifiers() == InputEvent.SHIFT_MASK) - BasicListUI.this.list.getSelectionModel(). - setLeadSelectionIndex(target); - } - else if (evt.getKeyCode() == KeyEvent.VK_BACK_SLASH - && (evt.getModifiers() == InputEvent.CTRL_MASK)) + } + else if (command.equals("addToSelection")) { - BasicListUI.this.list.clearSelection(); + list.addSelectionInterval(lead, lead); } - else if ((evt.getKeyCode() == KeyEvent.VK_HOME) - || evt.getKeyCode() == KeyEvent.VK_END) + else if (command.equals("extendTo")) { - if (evt.getModifiers() != 0 && - evt.getModifiers() != InputEvent.SHIFT_MASK) - return; - // index is either 0 for HOME, or last cell for END - int index = (evt.getKeyCode() == KeyEvent.VK_HOME) ? 0 : max; - - if (!evt.isShiftDown() ||(BasicListUI.this.list.getSelectionMode() - == ListSelectionModel.SINGLE_SELECTION)) - BasicListUI.this.list.setSelectedIndex(index); - else if (BasicListUI.this.list.getSelectionMode() == - ListSelectionModel.SINGLE_INTERVAL_SELECTION) - BasicListUI.this.list.setSelectionInterval - (BasicListUI.this.list.getAnchorSelectionIndex(), index); - else - BasicListUI.this.list.getSelectionModel(). - setLeadSelectionIndex(index); + selModel.setSelectionInterval(selModel.getAnchorSelectionIndex(), + lead); } - else if ((evt.getKeyCode() == KeyEvent.VK_A || evt.getKeyCode() - == KeyEvent.VK_SLASH) && (evt.getModifiers() == - InputEvent.CTRL_MASK)) + else if (command.equals("toggleAndAnchor")) { - BasicListUI.this.list.setSelectionInterval(0, max); - // this next line is to restore the lead selection index to the old - // position, because select-all should not change the lead index - BasicListUI.this.list.addSelectionInterval(lead, lead); + if (!list.isSelectedIndex(lead)) + list.addSelectionInterval(lead, lead); + else + list.removeSelectionInterval(lead, lead); + selModel.setAnchorSelectionIndex(lead); } - else if (evt.getKeyCode() == KeyEvent.VK_SPACE && - (evt.getModifiers() == InputEvent.CTRL_MASK)) + else { - BasicListUI.this.list.getSelectionModel(). - setLeadSelectionIndex(Math.min(lead+1,max)); + // DEBUG: uncomment the following line to print out + // key bindings that aren't implemented yet + + // System.out.println ("not implemented: "+e.getActionCommand()); } - - BasicListUI.this.list.ensureIndexIsVisible - (BasicListUI.this.list.getLeadSelectionIndex()); + + list.ensureIndexIsVisible(list.getLeadSelectionIndex()); } } - + /** * A helper class which listens for {@link MouseEvent}s * from the {@link JList}. @@ -333,48 +430,46 @@ public class BasicListUI extends ListUI public void mouseClicked(MouseEvent event) { Point click = event.getPoint(); - int index = BasicListUI.this.locationToIndex(list, click); + int index = locationToIndex(list, click); if (index == -1) return; if (event.isShiftDown()) { - if (BasicListUI.this.list.getSelectionMode() == - ListSelectionModel.SINGLE_SELECTION) - BasicListUI.this.list.setSelectedIndex(index); - else if (BasicListUI.this.list.getSelectionMode() == + if (list.getSelectionMode() == ListSelectionModel.SINGLE_SELECTION) + list.setSelectedIndex(index); + else if (list.getSelectionMode() == ListSelectionModel.SINGLE_INTERVAL_SELECTION) // COMPAT: the IBM VM is compatible with the following line of code. // However, compliance with Sun's VM would correspond to replacing // getAnchorSelectionIndex() with getLeadSelectionIndex().This is // both unnatural and contradictory to the way they handle other // similar UI interactions. - BasicListUI.this.list.setSelectionInterval - (BasicListUI.this.list.getAnchorSelectionIndex(), index); + list.setSelectionInterval(list.getAnchorSelectionIndex(), index); else // COMPAT: both Sun and IBM are compatible instead with: - // BasicListUI.this.list.setSelectionInterval - // (BasicListUI.this.list.getLeadSelectionIndex(),index); + // list.setSelectionInterval + // (list.getLeadSelectionIndex(),index); // Note that for IBM this is contradictory to what they did in // the above situation for SINGLE_INTERVAL_SELECTION. // The most natural thing to do is the following: - BasicListUI.this.list.getSelectionModel(). - setLeadSelectionIndex(index); + if (list.isSelectedIndex(list.getAnchorSelectionIndex())) + list.getSelectionModel().setLeadSelectionIndex(index); + else + list.addSelectionInterval(list.getAnchorSelectionIndex(), index); } else if (event.isControlDown()) { - if (BasicListUI.this.list.getSelectionMode() == - ListSelectionModel.SINGLE_SELECTION) - BasicListUI.this.list.setSelectedIndex(index); - else if (BasicListUI.this.list.isSelectedIndex(index)) - BasicListUI.this.list.removeSelectionInterval(index,index); + if (list.getSelectionMode() == ListSelectionModel.SINGLE_SELECTION) + list.setSelectedIndex(index); + else if (list.isSelectedIndex(index)) + list.removeSelectionInterval(index,index); else - BasicListUI.this.list.addSelectionInterval(index,index); + list.addSelectionInterval(index,index); } else - BasicListUI.this.list.setSelectedIndex(index); + list.setSelectedIndex(index); - BasicListUI.this.list.ensureIndexIsVisible - (BasicListUI.this.list.getLeadSelectionIndex()); + list.ensureIndexIsVisible(list.getLeadSelectionIndex()); } /** @@ -385,6 +480,7 @@ public class BasicListUI extends ListUI */ public void mousePressed(MouseEvent event) { + // TODO: What should be done here, if anything? } /** @@ -395,6 +491,7 @@ public class BasicListUI extends ListUI */ public void mouseReleased(MouseEvent event) { + // TODO: What should be done here, if anything? } /** @@ -405,6 +502,7 @@ public class BasicListUI extends ListUI */ public void mouseEntered(MouseEvent event) { + // TODO: What should be done here, if anything? } /** @@ -415,6 +513,7 @@ public class BasicListUI extends ListUI */ public void mouseExited(MouseEvent event) { + // TODO: What should be done here, if anything? } /** @@ -425,6 +524,7 @@ public class BasicListUI extends ListUI */ public void mouseDragged(MouseEvent event) { + // TODO: What should be done here, if anything? } /** @@ -435,6 +535,7 @@ public class BasicListUI extends ListUI */ public void mouseMoved(MouseEvent event) { + // TODO: What should be done here, if anything? } } @@ -459,11 +560,61 @@ public class BasicListUI extends ListUI if (e.getNewValue() != null && e.getNewValue() instanceof ListModel) ((ListModel) e.getNewValue()).addListDataListener(BasicListUI.this.listDataListener); } + // Update the updateLayoutStateNeeded flag. + if (e.getPropertyName().equals("model")) + updateLayoutStateNeeded += modelChanged; + else if (e.getPropertyName().equals("selectionModel")) + updateLayoutStateNeeded += selectionModelChanged; + else if (e.getPropertyName().equals("font")) + updateLayoutStateNeeded += fontChanged; + else if (e.getPropertyName().equals("fixedCellWidth")) + updateLayoutStateNeeded += fixedCellWidthChanged; + else if (e.getPropertyName().equals("fixedCellHeight")) + updateLayoutStateNeeded += fixedCellHeightChanged; + else if (e.getPropertyName().equals("prototypeCellValue")) + updateLayoutStateNeeded += prototypeCellValueChanged; + else if (e.getPropertyName().equals("cellRenderer")) + updateLayoutStateNeeded += cellRendererChanged; BasicListUI.this.damageLayout(); } } /** + * A constant to indicate that the model has changed. + */ + protected static final int modelChanged = 1; + + /** + * A constant to indicate that the selection model has changed. + */ + protected static final int selectionModelChanged = 2; + + /** + * A constant to indicate that the font has changed. + */ + protected static final int fontChanged = 4; + + /** + * A constant to indicate that the fixedCellWidth has changed. + */ + protected static final int fixedCellWidthChanged = 8; + + /** + * A constant to indicate that the fixedCellHeight has changed. + */ + protected static final int fixedCellHeightChanged = 16; + + /** + * A constant to indicate that the prototypeCellValue has changed. + */ + protected static final int prototypeCellValueChanged = 32; + + /** + * A constant to indicate that the cellRenderer has changed. + */ + protected static final int cellRendererChanged = 64; + + /** * Creates a new BasicListUI for the component. * * @param c The component to create a UI for @@ -487,9 +638,6 @@ public class BasicListUI extends ListUI /** The mouse listener listening to the list. */ protected MouseInputListener mouseInputListener; - /** The key listener listening to the list */ - private KeyHandler keyListener; - /** The property change listener listening to the list. */ protected PropertyChangeListener propertyChangeListener; @@ -501,7 +649,11 @@ public class BasicListUI extends ListUI /** Saved reference to the list this UI was created for. */ protected JList list; - /** The height of a single cell in the list. */ + /** + * The height of a single cell in the list. This field is used when the + * fixedCellHeight property of the list is set. Otherwise this field is + * set to <code>-1</code> and {@link #cellHeights} is used instead. + */ protected int cellHeight; /** The width of a single cell in the list. */ @@ -509,14 +661,25 @@ public class BasicListUI extends ListUI /** * An array of varying heights of cells in the list, in cases where each - * cell might have a different height. + * cell might have a different height. This field is used when the + * <code>fixedCellHeight</code> property of the list is not set. Otherwise + * this field is <code>null</code> and {@link #cellHeight} is used. */ protected int[] cellHeights; /** - * A simple counter. When nonzero, indicates that the UI class is out of + * A bitmask that indicates which properties of the JList have changed. + * When nonzero, indicates that the UI class is out of * date with respect to the underlying list, and must recalculate the * list layout before painting or performing size calculations. + * + * @see #modelChanged + * @see #selectionModelChanged + * @see #fontChanged + * @see #fixedCellWidthChanged + * @see #fixedCellHeightChanged + * @see #prototypeCellValueChanged + * @see #cellRendererChanged */ protected int updateLayoutStateNeeded; @@ -524,6 +687,9 @@ public class BasicListUI extends ListUI * The {@link CellRendererPane} that is used for painting. */ protected CellRendererPane rendererPane; + + /** The action bound to KeyStrokes. */ + ListAction action; /** * Calculate the height of a particular row. If there is a fixed {@link @@ -611,19 +777,51 @@ public class BasicListUI extends ListUI * @param y0 The Y coordinate to calculate the row number for * * @return The row number containing the specified Y value, or <code>-1</code> - * if the specified Y coordinate is invalid + * if the list model is empty + * + * @specnote This method is specified to return -1 for an invalid Y + * coordinate. However, some simple tests show that the behaviour + * is to return the index of the last list element for an Y + * coordinate that lies outside of the list bounds (even for + * negative indices). <code>-1</code> + * is only returned if the list model is empty. */ protected int convertYToRow(int y0) { - for (int row = 0; row < cellHeights.length; ++row) - { - int h = getRowHeight(row); + if (list.getModel().getSize() == 0) + return -1; + + // When y0 < 0, then the JDK returns the maximum row index of the list. So + // do we. + if (y0 < 0) + return list.getModel().getSize() - 1; + + // Update the layout if necessary. + maybeUpdateLayoutState(); + + int index = list.getModel().getSize() - 1;; - if (y0 < h) - return row; - y0 -= h; + // If a fixed cell height is set, then we can work more efficient. + if (cellHeight > 0) + { + index = Math.max(y0 / cellHeight, index); + } + // If we have no fixed cell height, we must add up each cell height up + // to y0. + else + { + int h = 0; + for (int row = 0; row < cellHeights.length; ++row) + { + h += cellHeights[row]; + if (y0 < h) + { + index = row; + break; + } + } } - return -1; + return index; } /** @@ -638,29 +836,47 @@ public class BasicListUI extends ListUI cellWidth = -1; if (cellHeights == null || cellHeights.length != nrows) cellHeights = new int[nrows]; - if (list.getFixedCellHeight() == -1 || list.getFixedCellWidth() == -1) + ListCellRenderer rend = list.getCellRenderer(); + // Update the cellHeight(s) fields. + int fixedCellHeight = list.getFixedCellHeight(); + if (fixedCellHeight > 0) + { + cellHeight = fixedCellHeight; + cellHeights = null; + } + else { - ListCellRenderer rend = list.getCellRenderer(); + cellHeight = -1; for (int i = 0; i < nrows; ++i) { - Component flyweight = rend.getListCellRendererComponent(list, - list.getModel() - .getElementAt(i), - 0, false, - false); + Component flyweight = + rend.getListCellRendererComponent(list, + list.getModel().getElementAt(i), + i, list.isSelectedIndex(i), + list.getSelectionModel().getAnchorSelectionIndex() == i); Dimension dim = flyweight.getPreferredSize(); cellHeights[i] = dim.height; - // compute average cell height (little hack here) - cellHeight = (cellHeight * i + cellHeights[i]) / (i + 1); - cellWidth = Math.max(cellWidth, dim.width); - if (list.getLayoutOrientation() == JList.VERTICAL) - cellWidth = Math.max(cellWidth, list.getSize().width); } } + + // Update the cellWidth field. + int fixedCellWidth = list.getFixedCellWidth(); + if (fixedCellWidth > 0) + cellWidth = fixedCellWidth; else { - cellHeight = list.getFixedCellHeight(); - cellWidth = list.getFixedCellWidth(); + for (int i = 0; i < nrows; ++i) + { + Component flyweight = + rend.getListCellRendererComponent(list, + list.getModel().getElementAt(i), + i, list.isSelectedIndex(i), + list.getSelectionModel().getAnchorSelectionIndex() == i); + Dimension dim = flyweight.getPreferredSize(); + cellWidth = Math.max(cellWidth, dim.width); + } + if (list.getLayoutOrientation() == JList.VERTICAL) + cellWidth = Math.max(cellWidth, list.getSize().width); } } @@ -694,13 +910,6 @@ public class BasicListUI extends ListUI */ public BasicListUI() { - focusListener = new FocusHandler(); - listDataListener = new ListDataHandler(); - listSelectionListener = new ListSelectionHandler(); - mouseInputListener = new MouseInputHandler(); - keyListener = new KeyHandler(); - propertyChangeListener = new PropertyChangeHandler(); - componentListener = new ComponentHandler(); updateLayoutStateNeeded = 1; rendererPane = new CellRendererPane(); } @@ -713,11 +922,10 @@ public class BasicListUI extends ListUI */ protected void installDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - list.setForeground(defaults.getColor("List.foreground")); - list.setBackground(defaults.getColor("List.background")); - list.setSelectionForeground(defaults.getColor("List.selectionForeground")); - list.setSelectionBackground(defaults.getColor("List.selectionBackground")); + LookAndFeel.installColorsAndFont(list, "List.background", + "List.foreground", "List.font"); + list.setSelectionForeground(UIManager.getColor("List.selectionForeground")); + list.setSelectionBackground(UIManager.getColor("List.selectionBackground")); list.setOpaque(true); } @@ -727,7 +935,6 @@ public class BasicListUI extends ListUI */ protected void uninstallDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); list.setForeground(null); list.setBackground(null); list.setSelectionForeground(null); @@ -742,14 +949,28 @@ public class BasicListUI extends ListUI */ protected void installListeners() { + if (focusListener == null) + focusListener = createFocusListener(); list.addFocusListener(focusListener); + if (listDataListener == null) + listDataListener = createListDataListener(); list.getModel().addListDataListener(listDataListener); + if (listSelectionListener == null) + listSelectionListener = createListSelectionListener(); list.addListSelectionListener(listSelectionListener); + if (mouseInputListener == null) + mouseInputListener = createMouseInputListener(); list.addMouseListener(mouseInputListener); - list.addKeyListener(keyListener); list.addMouseMotionListener(mouseInputListener); + if (propertyChangeListener == null) + propertyChangeListener = createPropertyChangeListener(); list.addPropertyChangeListener(propertyChangeListener); + + // FIXME: Are these two really needed? At least they are not documented. + //keyListener = new KeyHandler(); + componentListener = new ComponentHandler(); list.addComponentListener(componentListener); + //list.addKeyListener(keyListener); } /** @@ -761,16 +982,41 @@ public class BasicListUI extends ListUI list.getModel().removeListDataListener(listDataListener); list.removeListSelectionListener(listSelectionListener); list.removeMouseListener(mouseInputListener); - list.removeKeyListener(keyListener); + //list.removeKeyListener(keyListener); list.removeMouseMotionListener(mouseInputListener); list.removePropertyChangeListener(propertyChangeListener); } - + /** * Installs keyboard actions for this UI in the {@link JList}. */ protected void installKeyboardActions() { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + InputMap focusInputMap = (InputMap)defaults.get("List.focusInputMap"); + InputMapUIResource parentInputMap = new InputMapUIResource(); + // FIXME: The JDK uses a LazyActionMap for parentActionMap + ActionMap parentActionMap = new ActionMapUIResource(); + action = new ListAction(); + Object keys[] = focusInputMap.allKeys(); + // Register key bindings in the UI InputMap-ActionMap pair + for (int i = 0; i < keys.length; i++) + { + KeyStroke stroke = (KeyStroke)keys[i]; + String actionString = (String) focusInputMap.get(stroke); + parentInputMap.put(KeyStroke.getKeyStroke(stroke.getKeyCode(), + stroke.getModifiers()), + actionString); + + parentActionMap.put (actionString, + new ActionListenerProxy(action, actionString)); + } + // Register the new InputMap-ActionMap as the parents of the list's + // InputMap and ActionMap + parentInputMap.setParent(list.getInputMap().getParent()); + parentActionMap.setParent(list.getActionMap().getParent()); + list.getInputMap().setParent(parentInputMap); + list.getActionMap().setParent(parentActionMap); } /** @@ -778,6 +1024,7 @@ public class BasicListUI extends ListUI */ protected void uninstallKeyboardActions() { + // TODO: Implement this properly. } /** @@ -855,22 +1102,6 @@ public class BasicListUI extends ListUI } /** - * Paints the packground of the list using the background color - * of the specified component. - * - * @param g The graphics context to paint in - * @param c The component to paint the background of - */ - private void paintBackground(Graphics g, JComponent c) - { - Dimension size = getPreferredSize(c); - Color save = g.getColor(); - g.setColor(c.getBackground()); - g.fillRect(0, 0, size.width, size.height); - g.setColor(save); - } - - /** * Paints a single cell in the list. * * @param g The graphics context to paint in @@ -892,14 +1123,12 @@ public class BasicListUI extends ListUI Component comp = rend.getListCellRendererComponent(list, data.getElementAt(row), 0, isSel, hasFocus); - //comp.setBounds(new Rectangle(0, 0, bounds.width, bounds.height)); - //comp.paint(g); rendererPane.paintComponent(g, comp, list, bounds); } /** - * Paints the list by calling {@link #paintBackground} and then repeatedly - * calling {@link #paintCell} for each visible cell in the list. + * Paints the list by repeatedly calling {@link #paintCell} for each visible + * cell in the list. * * @param g The graphics context to paint with * @param c Ignored; uses the saved {@link JList} reference @@ -916,9 +1145,12 @@ public class BasicListUI extends ListUI ListSelectionModel sel = list.getSelectionModel(); int lead = sel.getLeadSelectionIndex(); Rectangle clip = g.getClipBounds(); - paintBackground(g, list); - for (int row = 0; row < nrows; ++row) + int startIndex = list.locationToIndex(new Point(clip.x, clip.y)); + int endIndex = list.locationToIndex(new Point(clip.x + clip.width, + clip.y + clip.height)); + + for (int row = startIndex; row <= endIndex; ++row) { Rectangle bounds = getCellBounds(list, row, row); if (bounds.intersects(clip)) @@ -927,13 +1159,15 @@ public class BasicListUI extends ListUI } /** - * Computes the index of a list cell given a point within the list. + * Computes the index of a list cell given a point within the list. If the + * location lies outside the bounds of the list, the greatest index in the + * list model is returned. * * @param list the list which on which the computation is based on * @param location the coordinates * * @return the index of the list item that is located at the given - * coordinates or <code>null</code> if the location is invalid + * coordinates or <code>-1</code> if the list model is empty */ public int locationToIndex(JList list, Point location) { @@ -983,7 +1217,6 @@ public class BasicListUI extends ListUI int numberOfItems2 = list.getModel().getSize(); int cellsPerRow2 = numberOfItems2 / visibleRows2 + 1; - Dimension listDim2 = list.getSize(); int gridX2 = Math.min(location.x / cellWidth, cellsPerRow2 - 1); int gridY2 = Math.min(location.y / cellHeight, visibleRows2); index = gridY2 + gridX2 * visibleRows2; @@ -1045,4 +1278,82 @@ public class BasicListUI extends ListUI } return loc; } + + /** + * Creates and returns the focus listener for this UI. + * + * @return the focus listener for this UI + */ + protected FocusListener createFocusListener() + { + return new FocusHandler(); + } + + /** + * Creates and returns the list data listener for this UI. + * + * @return the list data listener for this UI + */ + protected ListDataListener createListDataListener() + { + return new ListDataHandler(); + } + + /** + * Creates and returns the list selection listener for this UI. + * + * @return the list selection listener for this UI + */ + protected ListSelectionListener createListSelectionListener() + { + return new ListSelectionHandler(); + } + + /** + * Creates and returns the mouse input listener for this UI. + * + * @return the mouse input listener for this UI + */ + protected MouseInputListener createMouseInputListener() + { + return new MouseInputHandler(); + } + + /** + * Creates and returns the property change listener for this UI. + * + * @return the property change listener for this UI + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeHandler(); + } + + /** + * Selects the next list item and force it to be visible. + */ + protected void selectNextIndex() + { + int index = list.getSelectionModel().getLeadSelectionIndex(); + if (index < list.getModel().getSize() - 1) + { + index++; + list.setSelectedIndex(index); + } + list.ensureIndexIsVisible(index); + } + + /** + * Selects the previous list item and force it to be visible. + */ + protected void selectPreviousIndex() + { + int index = list.getSelectionModel().getLeadSelectionIndex(); + if (index > 0) + { + index--; + list.setSelectedIndex(index); + } + list.ensureIndexIsVisible(index); + } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java b/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java index d35ac9eb926..8ebe650350c 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java @@ -273,7 +273,7 @@ public abstract class BasicLookAndFeel extends LookAndFeel "Button.foreground", new ColorUIResource(Color.BLACK), "Button.highlight", new ColorUIResource(Color.WHITE), "Button.light", new ColorUIResource(Color.LIGHT_GRAY), - "Button.margin", new InsetsUIResource(2, 2, 2, 2), + "Button.margin", new InsetsUIResource(2, 14, 2, 14), "Button.shadow", new ColorUIResource(Color.GRAY), "Button.textIconGap", new Integer(4), "Button.textShiftOffset", new Integer(0), @@ -362,16 +362,16 @@ public abstract class BasicLookAndFeel extends LookAndFeel "HOME", "homePassThrough", "END", "endPassThrough" }), - "ComboBox.background", new ColorUIResource(light), + "ComboBox.background", new ColorUIResource(Color.white), "ComboBox.buttonBackground", new ColorUIResource(light), - "ComboBox.buttonDarkShadow", new ColorUIResource(shadow), + "ComboBox.buttonDarkShadow", new ColorUIResource(darkShadow), "ComboBox.buttonHighlight", new ColorUIResource(highLight), "ComboBox.buttonShadow", new ColorUIResource(shadow), "ComboBox.disabledBackground", new ColorUIResource(light), "ComboBox.disabledForeground", new ColorUIResource(Color.gray), "ComboBox.font", new FontUIResource("SansSerif", Font.PLAIN, 12), "ComboBox.foreground", new ColorUIResource(Color.black), - "ComboBox.selectionBackground", new ColorUIResource(Color.black), + "ComboBox.selectionBackground", new ColorUIResource(0, 0, 128), "ComboBox.selectionForeground", new ColorUIResource(Color.white), "Desktop.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { "KP_LEFT", "left", @@ -397,7 +397,7 @@ public abstract class BasicLookAndFeel extends LookAndFeel "DesktopIcon.border", new BorderUIResource.CompoundBorderUIResource(null, null), "EditorPane.background", new ColorUIResource(Color.white), - "EditorPane.border", new BasicBorders.MarginBorder(), + "EditorPane.border", BasicBorders.getMarginBorder(), "EditorPane.caretBlinkRate", new Integer(500), "EditorPane.caretForeground", new ColorUIResource(Color.black), "EditorPane.font", new FontUIResource("Serif", Font.PLAIN, 12), @@ -466,6 +466,8 @@ public abstract class BasicLookAndFeel extends LookAndFeel "FocusManagerClassName", "TODO", "FormattedTextField.background", new ColorUIResource(light), "FormattedTextField.caretForeground", new ColorUIResource(Color.black), + "FormattedTextField.font", + new FontUIResource("SansSerif", Font.PLAIN, 12), "FormattedTextField.foreground", new ColorUIResource(Color.black), "FormattedTextField.inactiveBackground", new ColorUIResource(light), "FormattedTextField.inactiveForeground", new ColorUIResource(Color.gray), @@ -528,30 +530,74 @@ public abstract class BasicLookAndFeel extends LookAndFeel "Label.disabledShadow", new ColorUIResource(shadow), "Label.font", new FontUIResource("Dialog", Font.PLAIN, 12), "Label.foreground", new ColorUIResource(darkShadow), - "List.background", new ColorUIResource(light), + "List.background", new ColorUIResource(Color.white), "List.border", new BasicBorders.MarginBorder(), "List.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { - "PAGE_UP", "scrollUp", - "ctrl \\", "clearSelection", - "PAGE_DOWN", "scrollDown", - "shift PAGE_DOWN","scrollDownExtendSelection", + "ctrl DOWN", "selectNextRowChangeLead", + "shift UP", "selectPreviousRowExtendSelection", + "ctrl RIGHT", "selectNextColumnChangeLead", + "shift ctrl LEFT", "selectPreviousColumnExtendSelection", + "shift KP_UP", "selectPreviousRowChangeLead", + "DOWN", "selectNextRow", + "ctrl UP", "selectPreviousRowChangeLead", + "ctrl LEFT", "selectPreviousColumnChangeLead", + "CUT", "cut", "END", "selectLastRow", - "HOME", "selectFirstRow", - "shift END", "selectLastRowExtendSelection", + "shift PAGE_UP","scrollUpExtendSelection", + "KP_UP", "selectPreviousRow", + "shift ctrl UP", "selectPreviousRowExtendSelection", + "ctrl HOME", "selectFirstRowChangeLead", + "shift LEFT", "selectPreviousColumnExtendSelection", + "ctrl END", "selectLastRowChangeLead", + "ctrl PAGE_DOWN", "scrollDownChangeLead", + "shift ctrl RIGHT", "selectNextColumnExtendSelection", + "LEFT", "selectPreviousColumn", + "ctrl PAGE_UP", "scrollUpChangeLead", + "KP_LEFT", "selectPreviousColumn", + "shift KP_RIGHT", "selectNextColumnExtendSelection", + "SPACE", "addToSelection", + "ctrl SPACE", "toggleAndAnchor", + "shift SPACE", "extendTo", + "shift ctrl SPACE", "moveSelectionTo", + "shift ctrl DOWN", "selectNextRowExtendSelection", + "ctrl BACK_SLASH", "clearSelection", "shift HOME", "selectFirstRowExtendSelection", - "UP", "selectPreviousRow", - "ctrl /", "selectAll", - "ctrl A", "selectAll", - "DOWN", "selectNextRow", - "shift UP", "selectPreviousRowExtendSelection", - "ctrl SPACE", "selectNextRowExtendSelection", + "RIGHT", "selectNextColumn", + "shift ctrl PAGE_UP", "scrollUpExtendSelection", "shift DOWN", "selectNextRowExtendSelection", - "KP_UP", "selectPreviousRow", - "shift PAGE_UP","scrollUpExtendSelection", - "KP_DOWN", "selectNextRow" + "PAGE_DOWN", "scrollDown", + "shift ctrl KP_UP", "selectPreviousRowExtendSelection", + "shift KP_LEFT", "selectPreviousColumnExtendSelection", + "ctrl X", "cut", + "shift ctrl PAGE_DOWN", "scrollDownExtendSelection", + "ctrl SLASH", "selectAll", + "ctrl C", "copy", + "ctrl KP_RIGHT", "selectNextColumnChangeLead", + "shift END", "selectLastRowExtendSelection", + "shift ctrl KP_DOWN", "selectNextRowExtendSelection", + "ctrl KP_LEFT", "selectPreviousColumnChangeLead", + "HOME", "selectFirstRow", + "ctrl V", "paste", + "KP_DOWN", "selectNextRow", + "ctrl KP_DOWN", "selectNextRowChangeLead", + "shift RIGHT", "selectNextColumnExtendSelection", + "ctrl A", "selectAll", + "shift ctrl END", "selectLastRowExtendSelection", + "COPY", "copy", + "ctrl KP_UP", "selectPreviousRowChangeLead", + "shift ctrl KP_LEFT", "selectPreviousColumnExtendSelection", + "shift KP_DOWN", "selectNextRowExtendSelection", + "UP", "selectPreviousRow", + "shift ctrl HOME", "selectFirstRowExtendSelection", + "shift PAGE_DOWN", "scrollDownExtendSelection", + "KP_RIGHT", "selectNextColumn", + "shift ctrl KP_RIGHT", "selectNextColumnExtendSelection", + "PAGE_UP", "scrollUp", + "PASTE", "paste" }), - "List.foreground", new ColorUIResource(darkShadow), - "List.selectionBackground", new ColorUIResource(Color.black), + "List.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "List.foreground", new ColorUIResource(Color.black), + "List.selectionBackground", new ColorUIResource(0, 0, 128), "List.selectionForeground", new ColorUIResource(Color.white), "List.focusCellHighlightBorder", new BorderUIResource. @@ -601,7 +647,6 @@ public abstract class BasicLookAndFeel extends LookAndFeel "MenuItem.background", new ColorUIResource(light), "MenuItem.border", new BasicBorders.MarginBorder(), "MenuItem.borderPainted", Boolean.FALSE, - "MenuItem.checkIcon", BasicIconFactory.getMenuItemCheckIcon(), "MenuItem.font", new FontUIResource("Dialog", Font.PLAIN, 12), "MenuItem.foreground", new ColorUIResource(darkShadow), "MenuItem.margin", new InsetsUIResource(2, 2, 2, 2), @@ -624,7 +669,9 @@ public abstract class BasicLookAndFeel extends LookAndFeel "OptionPane.messageAreaBorder", new BorderUIResource.EmptyBorderUIResource(0, 0, 0, 0), "OptionPane.messageForeground", new ColorUIResource(darkShadow), - "OptionPane.minimumSize", new DimensionUIResource(262, 90), + "OptionPane.minimumSize", + new DimensionUIResource(BasicOptionPaneUI.MinimumWidth, + BasicOptionPaneUI.MinimumHeight), "OptionPane.noButtonText", "No", "OptionPane.okButtonText", "OK", // XXX Don't use gif @@ -660,16 +707,17 @@ public abstract class BasicLookAndFeel extends LookAndFeel "PopupMenu.border", new BorderUIResource.BevelBorderUIResource(0), "PopupMenu.font", new FontUIResource("Dialog", Font.PLAIN, 12), "PopupMenu.foreground", new ColorUIResource(darkShadow), - "ProgressBar.background", new ColorUIResource(light), - "ProgressBar.border", new BorderUIResource.LineBorderUIResource(Color.darkGray), + "ProgressBar.background", new ColorUIResource(Color.LIGHT_GRAY), + "ProgressBar.border", + new BorderUIResource.LineBorderUIResource(Color.GREEN, 2), "ProgressBar.cellLength", new Integer(1), "ProgressBar.cellSpacing", new Integer(0), "ProgressBar.font", new FontUIResource("Dialog", Font.PLAIN, 12), - "ProgressBar.foreground", new ColorUIResource(Color.black), - "ProgressBar.selectionBackground", new ColorUIResource(Color.black), - "ProgressBar.selectionForeground", new ColorUIResource(light), - "ProgressBar.repaintInterval", new Integer(250), - "ProgressBar.cycleTime", new Integer(6000), + "ProgressBar.foreground", new ColorUIResource(0, 0, 128), + "ProgressBar.selectionBackground", new ColorUIResource(0, 0, 128), + "ProgressBar.selectionForeground", new ColorUIResource(Color.LIGHT_GRAY), + "ProgressBar.repaintInterval", new Integer(50), + "ProgressBar.cycleTime", new Integer(3000), "RadioButton.background", new ColorUIResource(light), "RadioButton.border", new BorderUIResource.CompoundBorderUIResource(null, null), @@ -742,6 +790,7 @@ public abstract class BasicLookAndFeel extends LookAndFeel "ScrollBar.thumbShadow", new ColorUIResource(shadow), "ScrollBar.track", new ColorUIResource(light), "ScrollBar.trackHighlight", new ColorUIResource(shadow), + "ScrollBar.width", new Integer(16), "ScrollPane.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { "PAGE_UP", "scrollUp", "KP_LEFT", "unitScrollLeft", @@ -846,6 +895,24 @@ public abstract class BasicLookAndFeel extends LookAndFeel "TabbedPane.tabRunOverlay", new Integer(2), "TabbedPane.textIconGap", new Integer(4), "Table.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { + "ctrl DOWN", "selectNextRowChangeLead", + "ctrl RIGHT", "selectNextColumnChangeLead", + "ctrl UP", "selectPreviousRowChangeLead", + "ctrl LEFT", "selectPreviousColumnChangeLead", + "CUT", "cut", + "SPACE", "addToSelection", + "ctrl SPACE", "toggleAndAnchor", + "shift SPACE", "extendTo", + "shift ctrl SPACE", "moveSelectionTo", + "ctrl X", "cut", + "ctrl C", "copy", + "ctrl KP_RIGHT", "selectNextColumnChangeLead", + "ctrl KP_LEFT", "selectPreviousColumnChangeLead", + "ctrl V", "paste", + "ctrl KP_DOWN", "selectNextRowChangeLead", + "COPY", "copy", + "ctrl KP_UP", "selectPreviousRowChangeLead", + "PASTE", "paste", "shift PAGE_DOWN","scrollDownExtendSelection", "PAGE_DOWN", "scrollDownChangeSelection", "END", "selectLastColumn", @@ -896,25 +963,26 @@ public abstract class BasicLookAndFeel extends LookAndFeel "ctrl SLASH", "selectAll", "ctrl shift KP_DOWN", "selectNextRowExtendSelection", }), - "Table.background", new ColorUIResource(light), - "Table.focusCellBackground", new ColorUIResource(light), - "Table.focusCellForeground", new ColorUIResource(darkShadow), + "Table.background", new ColorUIResource(new ColorUIResource(255, 255, 255)), + "Table.focusCellBackground", new ColorUIResource(new ColorUIResource(255, 255, 255)), + "Table.focusCellForeground", new ColorUIResource(new ColorUIResource(0, 0, 0)), "Table.focusCellHighlightBorder", new BorderUIResource.LineBorderUIResource( new ColorUIResource(255, 255, 0)), "Table.font", new FontUIResource("Dialog", Font.PLAIN, 12), - "Table.foreground", new ColorUIResource(darkShadow), - "Table.gridColor", new ColorUIResource(Color.gray), + "Table.foreground", new ColorUIResource(new ColorUIResource(0, 0, 0)), + "Table.gridColor", new ColorUIResource(new ColorUIResource(128, 128, 128)), "Table.scrollPaneBorder", new BorderUIResource.BevelBorderUIResource(0), - "Table.selectionBackground", new ColorUIResource(Color.black), - "Table.selectionForeground", new ColorUIResource(Color.white), - "TableHeader.background", new ColorUIResource(light), + "Table.selectionBackground", new ColorUIResource(new ColorUIResource(0, 0, 128)), + "Table.selectionForeground", new ColorUIResource(new ColorUIResource(255, 255, 255)), + "TableHeader.background", new ColorUIResource(new ColorUIResource(192, 192, 192)), "TableHeader.cellBorder", new BorderUIResource.BevelBorderUIResource(0), "TableHeader.font", new FontUIResource("Dialog", Font.PLAIN, 12), - "TableHeader.foreground", new ColorUIResource(darkShadow), + "TableHeader.foreground", new ColorUIResource(new ColorUIResource(0, 0, 0)), "TextArea.background", new ColorUIResource(light), - "TextArea.border", new BasicBorders.MarginBorder(), + "TextArea.border", + new BorderUIResource(BasicBorders.getMarginBorder()), "TextArea.caretBlinkRate", new Integer(500), "TextArea.caretForeground", new ColorUIResource(Color.black), "TextArea.font", new FontUIResource("MonoSpaced", Font.PLAIN, 12), @@ -945,8 +1013,8 @@ public abstract class BasicLookAndFeel extends LookAndFeel "TextField.font", new FontUIResource("SansSerif", Font.PLAIN, 12), "TextField.foreground", new ColorUIResource(Color.black), "TextField.highlight", new ColorUIResource(highLight), - "TextField.inactiveBackground", new ColorUIResource(light), - "TextField.inactiveForeground", new ColorUIResource(Color.gray), + "TextField.inactiveBackground", new ColorUIResource(Color.LIGHT_GRAY), + "TextField.inactiveForeground", new ColorUIResource(Color.GRAY), "TextField.light", new ColorUIResource(highLight), "TextField.highlight", new ColorUIResource(light), "TextField.keyBindings", new JTextComponent.KeyBinding[] { @@ -964,7 +1032,7 @@ public abstract class BasicLookAndFeel extends LookAndFeel "TextField.selectionBackground", new ColorUIResource(Color.black), "TextField.selectionForeground", new ColorUIResource(Color.white), "TextPane.background", new ColorUIResource(Color.white), - "TextPane.border", new BasicBorders.MarginBorder(), + "TextPane.border", BasicBorders.getMarginBorder(), "TextPane.caretBlinkRate", new Integer(500), "TextPane.caretForeground", new ColorUIResource(Color.black), "TextPane.font", new FontUIResource("Serif", Font.PLAIN, 12), @@ -1036,7 +1104,7 @@ public abstract class BasicLookAndFeel extends LookAndFeel "Tree.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { "ESCAPE", "cancel" }), - "Tree.background", new ColorUIResource(light), + "Tree.background", new ColorUIResource(new Color(255, 255, 255)), "Tree.changeSelectionWithFocus", Boolean.TRUE, // "Tree.closedIcon", new IconUIResource(new ImageIcon("icons/TreeClosed.png")), // "Tree.collapsedIcon", new IconUIResource(new ImageIcon("icons/TreeCollapsed.png")), @@ -1086,20 +1154,20 @@ public abstract class BasicLookAndFeel extends LookAndFeel "PAGE_UP", "scrollUpChangeSelection", "ctrl PAGE_DOWN", "scrollDownChangeLead" }), - "Tree.font", new FontUIResource(new Font("Helvetica", Font.PLAIN, 12)), + "Tree.font", new FontUIResource("Dialog", Font.PLAIN, 12), "Tree.foreground", new ColorUIResource(Color.black), "Tree.hash", new ColorUIResource(new Color(128, 128, 128)), "Tree.leftChildIndent", new Integer(7), "Tree.rightChildIndent", new Integer(13), - "Tree.rowHeight", new Integer(20), // FIXME + "Tree.rowHeight", new Integer(16), "Tree.scrollsOnExpand", Boolean.TRUE, "Tree.selectionBackground", new ColorUIResource(Color.black), - "Tree.nonSelectionBackground", new ColorUIResource(new Color(239, 235, 231)), + "Tree.nonSelectionBackground", new ColorUIResource(new Color(255, 255, 255)), "Tree.selectionBorderColor", new ColorUIResource(Color.black), "Tree.selectionBorder", new BorderUIResource.LineBorderUIResource(Color.black), "Tree.selectionForeground", new ColorUIResource(new Color(255, 255, 255)), - "Tree.textBackground", new ColorUIResource(new Color(255, 255, 255)), - "Tree.textForeground", new ColorUIResource(Color.black), + "Tree.textBackground", new ColorUIResource(new Color(192, 192, 192)), + "Tree.textForeground", new ColorUIResource(new Color(0, 0, 0)), "Viewport.background", new ColorUIResource(light), "Viewport.foreground", new ColorUIResource(Color.black), "Viewport.font", new FontUIResource("Dialog", Font.PLAIN, 12) diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java index 95f6b84fb7c..daa9b0d6b63 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java @@ -41,16 +41,19 @@ package javax.swing.plaf.basic; import java.awt.Dimension; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; +import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.BoxLayout; import javax.swing.JComponent; +import javax.swing.JMenu; import javax.swing.JMenuBar; -import javax.swing.UIDefaults; -import javax.swing.UIManager; +import javax.swing.LookAndFeel; +import javax.swing.MenuElement; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import javax.swing.event.MouseInputListener; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.MenuBarUI; @@ -63,12 +66,15 @@ public class BasicMenuBarUI extends MenuBarUI /*ContainerListener that listens to the ContainerEvents fired from menu bar*/ protected ContainerListener containerListener; - + /*Property change listeners that listener to PropertyChangeEvent from menu bar*/ protected PropertyChangeListener propertyChangeListener; /* menu bar for which this UI delegate is for*/ protected JMenuBar menuBar; + + /* MouseListener that listens to the mouseEvents fired from menu bar*/ + private MouseInputListener mouseListener; /** * Creates a new BasicMenuBarUI object. @@ -78,6 +84,7 @@ public class BasicMenuBarUI extends MenuBarUI changeListener = createChangeListener(); containerListener = createContainerListener(); propertyChangeListener = new PropertyChangeHandler(); + mouseListener = new MouseInputHandler(); } /** @@ -159,12 +166,9 @@ public class BasicMenuBarUI extends MenuBarUI */ protected void installDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - menuBar.setBackground(defaults.getColor("MenuBar.background")); - menuBar.setBorder(defaults.getBorder("MenuBar.border")); - menuBar.setFont(defaults.getFont("MenuBar.font")); - menuBar.setForeground(defaults.getColor("MenuBar.foreground")); + LookAndFeel.installBorder(menuBar, "MenuBar.border"); + LookAndFeel.installColorsAndFont(menuBar, "MenuBar.background", + "MenuBar.foreground", "MenuBar.font"); menuBar.setOpaque(true); } @@ -183,6 +187,7 @@ public class BasicMenuBarUI extends MenuBarUI { menuBar.addContainerListener(containerListener); menuBar.addPropertyChangeListener(propertyChangeListener); + menuBar.addMouseListener(mouseListener); } /** @@ -229,6 +234,7 @@ public class BasicMenuBarUI extends MenuBarUI { menuBar.removeContainerListener(containerListener); menuBar.removePropertyChangeListener(propertyChangeListener); + menuBar.removeMouseListener(mouseListener); } /** @@ -250,6 +256,7 @@ public class BasicMenuBarUI extends MenuBarUI { public void stateChanged(ChangeEvent event) { + // TODO: What should be done here, if anything? } } @@ -301,4 +308,84 @@ public class BasicMenuBarUI extends MenuBarUI menuBar.repaint(); } } + + private class MouseInputHandler implements MouseInputListener + { + /** + * Handles mouse clicked event + * + * @param e Mouse event + */ + public void mouseClicked(MouseEvent e) + { + MenuElement[] me = menuBar.getSubElements(); + + for (int i = 0; i < me.length; i++) + { + JMenu menu = menuBar.getMenu(i); + if (menu != null) + menu.setSelected(false); + } + } + + /** + * Handles mouse pressed event + * + * @param e Mouse event + */ + public void mousePressed(MouseEvent e) + { + // TODO: What should be done here, if anything? + } + + /** + * Handles mouse released event + * + * @param e Mouse event + */ + public void mouseReleased(MouseEvent e) + { + // TODO: What should be done here, if anything? + } + + /** + * Handles mouse exited event + * + * @param e Mouse event + */ + public void mouseExited(MouseEvent e) + { + // TODO: What should be done here, if anything? + } + + /** + * Handles mouse dragged event + * + * @param e Mouse event + */ + public void mouseDragged(MouseEvent e) + { + // TODO: What should be done here, if anything? + } + + /** + * Handles mouse moved event + * + * @param e Mouse event + */ + public void mouseMoved(MouseEvent e) + { + // TODO: What should be done here, if anything? + } + + /** + * Handles mouse entered event + * + * @param e Mouse event + */ + public void mouseEntered(MouseEvent e) + { + // TODO: What should be done here, if anything? + } + } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java index 8aa1193bcc4..2a3556a5db9 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java @@ -7,7 +7,7 @@ GNU Classpath is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - + GNU Classpath is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU @@ -46,18 +46,27 @@ import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Insets; import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; +import javax.swing.AbstractAction; +import javax.swing.ActionMap; +import javax.swing.ButtonModel; import javax.swing.Icon; +import javax.swing.InputMap; +import javax.swing.JCheckBoxMenuItem; import javax.swing.JComponent; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.KeyStroke; +import javax.swing.LookAndFeel; import javax.swing.MenuElement; import javax.swing.MenuSelectionManager; import javax.swing.SwingConstants; @@ -69,6 +78,8 @@ import javax.swing.event.MenuDragMouseListener; import javax.swing.event.MenuKeyEvent; import javax.swing.event.MenuKeyListener; import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ActionMapUIResource; +import javax.swing.plaf.ComponentInputMapUIResource; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.MenuItemUI; @@ -109,7 +120,7 @@ public class BasicMenuItemUI extends MenuItemUI * Number of spaces between icon and text. */ protected int defaultTextIconGap = 4; - + /** * Color of the text when menu item is disabled */ @@ -156,16 +167,69 @@ public class BasicMenuItemUI extends MenuItemUI private String acceleratorDelimiter; /** - * PropertyChangeListener to listen for property changes in the menu item + * ItemListener to listen for item changes in the menu item */ - private PropertyChangeListener propertyChangeListener; + private ItemListener itemListener; /** * Number of spaces between accelerator and menu item's label. */ - private int defaultAcceleratorLabelGap = 4; + private int defaultAcceleratorLabelGap = 10; /** + * The gap between different menus on the MenuBar. + */ + private int MenuGap = 10; + + /** A PropertyChangeListener to make UI updates after property changes **/ + PropertyChangeHandler propertyChangeListener; + + /** + * A class to handle PropertChangeEvents for the JMenuItem + * @author Anthony Balkissoon abalkiss at redhat dot com. + */ + class PropertyChangeHandler implements PropertyChangeListener + { + /** + * This method is called when a property of the menuItem is changed. + * Currently it is only used to update the accelerator key bindings. + * + * @param e + * the PropertyChangeEvent + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName() == "accelerator") + { + InputMap map = SwingUtilities.getUIInputMap(menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW); + if (map != null) + map.remove((KeyStroke)e.getOldValue()); + else + map = new ComponentInputMapUIResource(menuItem); + map.put((KeyStroke)e.getNewValue(), "doClick"); + } + } + } + + /** + * A class to handle accelerator keys. This is the Action we will + * perform when the accelerator key for this JMenuItem is pressed. + * @author Anthony Balkissoon abalkiss at redhat dot com + * + */ + class ClickAction extends AbstractAction + { + /** + * This is what is done when the accelerator key for the JMenuItem is + * pressed. + */ + public void actionPerformed(ActionEvent event) + { + doClick(MenuSelectionManager.defaultManager()); + } + } + + /** * Creates a new BasicMenuItemUI object. */ public BasicMenuItemUI() @@ -173,14 +237,15 @@ public class BasicMenuItemUI extends MenuItemUI mouseInputListener = createMouseInputListener(menuItem); menuDragMouseListener = createMenuDragMouseListener(menuItem); menuKeyListener = createMenuKeyListener(menuItem); + itemListener = new ItemHandler(); propertyChangeListener = new PropertyChangeHandler(); } /** * Create MenuDragMouseListener to listen for mouse dragged events. - * - * @param c menu item to listen to - * + * + * @param c + * menu item to listen to * @return The MenuDragMouseListener */ protected MenuDragMouseListener createMenuDragMouseListener(JComponent c) @@ -189,11 +254,11 @@ public class BasicMenuItemUI extends MenuItemUI } /** - * Creates MenuKeyListener to listen to key events occuring when menu item - * is visible on the screen. - * - * @param c menu item to listen to - * + * Creates MenuKeyListener to listen to key events occuring when menu item is + * visible on the screen. + * + * @param c + * menu item to listen to * @return The MenuKeyListener */ protected MenuKeyListener createMenuKeyListener(JComponent c) @@ -203,9 +268,9 @@ public class BasicMenuItemUI extends MenuItemUI /** * Handles mouse input events occuring for this menu item - * - * @param c menu item to listen to - * + * + * @param c + * menu item to listen to * @return The MouseInputListener */ protected MouseInputListener createMouseInputListener(JComponent c) @@ -216,9 +281,9 @@ public class BasicMenuItemUI extends MenuItemUI /** * Factory method to create a BasicMenuItemUI for the given {@link * JComponent}, which should be a {@link JMenuItem}. - * - * @param c The {@link JComponent} a UI is being created for. - * + * + * @param c + * The {@link JComponent} a UI is being created for. * @return A BasicMenuItemUI for the {@link JComponent}. */ public static ComponentUI createUI(JComponent c) @@ -228,8 +293,9 @@ public class BasicMenuItemUI extends MenuItemUI /** * Programatically clicks menu item. - * - * @param msm MenuSelectionManager for the menu hierarchy + * + * @param msm + * MenuSelectionManager for the menu hierarchy */ protected void doClick(MenuSelectionManager msm) { @@ -239,9 +305,9 @@ public class BasicMenuItemUI extends MenuItemUI /** * Returns maximum size for the specified menu item - * - * @param c component for which to get maximum size - * + * + * @param c + * component for which to get maximum size * @return Maximum size for the specified menu item. */ public Dimension getMaximumSize(JComponent c) @@ -251,9 +317,9 @@ public class BasicMenuItemUI extends MenuItemUI /** * Returns minimum size for the specified menu item - * - * @param c component for which to get minimum size - * + * + * @param c + * component for which to get minimum size * @return Minimum size for the specified menu item. */ public Dimension getMinimumSize(JComponent c) @@ -263,9 +329,9 @@ public class BasicMenuItemUI extends MenuItemUI /** * Returns path to this menu item. - * - * @return $MenuElement[]$ Returns array of menu elements - * that constitute a path to this menu item. + * + * @return $MenuElement[]$ Returns array of menu elements that constitute a + * path to this menu item. */ public MenuElement[] getPath() { @@ -278,12 +344,12 @@ public class BasicMenuItemUI extends MenuItemUI Component c = menuItem; while (c instanceof MenuElement) { - path.add(0, (MenuElement) c); + path.add(0, (MenuElement) c); - if (c instanceof JPopupMenu) - c = ((JPopupMenu) c).getInvoker(); - else - c = c.getParent(); + if (c instanceof JPopupMenu) + c = ((JPopupMenu) c).getInvoker(); + else + c = c.getParent(); } MenuElement[] pathArray = new MenuElement[path.size()]; @@ -293,12 +359,15 @@ public class BasicMenuItemUI extends MenuItemUI /** * Returns preferred size for the given menu item. - * - * @param c menu item for which to get preferred size - * @param checkIcon check icon displayed in the given menu item - * @param arrowIcon arrow icon displayed in the given menu item - * @param defaultTextIconGap space between icon and text in the given menuItem - * + * + * @param c + * menu item for which to get preferred size + * @param checkIcon + * check icon displayed in the given menu item + * @param arrowIcon + * arrow icon displayed in the given menu item + * @param defaultTextIconGap + * space between icon and text in the given menuItem * @return $Dimension$ preferred size for the given menu item */ protected Dimension getPreferredMenuItemSize(JComponent c, Icon checkIcon, @@ -308,7 +377,7 @@ public class BasicMenuItemUI extends MenuItemUI JMenuItem m = (JMenuItem) c; Dimension d = BasicGraphicsUtils.getPreferredButtonSize(m, defaultTextIconGap); - + // if menu item has accelerator then take accelerator's size into account // when calculating preferred size. KeyStroke accelerator = m.getAccelerator(); @@ -316,52 +385,57 @@ public class BasicMenuItemUI extends MenuItemUI if (accelerator != null) { - rect = getAcceleratorRect(accelerator, - m.getToolkit().getFontMetrics(acceleratorFont)); + rect = getAcceleratorRect( + accelerator, + m.getToolkit().getFontMetrics(acceleratorFont)); - // add width of accelerator's text - d.width = d.width + rect.width + defaultAcceleratorLabelGap; + // add width of accelerator's text + d.width += rect.width + defaultAcceleratorLabelGap; - // adjust the heigth of the preferred size if necessary - if (d.height < rect.height) - d.height = rect.height; + // adjust the heigth of the preferred size if necessary + if (d.height < rect.height) + d.height = rect.height; } if (checkIcon != null) { - d.width = d.width + checkIcon.getIconWidth() + defaultTextIconGap; + d.width += checkIcon.getIconWidth() + defaultTextIconGap; - if (checkIcon.getIconHeight() > d.height) - d.height = checkIcon.getIconHeight(); + if (checkIcon.getIconHeight() > d.height) + d.height = checkIcon.getIconHeight(); } if (arrowIcon != null && (c instanceof JMenu)) { - d.width = d.width + arrowIcon.getIconWidth() + defaultTextIconGap; - - if (arrowIcon.getIconHeight() > d.height) - d.height = arrowIcon.getIconHeight(); + int pWidth = m.getParent().getWidth(); + if (!((JMenu)c).isTopLevelMenu() && d.width < pWidth) + d.width = pWidth + - m.getInsets().left - m.getInsets().right; + else + d.width += arrowIcon.getIconWidth() + MenuGap; + + if (arrowIcon.getIconHeight() > d.height) + d.height = arrowIcon.getIconHeight(); } - + return d; } /** * Returns preferred size of the given component - * - * @param c component for which to return preferred size - * + * + * @param c + * component for which to return preferred size * @return $Dimension$ preferred size for the given component */ public Dimension getPreferredSize(JComponent c) { - return getPreferredMenuItemSize(c, checkIcon, arrowIcon, - defaultTextIconGap); + return getPreferredMenuItemSize(c, checkIcon, arrowIcon, defaultTextIconGap); } /** * Returns the prefix for entries in the {@link UIDefaults} table. - * + * * @return "MenuItem" */ protected String getPropertyPrefix() @@ -371,8 +445,9 @@ public class BasicMenuItemUI extends MenuItemUI /** * This method installs the components for this {@link JMenuItem}. - * - * @param menuItem The {@link JMenuItem} to install components for. + * + * @param menuItem + * The {@link JMenuItem} to install components for. */ protected void installComponents(JMenuItem menuItem) { @@ -380,28 +455,27 @@ public class BasicMenuItemUI extends MenuItemUI } /** - * This method installs the defaults that are defined in the Basic look and + * This method installs the defaults that are defined in the Basic look and * feel for this {@link JMenuItem}. */ protected void installDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - menuItem.setBackground(defaults.getColor("MenuItem.background")); - menuItem.setBorder(defaults.getBorder("MenuItem.border")); - menuItem.setFont(defaults.getFont("MenuItem.font")); - menuItem.setForeground(defaults.getColor("MenuItem.foreground")); - menuItem.setMargin(defaults.getInsets("MenuItem.margin")); - menuItem.setOpaque(true); - acceleratorFont = defaults.getFont("MenuItem.acceleratorFont"); - acceleratorForeground = defaults.getColor("MenuItem.acceleratorForeground"); - acceleratorSelectionForeground = defaults.getColor("MenuItem.acceleratorSelectionForeground"); - selectionBackground = defaults.getColor("MenuItem.selectionBackground"); - selectionForeground = defaults.getColor("MenuItem.selectionForeground"); - acceleratorDelimiter = defaults.getString("MenuItem.acceleratorDelimiter"); - + String prefix = getPropertyPrefix(); + LookAndFeel.installBorder(menuItem, prefix + ".border"); + LookAndFeel.installColorsAndFont(menuItem, prefix + ".background", + prefix + ".foreground", prefix + ".font"); + menuItem.setMargin(UIManager.getInsets(prefix + ".margin")); + acceleratorFont = UIManager.getFont(prefix + ".acceleratorFont"); + acceleratorForeground = UIManager.getColor(prefix + ".acceleratorForeground"); + acceleratorSelectionForeground = UIManager.getColor(prefix + ".acceleratorSelectionForeground"); + selectionBackground = UIManager.getColor(prefix + ".selectionBackground"); + selectionForeground = UIManager.getColor(prefix + ".selectionForeground"); + acceleratorDelimiter = UIManager.getString(prefix + ".acceleratorDelimiter"); + checkIcon = UIManager.getIcon(prefix + ".checkIcon"); + menuItem.setHorizontalTextPosition(SwingConstants.TRAILING); menuItem.setHorizontalAlignment(SwingConstants.LEADING); + menuItem.setOpaque(true); } /** @@ -409,7 +483,17 @@ public class BasicMenuItemUI extends MenuItemUI */ protected void installKeyboardActions() { - // FIXME: Need to implement + InputMap focusedWindowMap = SwingUtilities.getUIInputMap(menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW); + if (focusedWindowMap == null) + focusedWindowMap = new ComponentInputMapUIResource(menuItem); + focusedWindowMap.put(menuItem.getAccelerator(), "doClick"); + SwingUtilities.replaceUIInputMap(menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW, focusedWindowMap); + + ActionMap UIActionMap = SwingUtilities.getUIActionMap(menuItem); + if (UIActionMap == null) + UIActionMap = new ActionMapUIResource(); + UIActionMap.put("doClick", new ClickAction()); + SwingUtilities.replaceUIActionMap(menuItem, UIActionMap); } /** @@ -421,15 +505,17 @@ public class BasicMenuItemUI extends MenuItemUI menuItem.addMouseMotionListener(mouseInputListener); menuItem.addMenuDragMouseListener(menuDragMouseListener); menuItem.addMenuKeyListener(menuKeyListener); + menuItem.addItemListener(itemListener); menuItem.addPropertyChangeListener(propertyChangeListener); } /** - * Installs and initializes all fields for this UI delegate. Any properties - * of the UI that need to be initialized and/or set to defaults will be - * done now. It will also install any listeners necessary. - * - * @param c The {@link JComponent} that is having this UI installed. + * Installs and initializes all fields for this UI delegate. Any properties of + * the UI that need to be initialized and/or set to defaults will be done now. + * It will also install any listeners necessary. + * + * @param c + * The {@link JComponent} that is having this UI installed. */ public void installUI(JComponent c) { @@ -438,13 +524,16 @@ public class BasicMenuItemUI extends MenuItemUI installDefaults(); installComponents(menuItem); installListeners(); + installKeyboardActions(); } /** * Paints given menu item using specified graphics context - * - * @param g The graphics context used to paint this menu item - * @param c Menu Item to paint + * + * @param g + * The graphics context used to paint this menu item + * @param c + * Menu Item to paint */ public void paint(Graphics g, JComponent c) { @@ -454,10 +543,13 @@ public class BasicMenuItemUI extends MenuItemUI /** * Paints background of the menu item - * - * @param g The graphics context used to paint this menu item - * @param menuItem menu item to paint - * @param bgColor Background color to use when painting menu item + * + * @param g + * The graphics context used to paint this menu item + * @param menuItem + * menu item to paint + * @param bgColor + * Background color to use when painting menu item */ protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) { @@ -470,15 +562,21 @@ public class BasicMenuItemUI extends MenuItemUI /** * Paints specified menu item - * - * @param g The graphics context used to paint this menu item - * @param c menu item to paint - * @param checkIcon check icon to use when painting menu item - * @param arrowIcon arrow icon to use when painting menu item - * @param background Background color of the menu item - * @param foreground Foreground color of the menu item - * @param defaultTextIconGap space to use between icon and - * text when painting menu item + * + * @param g + * The graphics context used to paint this menu item + * @param c + * menu item to paint + * @param checkIcon + * check icon to use when painting menu item + * @param arrowIcon + * arrow icon to use when painting menu item + * @param background + * Background color of the menu item + * @param foreground + * Foreground color of the menu item + * @param defaultTextIconGap + * space to use between icon and text when painting menu item */ protected void paintMenuItem(Graphics g, JComponent c, Icon checkIcon, Icon arrowIcon, Color background, @@ -496,7 +594,7 @@ public class BasicMenuItemUI extends MenuItemUI int horAlign = m.getHorizontalAlignment(); int vertTextPos = m.getVerticalTextPosition(); int horTextPos = m.getHorizontalTextPosition(); - + Font f = m.getFont(); g.setFont(f); FontMetrics fm = g.getFontMetrics(f); @@ -504,8 +602,10 @@ public class BasicMenuItemUI extends MenuItemUI SwingUtilities.calculateInsetArea(br, m.getInsets(), vr); paintBackground(g, m, m.getBackground()); - /* MenuItems insets are equal to menuItems margin, space between text and - menuItems border. We need to paint insets region as well. */ + /* + * MenuItems insets are equal to menuItems margin, space between text and + * menuItems border. We need to paint insets region as well. + */ Insets insets = m.getInsets(); br.x -= insets.left; br.y -= insets.top; @@ -514,89 +614,93 @@ public class BasicMenuItemUI extends MenuItemUI // Menu item is considered to be highlighted when it is selected. // But we don't want to paint the background of JCheckBoxMenuItems - if ((m.isSelected() && checkIcon == null) || m.getModel().isArmed() && - (m.getParent() instanceof MenuElement)) + ButtonModel mod = m.getModel(); + if ((m.isSelected() && checkIcon == null) || (mod != null && + mod.isArmed()) + && (m.getParent() instanceof MenuElement)) { - if (m.isContentAreaFilled()) - { - g.setColor(selectionBackground); - g.fillRect(br.x, br.y, br.width, br.height); - } + if (m.isContentAreaFilled()) + { + g.setColor(selectionBackground); + g.fillRect(br.x, br.y, br.width, br.height); + } } else { - if (m.isContentAreaFilled()) - { - g.setColor(m.getBackground()); - g.fillRect(br.x, br.y, br.width, br.height); - } + if (m.isContentAreaFilled()) + { + g.setColor(m.getBackground()); + g.fillRect(br.x, br.y, br.width, br.height); + } } // If this menu item is a JCheckBoxMenuItem then paint check icon if (checkIcon != null) { - SwingUtilities.layoutCompoundLabel(m, fm, null, checkIcon, vertAlign, - horAlign, vertTextPos, horTextPos, - vr, cr, tr, defaultTextIconGap); + SwingUtilities.layoutCompoundLabel(m, fm, null, checkIcon, vertAlign, + horAlign, vertTextPos, horTextPos, + vr, cr, tr, defaultTextIconGap); checkIcon.paintIcon(m, g, cr.x, cr.y); - // We need to calculate position of the menu text and position of - // user menu icon if there exists one relative to the check icon. - // So we need to adjust view rectangle s.t. its starting point is at - // checkIcon.width + defaultTextIconGap. - vr.x = cr.x + cr.width + defaultTextIconGap; + // We need to calculate position of the menu text and position of + // user menu icon if there exists one relative to the check icon. + // So we need to adjust view rectangle s.t. its starting point is at + // checkIcon.width + defaultTextIconGap. + vr.x = cr.x + cr.width + defaultTextIconGap; } // if this is a submenu, then paint arrow icon to indicate it. if (arrowIcon != null && (c instanceof JMenu)) { - if (! ((JMenu) c).isTopLevelMenu()) - { - int width = arrowIcon.getIconWidth(); - int height = arrowIcon.getIconHeight(); - - arrowIcon.paintIcon(m, g, vr.width - width + defaultTextIconGap, - vr.y + 2); - } + if (!((JMenu) c).isTopLevelMenu()) + { + int width = arrowIcon.getIconWidth(); + int height = arrowIcon.getIconHeight(); + int offset = (vr.height - height) / 2; + arrowIcon.paintIcon(m, g, vr.width - width, vr.y + offset); + } } - // paint text and user menu icon if it exists + // paint text and user menu icon if it exists Icon i = m.getIcon(); - SwingUtilities.layoutCompoundLabel(c, fm, m.getText(), i, - vertAlign, horAlign, vertTextPos, - horTextPos, vr, ir, tr, - defaultTextIconGap); + SwingUtilities.layoutCompoundLabel(c, fm, m.getText(), i, vertAlign, + horAlign, vertTextPos, horTextPos, vr, + ir, tr, defaultTextIconGap); if (i != null) i.paintIcon(c, g, ir.x, ir.y); paintText(g, m, tr, m.getText()); - // paint accelerator + // paint accelerator String acceleratorText = ""; if (m.getAccelerator() != null) { - acceleratorText = getAcceleratorText(m.getAccelerator()); - fm = g.getFontMetrics(acceleratorFont); - ar.width = fm.stringWidth(acceleratorText); - ar.x = br.width - ar.width; - vr.x = br.width - ar.width; - - SwingUtilities.layoutCompoundLabel(m, fm, acceleratorText, null, - vertAlign, horAlign, vertTextPos, - horTextPos, vr, ir, ar, - defaultTextIconGap); - - paintAccelerator(g, m, ar, acceleratorText); + acceleratorText = getAcceleratorText(m.getAccelerator()); + fm = g.getFontMetrics(acceleratorFont); + ar.width = fm.stringWidth(acceleratorText); + ar.x = br.width - ar.width; + vr.x = br.width - ar.width - defaultTextIconGap; + + SwingUtilities.layoutCompoundLabel(m, fm, acceleratorText, null, + vertAlign, horAlign, vertTextPos, + horTextPos, vr, ir, ar, + defaultTextIconGap); + + paintAccelerator(g, m, ar, acceleratorText); } } /** * Paints label for the given menu item - * - * @param g The graphics context used to paint this menu item - * @param menuItem menu item for which to draw its label - * @param textRect rectangle specifiying position of the text relative to - * the given menu item - * @param text label of the menu item + * + * @param g + * The graphics context used to paint this menu item + * @param menuItem + * menu item for which to draw its label + * @param textRect + * rectangle specifiying position of the text relative to the given + * menu item + * @param text + * label of the menu item */ protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) @@ -605,43 +709,46 @@ public class BasicMenuItemUI extends MenuItemUI g.setFont(f); FontMetrics fm = g.getFontMetrics(f); - if (text != null && ! text.equals("")) + if (text != null && !text.equals("")) { - if (menuItem.isEnabled()) + if (menuItem.isEnabled()) { // Menu item is considered to be highlighted when it is selected. // But not if it's a JCheckBoxMenuItem - if ((menuItem.isSelected() && checkIcon == null) || menuItem.getModel().isArmed() && - (menuItem.getParent() instanceof MenuElement)) + ButtonModel mod = menuItem.getModel(); + if ((menuItem.isSelected() && checkIcon == null) + || (mod != null && mod.isArmed()) + && (menuItem.getParent() instanceof MenuElement)) g.setColor(selectionForeground); else g.setColor(menuItem.getForeground()); } - else - // FIXME: should fix this to use 'disabledForeground', but its - // default value in BasicLookAndFeel is null. - + else + // FIXME: should fix this to use 'disabledForeground', but its + // default value in BasicLookAndFeel is null. + // FIXME: should there be different foreground colours for selected // or deselected, when disabled? g.setColor(Color.gray); - int mnemonicIndex = menuItem.getDisplayedMnemonicIndex(); + int mnemonicIndex = menuItem.getDisplayedMnemonicIndex(); - if (mnemonicIndex != -1) - BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, mnemonicIndex, - textRect.x, - textRect.y - + fm.getAscent()); - else - BasicGraphicsUtils.drawString(g, text, 0, textRect.x, - textRect.y + fm.getAscent()); + if (mnemonicIndex != -1) + BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, mnemonicIndex, + textRect.x, + textRect.y + + fm.getAscent()); + else + BasicGraphicsUtils.drawString(g, text, 0, textRect.x, + textRect.y + fm.getAscent()); } } /** * This method uninstalls the components for this {@link JMenuItem}. - * - * @param menuItem The {@link JMenuItem} to uninstall components for. + * + * @param menuItem + * The {@link JMenuItem} to uninstall components for. */ protected void uninstallComponents(JMenuItem menuItem) { @@ -676,8 +783,9 @@ public class BasicMenuItemUI extends MenuItemUI * Uninstalls any keyboard actions. */ protected void uninstallKeyboardActions() - { - // FIXME: need to implement + { + SwingUtilities.replaceUIInputMap(menuItem, + JComponent.WHEN_IN_FOCUSED_WINDOW, null); } /** @@ -688,15 +796,17 @@ public class BasicMenuItemUI extends MenuItemUI menuItem.removeMouseListener(mouseInputListener); menuItem.removeMenuDragMouseListener(menuDragMouseListener); menuItem.removeMenuKeyListener(menuKeyListener); + menuItem.removeItemListener(itemListener); menuItem.removePropertyChangeListener(propertyChangeListener); } /** * Performs the opposite of installUI. Any properties or resources that need - * to be cleaned up will be done now. It will also uninstall any listeners - * it has. In addition, any properties of this UI will be nulled. - * - * @param c The {@link JComponent} that is having this UI uninstalled. + * to be cleaned up will be done now. It will also uninstall any listeners it + * has. In addition, any properties of this UI will be nulled. + * + * @param c + * The {@link JComponent} that is having this UI uninstalled. */ public void uninstallUI(JComponent c) { @@ -708,9 +818,11 @@ public class BasicMenuItemUI extends MenuItemUI /** * This method calls paint. - * - * @param g The graphics context used to paint this menu item - * @param c The menu item to paint + * + * @param g + * The graphics context used to paint this menu item + * @param c + * The menu item to paint */ public void update(Graphics g, JComponent c) { @@ -719,9 +831,9 @@ public class BasicMenuItemUI extends MenuItemUI /** * Return text representation of the specified accelerator - * - * @param accelerator Accelerator for which to return string representation - * + * + * @param accelerator + * Accelerator for which to return string representation * @return $String$ Text representation of the given accelerator */ private String getAcceleratorText(KeyStroke accelerator) @@ -744,10 +856,11 @@ public class BasicMenuItemUI extends MenuItemUI /** * Calculates and return rectange in which accelerator should be displayed - * - * @param accelerator accelerator for which to return the display rectangle - * @param fm The font metrics used to measure the text - * + * + * @param accelerator + * accelerator for which to return the display rectangle + * @param fm + * The font metrics used to measure the text * @return $Rectangle$ reactangle which will be used to display accelerator */ private Rectangle getAcceleratorRect(KeyStroke accelerator, FontMetrics fm) @@ -759,12 +872,16 @@ public class BasicMenuItemUI extends MenuItemUI /** * Paints accelerator inside menu item - * - * @param g The graphics context used to paint the border - * @param menuItem Menu item for which to draw accelerator - * @param acceleratorRect rectangle representing position - * of the accelerator relative to the menu item - * @param acceleratorText accelerator's text + * + * @param g + * The graphics context used to paint the border + * @param menuItem + * Menu item for which to draw accelerator + * @param acceleratorRect + * rectangle representing position of the accelerator relative to the + * menu item + * @param acceleratorText + * accelerator's text */ private void paintAccelerator(Graphics g, JMenuItem menuItem, Rectangle acceleratorRect, @@ -785,10 +902,9 @@ public class BasicMenuItemUI extends MenuItemUI } /** - * This class handles mouse events occuring inside the menu item. - * Most of the events are forwarded for processing to MenuSelectionManager - * of the current menu hierarchy. - * + * This class handles mouse events occuring inside the menu item. Most of the + * events are forwarded for processing to MenuSelectionManager of the current + * menu hierarchy. */ protected class MouseInputHandler implements MouseInputListener { @@ -797,13 +913,15 @@ public class BasicMenuItemUI extends MenuItemUI */ protected MouseInputHandler() { + // Nothing to do here. } /** - * This method is called when mouse is clicked on the menu item. - * It forwards this event to MenuSelectionManager. - * - * @param e A {@link MouseEvent}. + * This method is called when mouse is clicked on the menu item. It forwards + * this event to MenuSelectionManager. + * + * @param e + * A {@link MouseEvent}. */ public void mouseClicked(MouseEvent e) { @@ -812,10 +930,11 @@ public class BasicMenuItemUI extends MenuItemUI } /** - * This method is called when mouse is dragged inside the menu item. - * It forwards this event to MenuSelectionManager. - * - * @param e A {@link MouseEvent}. + * This method is called when mouse is dragged inside the menu item. It + * forwards this event to MenuSelectionManager. + * + * @param e + * A {@link MouseEvent}. */ public void mouseDragged(MouseEvent e) { @@ -824,29 +943,31 @@ public class BasicMenuItemUI extends MenuItemUI } /** - * This method is called when mouse enters menu item. - * When this happens menu item is considered to be selected and selection path - * in MenuSelectionManager is set. This event is also forwarded to MenuSelection - * Manager for further processing. - * - * @param e A {@link MouseEvent}. + * This method is called when mouse enters menu item. When this happens menu + * item is considered to be selected and selection path in + * MenuSelectionManager is set. This event is also forwarded to + * MenuSelection Manager for further processing. + * + * @param e + * A {@link MouseEvent}. */ public void mouseEntered(MouseEvent e) { Component source = (Component) e.getSource(); if (source.getParent() instanceof MenuElement) { - MenuSelectionManager manager = MenuSelectionManager.defaultManager(); - manager.setSelectedPath(getPath()); - manager.processMouseEvent(e); + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.setSelectedPath(getPath()); + manager.processMouseEvent(e); } } /** - * This method is called when mouse exits menu item. The event is - * forwarded to MenuSelectionManager for processing. - * - * @param e A {@link MouseEvent}. + * This method is called when mouse exits menu item. The event is forwarded + * to MenuSelectionManager for processing. + * + * @param e + * A {@link MouseEvent}. */ public void mouseExited(MouseEvent e) { @@ -855,10 +976,11 @@ public class BasicMenuItemUI extends MenuItemUI } /** - * This method is called when mouse is inside the menu item. - * This event is forwarder to MenuSelectionManager for further processing. - * - * @param e A {@link MouseEvent}. + * This method is called when mouse is inside the menu item. This event is + * forwarder to MenuSelectionManager for further processing. + * + * @param e + * A {@link MouseEvent}. */ public void mouseMoved(MouseEvent e) { @@ -869,8 +991,9 @@ public class BasicMenuItemUI extends MenuItemUI /** * This method is called when mouse is pressed. This event is forwarded to * MenuSelectionManager for further processing. - * - * @param e A {@link MouseEvent}. + * + * @param e + * A {@link MouseEvent}. */ public void mousePressed(MouseEvent e) { @@ -882,8 +1005,9 @@ public class BasicMenuItemUI extends MenuItemUI * This method is called when mouse is released. If the mouse is released * inside this menuItem, then this menu item is considered to be chosen and * the menu hierarchy should be closed. - * - * @param e A {@link MouseEvent}. + * + * @param e + * A {@link MouseEvent}. */ public void mouseReleased(MouseEvent e) { @@ -892,24 +1016,25 @@ public class BasicMenuItemUI extends MenuItemUI if (e.getX() > 0 && e.getX() < size.width && e.getY() > 0 && e.getY() < size.height) { - manager.clearSelectedPath(); - menuItem.doClick(); + manager.clearSelectedPath(); + menuItem.doClick(); } else - manager.processMouseEvent(e); + manager.processMouseEvent(e); } } /** * This class handles mouse dragged events. */ - protected class MenuDragMouseHandler implements MenuDragMouseListener + private class MenuDragMouseHandler implements MenuDragMouseListener { /** * Tbis method is invoked when mouse is dragged over the menu item. - * - * @param e The MenuDragMouseEvent + * + * @param e + * The MenuDragMouseEvent */ public void menuDragMouseDragged(MenuDragMouseEvent e) { @@ -918,10 +1043,11 @@ public class BasicMenuItemUI extends MenuItemUI } /** - * Tbis method is invoked when mouse enters the menu item while it is - * being dragged. - * - * @param e The MenuDragMouseEvent + * Tbis method is invoked when mouse enters the menu item while it is being + * dragged. + * + * @param e + * The MenuDragMouseEvent */ public void menuDragMouseEntered(MenuDragMouseEvent e) { @@ -930,27 +1056,29 @@ public class BasicMenuItemUI extends MenuItemUI } /** - * Tbis method is invoked when mouse exits the menu item while - * it is being dragged - * - * @param e The MenuDragMouseEvent + * Tbis method is invoked when mouse exits the menu item while it is being + * dragged + * + * @param e the MenuDragMouseEvent */ public void menuDragMouseExited(MenuDragMouseEvent e) { + // TODO: What should be done here, if anything? } /** - * Tbis method is invoked when mouse was dragged and released - * inside the menu item. - * - * @param e The MenuDragMouseEvent + * Tbis method is invoked when mouse was dragged and released inside the + * menu item. + * + * @param e + * The MenuDragMouseEvent */ public void menuDragMouseReleased(MenuDragMouseEvent e) { MenuElement[] path = e.getPath(); if (path[path.length - 1] instanceof JMenuItem) - ((JMenuItem) path[path.length - 1]).doClick(); + ((JMenuItem) path[path.length - 1]).doClick(); MenuSelectionManager manager = MenuSelectionManager.defaultManager(); manager.clearSelectedPath(); @@ -961,50 +1089,63 @@ public class BasicMenuItemUI extends MenuItemUI * This class handles key events occuring when menu item is visible on the * screen. */ - protected class MenuKeyHandler implements MenuKeyListener + private class MenuKeyHandler implements MenuKeyListener { /** * This method is invoked when key has been pressed - * - * @param e A {@link MenuKeyEvent}. + * + * @param e + * A {@link MenuKeyEvent}. */ public void menuKeyPressed(MenuKeyEvent e) { + // TODO: What should be done here, if anything? } /** * This method is invoked when key has been pressed - * - * @param e A {@link MenuKeyEvent}. + * + * @param e + * A {@link MenuKeyEvent}. */ public void menuKeyReleased(MenuKeyEvent e) { + // TODO: What should be done here, if anything? } /** - * This method is invoked when key has been typed - * It handles the mnemonic key for the menu item. - * - * @param e A {@link MenuKeyEvent}. + * This method is invoked when key has been typed It handles the mnemonic + * key for the menu item. + * + * @param e + * A {@link MenuKeyEvent}. */ public void menuKeyTyped(MenuKeyEvent e) { + // TODO: What should be done here, if anything? } } - + /** - * Helper class that listens for changes to the properties of the {@link + * Helper class that listens for item changes to the properties of the {@link * JMenuItem}. */ - protected class PropertyChangeHandler implements PropertyChangeListener + private class ItemHandler implements ItemListener { /** - * This method is called when one of the menu item's properties change. + * This method is called when one of the menu item changes. * - * @param evt A {@link PropertyChangeEvent}. + * @param evt A {@link ItemEvent}. */ - public void propertyChange(PropertyChangeEvent evt) + public void itemStateChanged(ItemEvent evt) { + boolean state = false; + if (menuItem instanceof JCheckBoxMenuItem) + { + if (evt.getStateChange() == ItemEvent.SELECTED) + state = true; + ((JCheckBoxMenuItem) menuItem).setState(state); + } menuItem.revalidate(); menuItem.repaint(); } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java index 30be592ee79..827cbb0f50d 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java @@ -38,6 +38,7 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import java.awt.Component; import java.awt.Dimension; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; @@ -46,8 +47,8 @@ import java.beans.PropertyChangeListener; import javax.swing.JComponent; import javax.swing.JMenu; import javax.swing.JMenuBar; -import javax.swing.JMenuItem; import javax.swing.JPopupMenu; +import javax.swing.LookAndFeel; import javax.swing.MenuSelectionManager; import javax.swing.UIDefaults; import javax.swing.UIManager; @@ -92,7 +93,7 @@ public class BasicMenuUI extends BasicMenuItemUI */ protected ChangeListener createChangeListener(JComponent c) { - return new ChangeHandler(); + return new ChangeHandler((JMenu) c, this); } /** @@ -180,12 +181,6 @@ public class BasicMenuUI extends BasicMenuItemUI */ public Dimension getMaximumSize(JComponent c) { - // If this menu is in a popup menu, treat it like a regular JMenuItem - if (!((JMenu)c).isTopLevelMenu()) - { - JMenuItem menuItem = new JMenuItem(((JMenu)c).getText(), ((JMenu)c).getIcon()); - return menuItem.getMaximumSize(); - } return c.getPreferredSize(); } @@ -205,20 +200,17 @@ public class BasicMenuUI extends BasicMenuItemUI */ protected void installDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - menuItem.setBackground(defaults.getColor("Menu.background")); - menuItem.setBorder(defaults.getBorder("Menu.border")); - menuItem.setFont(defaults.getFont("Menu.font")); - menuItem.setForeground(defaults.getColor("Menu.foreground")); - menuItem.setMargin(defaults.getInsets("Menu.margin")); - acceleratorFont = defaults.getFont("Menu.acceleratorFont"); - acceleratorForeground = defaults.getColor("Menu.acceleratorForeground"); - acceleratorSelectionForeground = defaults.getColor("Menu.acceleratorSelectionForeground"); - selectionBackground = defaults.getColor("Menu.selectionBackground"); - selectionForeground = defaults.getColor("Menu.selectionForeground"); - arrowIcon = defaults.getIcon("Menu.arrowIcon"); - oldBorderPainted = defaults.getBoolean("Menu.borderPainted"); + LookAndFeel.installBorder(menuItem, "Menu.border"); + LookAndFeel.installColorsAndFont(menuItem, "Menu.background", + "Menu.foreground", "Menu.font"); + menuItem.setMargin(UIManager.getInsets("Menu.margin")); + acceleratorFont = UIManager.getFont("Menu.acceleratorFont"); + acceleratorForeground = UIManager.getColor("Menu.acceleratorForeground"); + acceleratorSelectionForeground = UIManager.getColor("Menu.acceleratorSelectionForeground"); + selectionBackground = UIManager.getColor("Menu.selectionBackground"); + selectionForeground = UIManager.getColor("Menu.selectionForeground"); + arrowIcon = UIManager.getIcon("Menu.arrowIcon"); + oldBorderPainted = UIManager.getBoolean("Menu.borderPainted"); menuItem.setOpaque(true); } @@ -245,6 +237,7 @@ public class BasicMenuUI extends BasicMenuItemUI protected void setupPostTimer(JMenu menu) { + // TODO: Implement this properly. } /** @@ -356,6 +349,7 @@ public class BasicMenuUI extends BasicMenuItemUI public void mouseMoved(MouseEvent e) { + // TODO: What should be done here, if anything? } public void mousePressed(MouseEvent e) @@ -421,10 +415,13 @@ public class BasicMenuUI extends BasicMenuItemUI public void menuDeselected(MenuEvent e) { JMenu menu = (JMenu) menuItem; - if (menu.isTopLevelMenu()) - ((JMenuBar) menu.getParent()).getSelectionModel().clearSelection(); - else - ((JPopupMenu) menu.getParent()).getSelectionModel().clearSelection(); + if (menu.getParent() != null) + { + if (menu.isTopLevelMenu()) + ((JMenuBar) menu.getParent()).getSelectionModel().clearSelection(); + else + ((JPopupMenu) menu.getParent()).getSelectionModel().clearSelection(); + } } /** @@ -456,6 +453,7 @@ public class BasicMenuUI extends BasicMenuItemUI */ public void propertyChange(PropertyChangeEvent e) { + // TODO: Implement this properly. } } @@ -464,9 +462,40 @@ public class BasicMenuUI extends BasicMenuItemUI */ public class ChangeHandler implements ChangeListener { + /** + * Not used. + */ + public boolean isSelected; + + /** + * Not used. + */ + public JMenu menu; + + /** + * Not used. + */ + public BasicMenuUI ui; + + /** + * Not used. + */ + public Component wasFocused; + + /** + * Not used. + */ + public ChangeHandler(JMenu m, BasicMenuUI ui) + { + // Not used. + } + + /** + * Not used. + */ public void stateChanged(ChangeEvent e) { - // FIXME: It seems that this class is not used anywhere + // Not used. } } @@ -506,6 +535,7 @@ public class BasicMenuUI extends BasicMenuItemUI */ public void menuDragMouseExited(MenuDragMouseEvent e) { + // TODO: What should be done here, if anything? } /** @@ -516,6 +546,7 @@ public class BasicMenuUI extends BasicMenuItemUI */ public void menuDragMouseReleased(MenuDragMouseEvent e) { + // TODO: What should be done here, if anything? } } @@ -532,6 +563,7 @@ public class BasicMenuUI extends BasicMenuItemUI */ public void menuKeyPressed(MenuKeyEvent e) { + // TODO: What should be done here, if anything? } /** @@ -541,6 +573,7 @@ public class BasicMenuUI extends BasicMenuItemUI */ public void menuKeyReleased(MenuKeyEvent e) { + // TODO: What should be done here, if anything? } /** @@ -551,6 +584,7 @@ public class BasicMenuUI extends BasicMenuItemUI */ public void menuKeyTyped(MenuKeyEvent e) { + // TODO: What should be done here, if anything? } } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicOptionPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicOptionPaneUI.java index c9f623259ba..6b37d315fa8 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicOptionPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicOptionPaneUI.java @@ -70,8 +70,8 @@ import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextField; +import javax.swing.LookAndFeel; import javax.swing.SwingUtilities; -import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.plaf.ComponentUI; @@ -141,13 +141,14 @@ public class BasicOptionPaneUI extends OptionPaneUI optionPane); if (inf != null) { - try - { - inf.setClosed(true); - } - catch (PropertyVetoException pve) - { - } + try + { + inf.setClosed(true); + } + catch (PropertyVetoException pve) + { + // We do nothing if attempt has been vetoed. + } } } } @@ -405,16 +406,30 @@ public class BasicOptionPaneUI extends OptionPaneUI || e.getPropertyName().equals(JOptionPane.WANTS_INPUT_PROPERTY) || e.getPropertyName().equals(JOptionPane.SELECTION_VALUES_PROPERTY)) { - optionPane.removeAll(); - messageAreaContainer = createMessageArea(); - optionPane.add(messageAreaContainer); - optionPane.add(buttonContainer); + optionPane.remove(messageAreaContainer); + messageAreaContainer = createMessageArea(); + optionPane.add(messageAreaContainer); + Container newButtons = createButtonArea(); + optionPane.remove(buttonContainer); + optionPane.add(newButtons); + buttonContainer = newButtons; + optionPane.add(buttonContainer); } optionPane.invalidate(); optionPane.repaint(); } } + /** + * The minimum width for JOptionPanes. + */ + public static final int MinimumWidth = 262; + + /** + * The minimum height for JOptionPanes. + */ + public static final int MinimumHeight = 90; + /** Whether the JOptionPane contains custom components. */ protected boolean hasCustomComponents = false; @@ -433,12 +448,6 @@ public class BasicOptionPaneUI extends OptionPaneUI /** The component that receives input when the JOptionPane needs it. */ protected JComponent inputComponent; - /** The minimum height of the JOptionPane. */ - public static int minimumHeight; - - /** The minimum width of the JOptionPane. */ - public static int minimumWidth; - /** The minimum dimensions of the JOptionPane. */ protected Dimension minimumSize; @@ -518,6 +527,7 @@ public class BasicOptionPaneUI extends OptionPaneUI */ public void paintIcon(Component c, Graphics g, int x, int y) { + // Nothing to do here. } } @@ -637,6 +647,7 @@ public class BasicOptionPaneUI extends OptionPaneUI */ public BasicOptionPaneUI() { + // Nothing to do here. } /** @@ -860,10 +871,10 @@ public class BasicOptionPaneUI extends OptionPaneUI addIcon(messageArea); JPanel rightSide = new JPanel(); - rightSide.setBorder(BorderFactory.createEmptyBorder(0, 11, 17, 0)); + rightSide.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); rightSide.setLayout(new GridBagLayout()); GridBagConstraints con = createConstraints(); - + addMessageComponents(rightSide, con, getMessage(), getMaxCharactersPerLineCount(), false); @@ -886,7 +897,7 @@ public class BasicOptionPaneUI extends OptionPaneUI } } - messageArea.add(rightSide, BorderLayout.EAST); + messageArea.add(rightSide, BorderLayout.CENTER); return messageArea; } @@ -944,8 +955,14 @@ public class BasicOptionPaneUI extends OptionPaneUI case JOptionPane.YES_NO_CANCEL_OPTION: return new Object[] { YES_STRING, NO_STRING, CANCEL_STRING }; case JOptionPane.OK_CANCEL_OPTION: - case JOptionPane.DEFAULT_OPTION: return new Object[] { OK_STRING, CANCEL_STRING }; + case JOptionPane.DEFAULT_OPTION: + return (optionPane.getWantsInput() ) ? + new Object[] { OK_STRING, CANCEL_STRING } : + ( optionPane.getMessageType() == JOptionPane.QUESTION_MESSAGE ) ? + new Object[] { YES_STRING, NO_STRING, CANCEL_STRING } : + // ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE, PLAIN_MESSAGE + new Object[] { OK_STRING }; } return null; } @@ -1142,21 +1159,17 @@ public class BasicOptionPaneUI extends OptionPaneUI */ protected void installDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - optionPane.setFont(defaults.getFont("OptionPane.font")); - optionPane.setBackground(defaults.getColor("OptionPane.background")); - optionPane.setForeground(defaults.getColor("OptionPane.foreground")); - optionPane.setBorder(defaults.getBorder("OptionPane.border")); + LookAndFeel.installColorsAndFont(optionPane, "OptionPane.background", + "OptionPane.foreground", + "OptionPane.font"); + LookAndFeel.installBorder(optionPane, "OptionPane.border"); optionPane.setOpaque(true); - messageBorder = defaults.getBorder("OptionPane.messageAreaBorder"); - messageForeground = defaults.getColor("OptionPane.messageForeground"); - buttonBorder = defaults.getBorder("OptionPane.buttonAreaBorder"); + messageBorder = UIManager.getBorder("OptionPane.messageAreaBorder"); + messageForeground = UIManager.getColor("OptionPane.messageForeground"); + buttonBorder = UIManager.getBorder("OptionPane.buttonAreaBorder"); - minimumSize = defaults.getDimension("OptionPane.minimumSize"); - minimumWidth = minimumSize.width; - minimumHeight = minimumSize.height; + minimumSize = UIManager.getDimension("OptionPane.minimumSize"); // FIXME: Image icons don't seem to work properly right now. // Once they do, replace the synthetic icons with these ones. diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java index b715c57b360..783cec473bc 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java @@ -40,8 +40,7 @@ package javax.swing.plaf.basic; import javax.swing.JComponent; import javax.swing.JPanel; -import javax.swing.UIDefaults; -import javax.swing.UIManager; +import javax.swing.LookAndFeel; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.PanelUI; @@ -64,8 +63,29 @@ public class BasicPanelUI extends PanelUI public void installDefaults(JPanel p) { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - p.setBackground(defaults.getColor("Panel.background")); + LookAndFeel.installColorsAndFont(p, "Panel.background", "Panel.foreground", + "Panel.font"); p.setOpaque(true); } + + /** + * Uninstalls this UI from the JPanel. + * + * @param c the JPanel from which to uninstall this UI + */ + public void uninstallUI(JComponent c) + { + uninstallDefaults((JPanel) c); + } + + /** + * Uninstalls the UI defaults that have been install through + * {@link #installDefaults}. + * + * @param p the panel from which to uninstall the UI defaults + */ + protected void uninstallDefaults(JPanel p) + { + // Nothing to do here. + } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java index 044027b0b4a..76dcfc43559 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java @@ -39,6 +39,7 @@ exception statement from your version. */ package javax.swing.plaf.basic; import javax.swing.JComponent; +import javax.swing.UIDefaults; import javax.swing.plaf.ComponentUI; import javax.swing.text.Element; import javax.swing.text.PasswordView; @@ -48,6 +49,7 @@ public class BasicPasswordFieldUI extends BasicTextFieldUI { public BasicPasswordFieldUI() { + // Nothing to do here. } public View create(Element elem) @@ -60,6 +62,11 @@ public class BasicPasswordFieldUI extends BasicTextFieldUI return new BasicPasswordFieldUI(); } + /** + * Returns the prefix for entries in the {@link UIDefaults} table. + * + * @return "PasswordField" + */ protected String getPropertyPrefix() { return "PasswordField"; diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java index 247117bc983..e15a17bab28 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java @@ -53,12 +53,11 @@ import javax.swing.JLayeredPane; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; +import javax.swing.LookAndFeel; import javax.swing.MenuElement; import javax.swing.MenuSelectionManager; import javax.swing.RootPaneContainer; import javax.swing.SwingUtilities; -import javax.swing.UIDefaults; -import javax.swing.UIManager; import javax.swing.event.MouseInputListener; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; @@ -131,12 +130,9 @@ public class BasicPopupMenuUI extends PopupMenuUI */ public void installDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - popupMenu.setBackground(defaults.getColor("PopupMenu.background")); - popupMenu.setBorder(defaults.getBorder("PopupMenu.border")); - popupMenu.setFont(defaults.getFont("PopupMenu.font")); - popupMenu.setForeground(defaults.getColor("PopupMenu.foreground")); + LookAndFeel.installColorsAndFont(popupMenu, "PopupMenu.background", + "PopupMenu.foreground", "PopupMenu.font"); + LookAndFeel.installBorder(popupMenu, "PopupMenu.border"); popupMenu.setOpaque(true); } @@ -277,23 +273,26 @@ public class BasicPopupMenuUI extends PopupMenuUI RootPaneContainer rootContainer = (RootPaneContainer) SwingUtilities .getRoot(invoker); - ((Container) rootContainer).removeComponentListener(topWindowListener); - - // If this popup menu is the last popup menu visible on the screen, then - // stop interrupting mouse events in the glass pane before hiding this - // last popup menu. - boolean topLevelMenu = (popupMenu.getInvoker() instanceof JMenu) - && ((JMenu) popupMenu.getInvoker()) - .isTopLevelMenu(); - - if (topLevelMenu || ! (popupMenu.getInvoker() instanceof MenuElement)) + if (rootContainer != null) { - // set glass pane not to interrupt mouse events and remove - // mouseInputListener - Container glassPane = (Container) rootContainer.getGlassPane(); - glassPane.setVisible(false); - glassPane.removeMouseListener(mouseInputListener); - mouseInputListener = null; + ((Container) rootContainer).removeComponentListener(topWindowListener); + + // If this popup menu is the last popup menu visible on the screen, + // then + // stop interrupting mouse events in the glass pane before hiding this + // last popup menu. + boolean topLevelMenu = (popupMenu.getInvoker() instanceof JMenu) + && ((JMenu) popupMenu.getInvoker()).isTopLevelMenu(); + + if (topLevelMenu || !(popupMenu.getInvoker() instanceof MenuElement)) + { + // set glass pane not to interrupt mouse events and remove + // mouseInputListener + Container glassPane = (Container) rootContainer.getGlassPane(); + glassPane.setVisible(false); + glassPane.removeMouseListener(mouseInputListener); + mouseInputListener = null; + } } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java index d00628f53d4..88d949b1caf 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java @@ -46,21 +46,24 @@ import java.awt.Graphics; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; +import java.awt.Shape; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.font.FontRenderContext; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.JComponent; import javax.swing.JProgressBar; +import javax.swing.LookAndFeel; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.Timer; -import javax.swing.UIDefaults; import javax.swing.UIManager; +import javax.swing.event.AncestorEvent; +import javax.swing.event.AncestorListener; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.plaf.ComponentUI; @@ -110,14 +113,56 @@ public class BasicProgressBarUI extends ProgressBarUI { // Only need to listen for indeterminate changes. // All other things are done on a repaint. - if (e.getPropertyName().equals("inderterminate")) - if (((Boolean) e.getNewValue()).booleanValue()) - startAnimationTimer(); - else - stopAnimationTimer(); - else - progressBar.repaint(); + if (e.getPropertyName().equals("indeterminate")) + if (((Boolean) e.getNewValue()).booleanValue() + && progressBar.isShowing()) + startAnimationTimer(); + else + stopAnimationTimer(); + } + } + + /** + * Receives notification when the progressbar is becoming visible or + * invisible and starts/stops the animation timer accordingly. + * + * @author Roman Kennke (kennke@aicas.com) + */ + private class AncestorHandler implements AncestorListener + { + + /** + * Receives notification when the progressbar is becoming visible. This + * starts the animation timer if the progressbar is indeterminate. + * + * @param event the ancestor event + */ + public void ancestorAdded(AncestorEvent event) + { + if (progressBar.isIndeterminate()) + startAnimationTimer(); + } + + /** + * Receives notification when the progressbar is becoming invisible. This + * stops the animation timer if the progressbar is indeterminate. + * + * @param event the ancestor event + */ + public void ancestorRemoved(AncestorEvent event) + { + stopAnimationTimer(); + } + + /** + * Receives notification when an ancestor has been moved. We don't need to + * do anything here. + */ + public void ancestorMoved(AncestorEvent event) + { + // Nothing to do here. } + } /** @@ -141,6 +186,35 @@ public class BasicProgressBarUI extends ProgressBarUI } } + /** + * Receives notification when the size of the progress bar changes and + * invalidates the layout information for the box calculation in + * {@link BasicProgressBarUI#getBox(Rectangle)}. + * + * @author Roman Kennke (kennke@aicas.com) + */ + private class ComponentHandler extends ComponentAdapter + { + /** + * Receives notification when the size of the progress bar changes and + * invalidates the layout information for the box calculation in + * {@link BasicProgressBarUI#getBox}. + * + * @param e the component event + */ + public void componentResized(ComponentEvent e) + { + boxDependent = -1; + boxIndependent = -1; + incr = -1; + } + } + + /** + * Holds the value of the bouncing box that is returned by {@link #getBox}. + */ + protected Rectangle boxRect; + /** The timer used to move the bouncing box. */ private transient Timer animationTimer; @@ -172,6 +246,27 @@ public class BasicProgressBarUI extends ProgressBarUI /** The progressBar for this UI. */ protected JProgressBar progressBar; + + /** + * The size of the box returned by {@link #getBox} in the orientation + * direction of the progress bar. This is package private to avoid accessor + * method. + */ + transient double boxDependent = - 1; + + /** + * The size of the box returned by {@link #getBox} against the orientation + * direction of the progress bar. This is package private to avoid accessor + * method. + */ + transient int boxIndependent = - 1; + + /** + * The increment for box animation. This is package private to avoid accessor + * method. + */ + transient double incr = -1; + /** The length of the cell. The cell is the painted part. */ private transient int cellLength; @@ -185,6 +280,18 @@ public class BasicProgressBarUI extends ProgressBarUI private transient Color selectionForeground; /** + * Listens for notification when the component becomes showing and + * starts/stops the animation timer. + */ + private AncestorListener ancestorListener; + + /** + * Listens for resize events on the progress bar and invalidates some + * layout info. + */ + private ComponentListener componentListener; + + /** * Creates a new BasicProgressBarUI object. */ public BasicProgressBarUI() @@ -248,48 +355,49 @@ public class BasicProgressBarUI extends ProgressBarUI { if (!progressBar.isIndeterminate()) return null; - //numFrames has to be an even number as defined by spec. - int iterations = numFrames / 2 + 1; + if (r == null) + r = new Rectangle(); - double boxDependent; - double boxIndependent; + Rectangle vr = new Rectangle(); + SwingUtilities.calculateInnerArea(progressBar, vr); - if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) + // Recalculate the metrics only when size of the progressbar has changed. + if (incr == -1 || boxDependent == -1 || boxIndependent == -1) { - Dimension dims = getPreferredInnerHorizontal(); - boxDependent = (double) dims.width / iterations; - boxIndependent = dims.height; - } - else - { - Dimension dims = getPreferredInnerVertical(); - boxDependent = (double) dims.height / iterations; - boxIndependent = dims.width; + //numFrames has to be an even number as defined by spec. + int iterations = numFrames / 2; + if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) + { + boxDependent = vr.width / 6.; + incr = ((double) (vr.width - boxDependent)) / (double) iterations; + boxIndependent = vr.height; + } + else + { + boxDependent = vr.height / 6.; + incr = ((double) (vr.height - boxDependent)) / (double) iterations; + boxIndependent = vr.width; + } } - Rectangle vr = new Rectangle(); - SwingUtilities.calculateInnerArea(progressBar, vr); - int index = getAnimationIndex(); - if (animationIndex > (numFrames + 1) / 2) + if (animationIndex > (numFrames) / 2) index = numFrames - getAnimationIndex(); if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) { - r.x = vr.x + (int) (index * boxDependent); - r.y = vr.y; - r.width = (int) boxDependent; - r.height = (int) boxIndependent; + r.x = vr.x + (int) (incr * index); + r.y = vr.y; + r.width = (int) boxDependent; + r.height = (int) boxIndependent; } else { - index++; - r.x = vr.x; - r.y = vr.height - (int) (index * boxDependent) + vr.y; - r.width = (int) boxIndependent; - r.height = (int) boxDependent; + r.x = vr.x; + r.y = vr.height - (int) (incr * index) + vr.y - (int) boxDependent; + r.width = (int) boxIndependent; + r.height = (int) boxDependent; } - return r; } @@ -324,7 +432,22 @@ public class BasicProgressBarUI extends ProgressBarUI */ public Dimension getMaximumSize(JComponent c) { - return getPreferredSize(c); + Insets insets = c.getInsets(); + Dimension ret; + int orientation = progressBar.getOrientation(); + if (orientation == JProgressBar.VERTICAL) + { + ret = getPreferredInnerVertical(); + ret.height = Short.MAX_VALUE; + ret.width += insets.left + insets.right; + } + else + { + ret = getPreferredInnerHorizontal(); + ret.width = Short.MAX_VALUE; + ret.height += insets.top + insets.bottom; + } + return ret; } /** @@ -338,7 +461,22 @@ public class BasicProgressBarUI extends ProgressBarUI */ public Dimension getMinimumSize(JComponent c) { - return getPreferredSize(c); + Insets insets = c.getInsets(); + Dimension ret; + int orientation = progressBar.getOrientation(); + if (orientation == JProgressBar.VERTICAL) + { + ret = getPreferredInnerVertical(); + ret.height = 10; + ret.width += insets.left + insets.right; + } + else + { + ret = getPreferredInnerHorizontal(); + ret.width = 10; + ret.height += insets.top + insets.bottom; + } + return ret; } /** @@ -351,11 +489,22 @@ public class BasicProgressBarUI extends ProgressBarUI */ protected Dimension getPreferredInnerHorizontal() { - Rectangle vr = new Rectangle(); + Font font = progressBar.getFont(); + FontMetrics fm = progressBar.getFontMetrics(font); - SwingUtilities.calculateInnerArea(progressBar, vr); + int stringWidth = 0; + String str = progressBar.getString(); + if (str != null) + stringWidth = fm.stringWidth(progressBar.getString()); + Insets i = progressBar.getInsets(); + int prefWidth = Math.max(200 - i.left - i.right, stringWidth); - return new Dimension(vr.width, vr.height); + int stringHeight = 0; + if (str != null) + stringHeight = fm.getHeight(); + int prefHeight = Math.max(16 - i.top - i.bottom, stringHeight); + + return new Dimension(prefWidth, prefHeight); } /** @@ -368,11 +517,22 @@ public class BasicProgressBarUI extends ProgressBarUI */ protected Dimension getPreferredInnerVertical() { - Rectangle vr = new Rectangle(); + Font font = progressBar.getFont(); + FontMetrics fm = progressBar.getFontMetrics(font); - SwingUtilities.calculateInnerArea(progressBar, vr); + int stringWidth = 0; + String str = progressBar.getString(); + if (str != null) + stringWidth = fm.stringWidth(progressBar.getString()); + Insets i = progressBar.getInsets(); + int prefHeight = Math.max(200 - i.left - i.right, stringWidth); + + int stringHeight = 0; + if (str != null) + stringHeight = fm.getHeight(); + int prefWidth = Math.max(16 - i.top - i.bottom, stringHeight); - return new Dimension(vr.width, vr.height); + return new Dimension(prefWidth, prefHeight); } /** @@ -386,36 +546,16 @@ public class BasicProgressBarUI extends ProgressBarUI */ public Dimension getPreferredSize(JComponent c) { - // The only thing we need to worry about is - // the text size. Insets insets = c.getInsets(); - - // make a fontrenderer context so that we can make assumptions about - // the string bounds - FontRenderContext ctx = new FontRenderContext(new AffineTransform(), - false, false); - Rectangle2D bounds = c.getFont().getStringBounds(progressBar.getString(), - ctx); - int textW = (int) bounds.getWidth(); - int textH = (int) bounds.getHeight(); - - if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) - { - if (textH < 20) - textH = 20; - if (textW < 200) - textW = 200; - } + Dimension ret; + int orientation = progressBar.getOrientation(); + if (orientation == JProgressBar.VERTICAL) + ret = getPreferredInnerVertical(); else - { - if (textH < 200) - textH = 200; - if (textW < 20) - textW = 20; - } - textW += insets.left + insets.right; - textH += insets.top + insets.bottom; - return new Dimension(textW, textH); + ret = getPreferredInnerHorizontal(); + ret.width += insets.left + insets.right; + ret.height += insets.top + insets.bottom; + return ret; } /** @@ -514,66 +654,22 @@ public class BasicProgressBarUI extends ProgressBarUI int min = progressBar.getMinimum(); int value = progressBar.getValue(); - Rectangle vr = new Rectangle(); - SwingUtilities.calculateInnerArea(c, vr); - - Rectangle or = c.getBounds(); - + Rectangle vr = SwingUtilities.calculateInnerArea(c, new Rectangle()); + Rectangle or = progressBar.getBounds(); Insets insets = c.getInsets(); int amountFull = getAmountFull(insets, or.width, or.height); - g.setColor(c.getBackground()); - g.fill3DRect(vr.x, vr.y, vr.width, vr.height, false); - - if (max != min && len != 0 && value > min) - { - int iterations = value / (space + len); - if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) { - double spaceInUnits = space * (double) vr.width / (max - min); - double lenInUnits = len * (double) vr.width / (max - min); - double currX = vr.x; - g.setColor(c.getForeground()); - g.fill3DRect(vr.x, vr.y, amountFull, vr.height, true); - - g.setColor(c.getBackground()); - if (spaceInUnits != 0) - { - for (int i = 0; i < iterations; i++) - { - currX += lenInUnits; - g.fill3DRect((int) currX, vr.y, (int) spaceInUnits, - vr.height, true); - currX += spaceInUnits; - } - } + g.fillRect(vr.x, vr.y, amountFull, vr.height); } else { - double currY = vr.y; - double spaceInUnits = space * (double) vr.height / (max - min); - double lenInUnits = len * (double) vr.height / (max - min); - g.setColor(c.getForeground()); - g.fill3DRect(vr.x, vr.y + vr.height - amountFull, vr.width, - amountFull, true); - - g.setColor(c.getBackground()); - - if (spaceInUnits != 0) - { - for (int i = 0; i < iterations; i++) - { - currY -= lenInUnits + spaceInUnits; - g.fill3DRect(vr.x, (int) currY, vr.width, - (int) spaceInUnits, true); - } - } + g.fillRect(vr.x, vr.y + vr.height - amountFull, vr.width, amountFull); } - } if (progressBar.isStringPainted() && !progressBar.getString().equals("")) paintString(g, 0, 0, or.width, or.height, amountFull, insets); @@ -599,13 +695,12 @@ public class BasicProgressBarUI extends ProgressBarUI SwingUtilities.calculateInnerArea(c, vr); g.setColor(c.getBackground()); - g.fill3DRect(vr.x, vr.y, vr.width, vr.height, false); + g.fillRect(vr.x, vr.y, vr.width, vr.height); - Rectangle box = new Rectangle(); - getBox(box); + boxRect = getBox(boxRect); g.setColor(c.getForeground()); - g.fill3DRect(box.x, box.y, box.width, box.height, true); + g.fillRect(boxRect.x, boxRect.y, boxRect.width, boxRect.height); if (progressBar.isStringPainted() && !progressBar.getString().equals("")) paintString(g, 0, 0, or.width, or.height, @@ -628,23 +723,34 @@ public class BasicProgressBarUI extends ProgressBarUI protected void paintString(Graphics g, int x, int y, int width, int height, int amountFull, Insets b) { + // FIXME: We do not support vertical text painting because Java2D is needed + // for this. + if (progressBar.getOrientation() == JProgressBar.VERTICAL) + return; + // We want to place in the exact center of the bar. Point placement = getStringPlacement(g, progressBar.getString(), x + b.left, y + b.top, width - b.left - b.right, height - b.top - b.bottom); - Color saved = g.getColor(); - - // FIXME: The Color of the text should use selectionForeground and selectionBackground - // but that can't be done right now, so we'll use white in the mean time. - g.setColor(Color.WHITE); + Color savedColor = g.getColor(); + Shape savedClip = g.getClip(); FontMetrics fm = g.getFontMetrics(progressBar.getFont()); + int full = getAmountFull(b, width, height); + String str = progressBar.getString(); - g.drawString(progressBar.getString(), placement.x, - placement.y + fm.getAscent()); - - g.setColor(saved); + // We draw this string two times with different clips so that the text + // over the filled area is painted with selectionForeground and over + // the clear area with selectionBackground. + g.setColor(getSelectionForeground()); + g.setClip(0, 0, full + b.left, height); + g.drawString(str, placement.x, placement.y + fm.getAscent()); + g.setColor(getSelectionBackground()); + g.setClip(full + b.left, 0, width - full, height); + g.drawString(str, placement.x, placement.y + fm.getAscent()); + g.setClip(savedClip); + g.setColor(savedColor); } /** @@ -712,21 +818,19 @@ public class BasicProgressBarUI extends ProgressBarUI */ protected void installDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - progressBar.setFont(defaults.getFont("ProgressBar.font")); - progressBar.setForeground(defaults.getColor("ProgressBar.foreground")); - progressBar.setBackground(defaults.getColor("ProgressBar.background")); - progressBar.setBorder(defaults.getBorder("ProgressBar.border")); + LookAndFeel.installColorsAndFont(progressBar, "ProgressBar.background", + "ProgressBar.foreground", + "ProgressBar.font"); + LookAndFeel.installBorder(progressBar, "ProgressBar.border"); progressBar.setOpaque(true); - selectionForeground = defaults.getColor("ProgressBar.selectionForeground"); - selectionBackground = defaults.getColor("ProgressBar.selectionBackground"); - cellLength = defaults.getInt("ProgressBar.cellLength"); - cellSpacing = defaults.getInt("ProgressBar.cellSpacing"); + selectionForeground = UIManager.getColor("ProgressBar.selectionForeground"); + selectionBackground = UIManager.getColor("ProgressBar.selectionBackground"); + cellLength = UIManager.getInt("ProgressBar.cellLength"); + cellSpacing = UIManager.getInt("ProgressBar.cellSpacing"); - int repaintInterval = defaults.getInt("ProgressBar.repaintInterval"); - int cycleTime = defaults.getInt("ProgressBar.cycleTime"); + int repaintInterval = UIManager.getInt("ProgressBar.repaintInterval"); + int cycleTime = UIManager.getInt("ProgressBar.cycleTime"); if (cycleTime % repaintInterval != 0 && (cycleTime / repaintInterval) % 2 != 0) @@ -768,6 +872,12 @@ public class BasicProgressBarUI extends ProgressBarUI progressBar.addChangeListener(changeListener); progressBar.addPropertyChangeListener(propertyListener); animationTimer.addActionListener(animation); + + ancestorListener = new AncestorHandler(); + progressBar.addAncestorListener(ancestorListener); + + componentListener = new ComponentHandler(); + progressBar.addComponentListener(componentListener); } /** @@ -783,6 +893,14 @@ public class BasicProgressBarUI extends ProgressBarUI changeListener = null; propertyListener = null; animation = null; + + if (ancestorListener != null) + progressBar.removeAncestorListener(ancestorListener); + ancestorListener = null; + + if (componentListener != null) + progressBar.removeComponentListener(componentListener); + componentListener = null; } /** @@ -806,6 +924,8 @@ public class BasicProgressBarUI extends ProgressBarUI installDefaults(); installListeners(); } + if (progressBar.isIndeterminate()) + startAnimationTimer(); } /** @@ -824,4 +944,5 @@ public class BasicProgressBarUI extends ProgressBarUI animationTimer = null; progressBar = null; } + } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java index fa74a008bae..8af5ff7f95c 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java @@ -59,8 +59,6 @@ public class BasicRadioButtonMenuItemUI extends BasicMenuItemUI public BasicRadioButtonMenuItemUI() { super(); - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - checkIcon = defaults.getIcon("RadioButtonMenuItem.checkIcon"); } /** @@ -98,5 +96,7 @@ public class BasicRadioButtonMenuItemUI extends BasicMenuItemUI MenuElement[] path, MenuSelectionManager manager) { + // TODO: May not be implemented properly. + item.processMouseEvent(e, path, manager); } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java index fbd21241a0d..f3698e85908 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java @@ -38,6 +38,8 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import java.awt.Color; +import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Rectangle; @@ -93,6 +95,10 @@ public class BasicRadioButtonUI extends BasicToggleButtonUI b.setIcon(icon); if (b.getSelectedIcon() == null) b.setSelectedIcon(icon); + if (b.getDisabledIcon() == null) + b.setDisabledIcon(icon); + if (b.getDisabledSelectedIcon() == null) + b.setDisabledSelectedIcon(icon); } /** @@ -139,10 +145,14 @@ public class BasicRadioButtonUI extends BasicToggleButtonUI g.setFont(f); Icon currentIcon = null; - if (b.isSelected()) + if (b.isSelected() && b.isEnabled()) currentIcon = b.getSelectedIcon(); - else + else if (!b.isSelected() && b.isEnabled()) currentIcon = b.getIcon(); + else if (b.isSelected() && !b.isEnabled()) + currentIcon = b.getDisabledSelectedIcon(); + else // (!b.isSelected() && !b.isEnabled()) + currentIcon = b.getDisabledIcon(); SwingUtilities.calculateInnerArea(b, vr); String text = SwingUtilities.layoutCompoundLabel @@ -157,6 +167,25 @@ public class BasicRadioButtonUI extends BasicToggleButtonUI } if (text != null) paintText(g, b, tr, text); - paintFocus(g, b, vr, tr, ir); + // TODO: Figure out what is the size parameter? + if (b.hasFocus() && b.isFocusPainted() && b.isEnabled()) + paintFocus(g, tr, null); + } + + /** + * Paints the focus indicator for JRadioButtons. + * + * @param g the graphics context + * @param tr the rectangle for the text label + * @param size the size (??) + */ + // TODO: Figure out what for is the size parameter. + protected void paintFocus(Graphics g, Rectangle tr, Dimension size) + { + Color focusColor = UIManager.getColor(getPropertyPrefix() + ".focus"); + Color saved = g.getColor(); + g.setColor(focusColor); + g.drawRect(tr.x, tr.y, tr.width, tr.height); + g.setColor(saved); } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java index d97f7baea67..2a698e8a162 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java @@ -42,6 +42,7 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.JComponent; +import javax.swing.JRootPane; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.RootPaneUI; @@ -56,11 +57,127 @@ public class BasicRootPaneUI extends RootPaneUI public void installUI(JComponent c) { - c.setBackground(UIManager.getColor("control")); super.installUI(c); + if (c instanceof JRootPane) + { + JRootPane rp = (JRootPane) c; + installDefaults(rp); + installComponents(rp); + installListeners(rp); + installKeyboardActions(rp); + } + } + + /** + * Installs the look and feel defaults for JRootPane. + * + * @param rp the root pane to install the defaults to + */ + protected void installDefaults(JRootPane rp) + { + // Is this ok? + rp.setBackground(UIManager.getColor("control")); + } + + /** + * Installs additional look and feel components to the root pane. + * + * @param rp the root pane to install the components to + */ + protected void installComponents(JRootPane rp) + { + // All components are initialized in the JRootPane constructor, and since + // the createXXXPane methods are protected, I see no reasonable way, + // and no need to initialize them here. This method is here anyway + // for compatibility and to provide the necessary hooks to subclasses. + } + + /** + * Installs any look and feel specific listeners on the root pane. + * + * @param rp the root pane to install the listeners to + */ + protected void installListeners(JRootPane rp) + { + rp.addPropertyChangeListener(this); + } + + /** + * Installs look and feel keyboard actions on the root pane. + * + * @param rp the root pane to install the keyboard actions to + */ + protected void installKeyboardActions(JRootPane rp) + { + // We currently do not install any keyboard actions here. + // This method is here anyway for compatibility and to provide + // the necessary hooks to subclasses. } public void propertyChange(PropertyChangeEvent event) { + // TODO: Implement this properly. + } + + /** + * Uninstalls this UI from the root pane. This calls + * {@link #uninstallDefaults}, {@link #uninstallComponents}, + * {@link #uninstallListeners}, {@link #uninstallKeyboardActions} + * in this order. + * + * @param c the root pane to uninstall the UI from + */ + public void uninstallUI(JComponent c) + { + super.uninstallUI(c); + if (c instanceof JRootPane) + { + JRootPane rp = (JRootPane) c; + uninstallDefaults(rp); + uninstallComponents(rp); + uninstallListeners(rp); + uninstallKeyboardActions(rp); + } + } + + /** + * Uninstalls the look and feel defaults that have been installed in + * {@link #installDefaults}. + * + * @param rp the root pane to uninstall the defaults from + */ + protected void uninstallDefaults(JRootPane rp) + { + // We do nothing here. + } + + /** + * Uninstalls look and feel components from the root pane. + * + * @param rp the root pane to uninstall the components from + */ + protected void uninstallComponents(JRootPane rp) + { + // We do nothing here. + } + + /** + * Uninstalls any look and feel specific listeners from the root pane. + * + * @param rp the root pane to uninstall the listeners from + */ + protected void uninstallListeners(JRootPane rp) + { + rp.removePropertyChangeListener(this); + } + + /** + * Uninstalls look and feel keyboard actions from the root pane. + * + * @param rp the root pane to uninstall the keyboard actions from + */ + protected void uninstallKeyboardActions(JRootPane rp) + { + // We do nothing here. } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java index 22242afcd8a..2f5eaf391e1 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java @@ -58,6 +58,7 @@ import javax.swing.BoundedRangeModel; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JScrollBar; +import javax.swing.LookAndFeel; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.Timer; @@ -80,6 +81,7 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ protected class ArrowButtonListener extends MouseAdapter { + /** * Move the thumb in the direction specified by the button's arrow. If * this button is held down, then it should keep moving the thumb. @@ -91,9 +93,10 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, scrollTimer.stop(); scrollListener.setScrollByBlock(false); if (e.getSource() == incrButton) - scrollListener.setDirection(POSITIVE_SCROLL); - else - scrollListener.setDirection(NEGATIVE_SCROLL); + scrollListener.setDirection(POSITIVE_SCROLL); + else if (e.getSource() == decrButton) + scrollListener.setDirection(NEGATIVE_SCROLL); + scrollTimer.setDelay(100); scrollTimer.start(); } @@ -105,6 +108,11 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, public void mouseReleased(MouseEvent e) { scrollTimer.stop(); + scrollTimer.setDelay(300); + if (e.getSource() == incrButton) + scrollByUnit(POSITIVE_SCROLL); + else if (e.getSource() == decrButton) + scrollByUnit(NEGATIVE_SCROLL); } } @@ -120,9 +128,8 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ public void stateChanged(ChangeEvent e) { - // System.err.println(this + ".stateChanged()"); calculatePreferredSize(); - getThumbBounds(); + updateThumbRect(); scrollbar.repaint(); } } @@ -141,31 +148,27 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, { if (e.getPropertyName().equals("model")) { - ((BoundedRangeModel) e.getOldValue()).removeChangeListener(modelListener); - scrollbar.getModel().addChangeListener(modelListener); - getThumbBounds(); + ((BoundedRangeModel) e.getOldValue()).removeChangeListener(modelListener); + scrollbar.getModel().addChangeListener(modelListener); + updateThumbRect(); } else if (e.getPropertyName().equals("orientation")) { - incrButton.removeMouseListener(buttonListener); - decrButton.removeMouseListener(buttonListener); - int orientation = scrollbar.getOrientation(); - switch (orientation) - { - case (JScrollBar.HORIZONTAL): - incrButton = createIncreaseButton(EAST); - decrButton = createDecreaseButton(WEST); - break; - default: - incrButton = createIncreaseButton(SOUTH); - decrButton = createDecreaseButton(NORTH); - break; - } - incrButton.addMouseListener(buttonListener); - decrButton.addMouseListener(buttonListener); - calculatePreferredSize(); + uninstallListeners(); + uninstallComponents(); + uninstallDefaults(); + installDefaults(); + installComponents(); + installListeners(); + } + else if (e.getPropertyName().equals("enabled")) + { + Boolean b = (Boolean) e.getNewValue(); + if (incrButton != null) + incrButton.setEnabled(b.booleanValue()); + if (decrButton != null) + decrButton.setEnabled(b.booleanValue()); } - scrollbar.repaint(); } } @@ -233,19 +236,19 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, { if (block) { - // Only need to check it if it's block scrolling - // We only block scroll if the click occurs - // in the track. - if (! trackListener.shouldScroll(direction)) - { - trackHighlight = NO_HIGHLIGHT; - scrollbar.repaint(); - return; - } - scrollByBlock(direction); + // Only need to check it if it's block scrolling + // We only block scroll if the click occurs + // in the track. + if (!trackListener.shouldScroll(direction)) + { + trackHighlight = NO_HIGHLIGHT; + scrollbar.repaint(); + return; + } + scrollByBlock(direction); } else - scrollByUnit(direction); + scrollByUnit(direction); } } @@ -316,9 +319,6 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, else value = valueForYPosition(currentMouseY); - if (value == scrollbar.getValue()) - return; - if (! thumbRect.contains(e.getPoint())) { scrollTimer.stop(); @@ -333,6 +333,7 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, trackHighlight = DECREASE_HIGHLIGHT; scrollListener.setDirection(NEGATIVE_SCROLL); } + scrollTimer.setDelay(100); scrollTimer.start(); } else @@ -343,8 +344,10 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, // "lower" edge of the thumb. The value at which // the cursor is at must be greater or equal // to that value. + + scrollListener.setScrollByBlock(false); scrollbar.setValueIsAdjusting(true); - offset = value - scrollbar.getValue(); + offset = value - scrollbar.getValue(); } scrollbar.repaint(); } @@ -357,11 +360,19 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ public void mouseReleased(MouseEvent e) { - trackHighlight = NO_HIGHLIGHT; scrollTimer.stop(); + scrollTimer.setDelay(300); + currentMouseX = e.getX(); + currentMouseY = e.getY(); - if (scrollbar.getValueIsAdjusting()) - scrollbar.setValueIsAdjusting(false); + if (shouldScroll(POSITIVE_SCROLL)) + scrollByBlock(POSITIVE_SCROLL); + else if (shouldScroll(NEGATIVE_SCROLL)) + scrollByBlock(NEGATIVE_SCROLL); + + trackHighlight = NO_HIGHLIGHT; + scrollListener.setScrollByBlock(false); + scrollbar.setValueIsAdjusting(true); scrollbar.repaint(); } @@ -381,6 +392,9 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, else value = valueForYPosition(currentMouseY); + if (thumbRect.contains(currentMouseX, currentMouseY)) + return false; + if (direction == POSITIVE_SCROLL) return (value > scrollbar.getValue()); else @@ -517,11 +531,7 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ protected JButton createIncreaseButton(int orientation) { - if (incrButton == null) - incrButton = new BasicArrowButton(orientation); - else - ((BasicArrowButton) incrButton).setDirection(orientation); - return incrButton; + return new BasicArrowButton(orientation); } /** @@ -534,11 +544,7 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ protected JButton createDecreaseButton(int orientation) { - if (decrButton == null) - decrButton = new BasicArrowButton(orientation); - else - ((BasicArrowButton) decrButton).setDirection(orientation); - return decrButton; + return new BasicArrowButton(orientation); } /** @@ -602,7 +608,7 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ public Dimension getMaximumSize(JComponent c) { - return getPreferredSize(c); + return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); } /** @@ -644,7 +650,6 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ void calculatePreferredSize() { - // System.err.println(this + ".calculatePreferredSize()"); int height; int width; height = width = 0; @@ -707,48 +712,6 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ protected Rectangle getThumbBounds() { - int max = scrollbar.getMaximum(); - int min = scrollbar.getMinimum(); - int value = scrollbar.getValue(); - int extent = scrollbar.getVisibleAmount(); - - // System.err.println(this + ".getThumbBounds()"); - if (max == min) - { - thumbRect.x = trackRect.x; - thumbRect.y = trackRect.y; - if (scrollbar.getOrientation() == HORIZONTAL) - { - thumbRect.width = getMinimumThumbSize().width; - thumbRect.height = trackRect.height; - } - else - { - thumbRect.width = trackRect.width; - thumbRect.height = getMinimumThumbSize().height; - } - return thumbRect; - } - - if (scrollbar.getOrientation() == HORIZONTAL) - { - thumbRect.x = trackRect.x; - thumbRect.x += (value - min) * trackRect.width / (max - min); - thumbRect.y = trackRect.y; - - thumbRect.width = Math.max(extent * trackRect.width / (max - min), - getMinimumThumbSize().width); - thumbRect.height = trackRect.height; - } - else - { - thumbRect.x = trackRect.x; - thumbRect.y = trackRect.y + value * trackRect.height / (max - min); - - thumbRect.width = trackRect.width; - thumbRect.height = Math.max(extent * trackRect.height / (max - min), - getMinimumThumbSize().height); - } return thumbRect; } @@ -760,22 +723,6 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ protected Rectangle getTrackBounds() { - SwingUtilities.calculateInnerArea(scrollbar, trackRect); - - if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL) - { - trackRect.width -= incrButton.getPreferredSize().getWidth(); - trackRect.width -= decrButton.getPreferredSize().getWidth(); - - trackRect.x += decrButton.getPreferredSize().getWidth(); - } - else - { - trackRect.height -= incrButton.getPreferredSize().getHeight(); - trackRect.height -= decrButton.getPreferredSize().getHeight(); - - trackRect.y += incrButton.getPreferredSize().getHeight(); - } return trackRect; } @@ -785,6 +732,18 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ protected void installComponents() { + if (incrButton != null) + scrollbar.add(incrButton); + if (decrButton != null) + scrollbar.add(decrButton); + } + + /** + * This method installs the defaults for the scrollbar specified by the + * Basic Look and Feel. + */ + protected void installDefaults() + { int orientation = scrollbar.getOrientation(); switch (orientation) { @@ -797,31 +756,20 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, decrButton = createDecreaseButton(NORTH); break; } - scrollbar.add(incrButton); - scrollbar.add(decrButton); - } - - /** - * This method installs the defaults for the scrollbar specified by the - * Basic Look and Feel. - */ - protected void installDefaults() - { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - scrollbar.setForeground(defaults.getColor("ScrollBar.foreground")); - scrollbar.setBackground(defaults.getColor("ScrollBar.background")); - scrollbar.setBorder(defaults.getBorder("ScrollBar.border")); + LookAndFeel.installColors(scrollbar, "ScrollBar.background", + "ScrollBar.foreground"); + LookAndFeel.installBorder(scrollbar, "ScrollBar.border"); scrollbar.setOpaque(true); scrollbar.setLayout(this); - thumbColor = defaults.getColor("ScrollBar.thumb"); - thumbDarkShadowColor = defaults.getColor("ScrollBar.thumbDarkShadow"); - thumbHighlightColor = defaults.getColor("ScrollBar.thumbHighlight"); - thumbLightShadowColor = defaults.getColor("ScrollBar.thumbShadow"); + thumbColor = UIManager.getColor("ScrollBar.thumb"); + thumbDarkShadowColor = UIManager.getColor("ScrollBar.thumbDarkShadow"); + thumbHighlightColor = UIManager.getColor("ScrollBar.thumbHighlight"); + thumbLightShadowColor = UIManager.getColor("ScrollBar.thumbShadow"); - maximumThumbSize = defaults.getDimension("ScrollBar.maximumThumbSize"); - minimumThumbSize = defaults.getDimension("ScrollBar.minimumThumbSize"); + maximumThumbSize = UIManager.getDimension("ScrollBar.maximumThumbSize"); + minimumThumbSize = UIManager.getDimension("ScrollBar.minimumThumbSize"); } /** @@ -873,11 +821,10 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, trackRect = new Rectangle(); thumbRect = new Rectangle(); - scrollTimer = new Timer(200, null); - scrollTimer.setRepeats(true); + scrollTimer = new Timer(300, null); + installDefaults(); installComponents(); - installDefaults(); configureScrollBarColors(); installListeners(); @@ -908,17 +855,20 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ protected void layoutHScrollbar(JScrollBar sb) { - // All we have to do is layout the 2 buttons? Rectangle vr = new Rectangle(); SwingUtilities.calculateInnerArea(scrollbar, vr); - // Update the rectangles. - getTrackBounds(); - getThumbBounds(); - Dimension incrDims = incrButton.getPreferredSize(); Dimension decrDims = decrButton.getPreferredSize(); + + // calculate and update the track bounds + SwingUtilities.calculateInnerArea(scrollbar, trackRect); + trackRect.width -= incrDims.getWidth(); + trackRect.width -= decrDims.getWidth(); + trackRect.x += decrDims.getWidth(); + updateThumbRect(); + decrButton.setBounds(vr.x, vr.y, decrDims.width, trackRect.height); incrButton.setBounds(trackRect.x + trackRect.width, vr.y, incrDims.width, trackRect.height); @@ -934,12 +884,16 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, Rectangle vr = new Rectangle(); SwingUtilities.calculateInnerArea(scrollbar, vr); - // Update rectangles - getTrackBounds(); - getThumbBounds(); - Dimension incrDims = incrButton.getPreferredSize(); Dimension decrDims = decrButton.getPreferredSize(); + + // Update rectangles + SwingUtilities.calculateInnerArea(scrollbar, trackRect); + trackRect.height -= incrDims.getHeight(); + trackRect.height -= decrDims.getHeight(); + trackRect.y += decrDims.getHeight(); + + updateThumbRect(); decrButton.setBounds(vr.x, vr.y, trackRect.width, decrDims.height); incrButton.setBounds(vr.x, trackRect.y + trackRect.height, @@ -947,6 +901,58 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, } /** + * Updates the thumb rect. + */ + void updateThumbRect() + { + int max = scrollbar.getMaximum(); + int min = scrollbar.getMinimum(); + int value = scrollbar.getValue(); + int extent = scrollbar.getVisibleAmount(); + if (max - extent <= min) + { + if (scrollbar.getOrientation() == JScrollBar.HORIZONTAL) + { + thumbRect.x = trackRect.x; + thumbRect.y = trackRect.y; + thumbRect.width = getMinimumThumbSize().width; + thumbRect.height = trackRect.height; + } + else + { + thumbRect.x = trackRect.x; + thumbRect.y = trackRect.y; + thumbRect.width = trackRect.width; + thumbRect.height = getMinimumThumbSize().height; + } + } + else + { + if (scrollbar.getOrientation() == JScrollBar.HORIZONTAL) + { + thumbRect.x = trackRect.x; + thumbRect.width = Math.max(extent * trackRect.width / (max - min), + getMinimumThumbSize().width); + int availableWidth = trackRect.width - thumbRect.width; + thumbRect.x += (value - min) * availableWidth / (max - min - extent); + thumbRect.y = trackRect.y; + thumbRect.height = trackRect.height; + } + else + { + thumbRect.x = trackRect.x; + thumbRect.height = Math.max(extent * trackRect.height / (max - min), + getMinimumThumbSize().height); + int availableHeight = trackRect.height - thumbRect.height; + thumbRect.y = trackRect.y + + (value - min) * availableHeight / (max - min - extent); + thumbRect.width = trackRect.width; + } + } + + } + + /** * This method returns the minimum size required for the layout. * * @param scrollbarContainer The Container that is laid out. @@ -1124,10 +1130,10 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ protected void uninstallComponents() { - scrollbar.remove(incrButton); - scrollbar.remove(decrButton); - incrButton = null; - decrButton = null; + if (incrButton != null) + scrollbar.remove(incrButton); + if (decrButton != null) + scrollbar.remove(decrButton); } /** @@ -1138,7 +1144,9 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, { scrollbar.setForeground(null); scrollbar.setBackground(null); - scrollbar.setBorder(null); + LookAndFeel.uninstallBorder(scrollbar); + incrButton = null; + decrButton = null; } /** @@ -1155,17 +1163,22 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ protected void uninstallListeners() { - scrollTimer.removeActionListener(scrollListener); + if (scrollTimer != null) + scrollTimer.removeActionListener(scrollListener); - scrollbar.getModel().removeChangeListener(modelListener); - scrollbar.removePropertyChangeListener(propertyChangeListener); - - decrButton.removeMouseListener(buttonListener); - incrButton.removeMouseListener(buttonListener); - - scrollbar.removeMouseListener(trackListener); - scrollbar.removeMouseMotionListener(trackListener); + if (scrollbar != null) + { + scrollbar.getModel().removeChangeListener(modelListener); + scrollbar.removePropertyChangeListener(propertyChangeListener); + scrollbar.removeMouseListener(trackListener); + scrollbar.removeMouseMotionListener(trackListener); + } + if (decrButton != null) + decrButton.removeMouseListener(buttonListener); + if (incrButton != null) + incrButton.removeMouseListener(buttonListener); + propertyChangeListener = null; modelListener = null; buttonListener = null; @@ -1182,8 +1195,8 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ public void uninstallUI(JComponent c) { - uninstallDefaults(); uninstallListeners(); + uninstallDefaults(); uninstallComponents(); scrollTimer = null; diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java index bd1576f37a5..808ed2763e9 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java @@ -40,13 +40,21 @@ package javax.swing.plaf.basic; import java.awt.Dimension; import java.awt.Graphics; +import java.awt.Point; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import javax.swing.JComponent; +import javax.swing.JScrollBar; import javax.swing.JScrollPane; +import javax.swing.JViewport; +import javax.swing.LookAndFeel; import javax.swing.ScrollPaneConstants; import javax.swing.ScrollPaneLayout; -import javax.swing.UIDefaults; -import javax.swing.UIManager; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ScrollPaneUI; @@ -54,9 +62,207 @@ public class BasicScrollPaneUI extends ScrollPaneUI implements ScrollPaneConstants { + /** + * Listens for changes in the state of the horizontal scrollbar's model and + * updates the scrollpane accordingly. + * + * @author Roman Kennke (kennke@aicas.com) + */ + public class HSBChangeListener implements ChangeListener + { + + /** + * Receives notification when the state of the horizontal scrollbar + * model has changed. + * + * @param event the change event + */ + public void stateChanged(ChangeEvent event) + { + JScrollBar hsb = scrollpane.getHorizontalScrollBar(); + JViewport vp = scrollpane.getViewport(); + Point viewPosition = vp.getViewPosition(); + int xpos = hsb.getValue(); + + if (xpos != viewPosition.x) + { + viewPosition.x = xpos; + vp.setViewPosition(viewPosition); + } + + viewPosition.y = 0; + JViewport columnHeader = scrollpane.getColumnHeader(); + if (columnHeader != null + && !columnHeader.getViewPosition().equals(viewPosition)) + columnHeader.setViewPosition(viewPosition); + } + + } + + /** + * Listens for changes in the state of the vertical scrollbar's model and + * updates the scrollpane accordingly. + * + * @author Roman Kennke (kennke@aicas.com) + */ + public class VSBChangeListener implements ChangeListener + { + + /** + * Receives notification when the state of the vertical scrollbar + * model has changed. + * + * @param event the change event + */ + public void stateChanged(ChangeEvent event) + { + JScrollBar vsb = scrollpane.getVerticalScrollBar(); + JViewport vp = scrollpane.getViewport(); + Point viewPosition = vp.getViewPosition(); + int ypos = vsb.getValue(); + if (ypos != viewPosition.y) + { + viewPosition.y = ypos; + vp.setViewPosition(viewPosition); + } + + viewPosition.x = 0; + JViewport rowHeader = scrollpane.getRowHeader(); + if (rowHeader != null + && !rowHeader.getViewPosition().equals(viewPosition)) + rowHeader.setViewPosition(viewPosition); + } + + } + + /** + * Listens for changes of the viewport's extent size and updates the + * scrollpane accordingly. + * + * @author Roman Kennke (kennke@aicas.com) + */ + public class ViewportChangeHandler implements ChangeListener + { + + /** + * Receives notification when the view's size, position or extent size + * changes. When the extents size has changed, this method calls + * {@link BasicScrollPaneUI#syncScrollPaneWithViewport()} to adjust the + * scrollbars extents as well. + * + * @param event the change event + */ + public void stateChanged(ChangeEvent event) + { + JViewport vp = scrollpane.getViewport(); + JScrollBar hsb = scrollpane.getHorizontalScrollBar(); + JScrollBar vsb = scrollpane.getVerticalScrollBar(); + syncScrollPaneWithViewport(); + } + + } + + /** + * Listens for property changes on the scrollpane and update the view + * accordingly. + * + * @author Roman Kennke (kennke@aicas.com) + */ + public class PropertyChangeHandler implements PropertyChangeListener + { + + /** + * Receives notification when any of the scrollpane's bound property + * changes. This method calls the appropriate update method on the + * <code>ScrollBarUI</code>. + * + * @param e the property change event + * + * @see BasicScrollPaneUI#updateColumnHeader(PropertyChangeEvent) + * @see BasicScrollPaneUI#updateRowHeader(PropertyChangeEvent) + * @see BasicScrollPaneUI#updateScrollBarDisplayPolicy(PropertyChangeEvent) + * @see BasicScrollPaneUI#updateViewport(PropertyChangeEvent) + */ + public void propertyChange(PropertyChangeEvent e) + { + String propName = e.getPropertyName(); + if (propName.equals("viewport")) + updateViewport(e); + else if (propName.equals("rowHeader")) + updateRowHeader(e); + else if (propName.equals("columnHeader")) + updateColumnHeader(e); + else if (propName.equals("horizontalScrollBarPolicy") + || e.getPropertyName().equals("verticalScrollBarPolicy")) + updateScrollBarDisplayPolicy(e); + else if (propName.equals("verticalScrollBar")) + { + JScrollBar oldSb = (JScrollBar) e.getOldValue(); + oldSb.getModel().removeChangeListener(vsbChangeListener); + JScrollBar newSb = (JScrollBar) e.getNewValue(); + newSb.getModel().addChangeListener(vsbChangeListener); + } + else if (propName.equals("horizontalScrollBar")) + { + JScrollBar oldSb = (JScrollBar) e.getOldValue(); + oldSb.getModel().removeChangeListener(hsbChangeListener); + JScrollBar newSb = (JScrollBar) e.getNewValue(); + newSb.getModel().addChangeListener(hsbChangeListener); + } + } + + } + + /** + * Listens for mouse wheel events and update the scrollpane accordingly. + * + * @author Roman Kennke (kennke@aicas.com) + * + * @since 1.4 + */ + protected class MouseWheelHandler implements MouseWheelListener + { + + /** + * Receives notification whenever the mouse wheel is moved. + * + * @param event the mouse wheel event + */ + public void mouseWheelMoved(MouseWheelEvent event) + { + // TODO: Implement this properly. + } + + } + /** The Scrollpane for which the UI is provided by this class. */ protected JScrollPane scrollpane; + /** + * The horizontal scrollbar listener. + */ + protected ChangeListener hsbChangeListener; + + /** + * The vertical scrollbar listener. + */ + protected ChangeListener vsbChangeListener; + + /** + * The viewport listener. + */ + protected ChangeListener viewportChangeListener; + + /** + * The scrollpane property change listener. + */ + protected PropertyChangeListener spPropertyChangeListener; + + /** + * The mousewheel listener for the scrollpane. + */ + MouseWheelListener mouseWheelListener; + public static ComponentUI createUI(final JComponent c) { return new BasicScrollPaneUI(); @@ -65,11 +271,10 @@ public class BasicScrollPaneUI extends ScrollPaneUI protected void installDefaults(JScrollPane p) { scrollpane = p; - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - p.setForeground(defaults.getColor("ScrollPane.foreground")); - p.setBackground(defaults.getColor("ScrollPane.background")); - p.setFont(defaults.getFont("ScrollPane.font")); - p.setBorder(defaults.getBorder("ScrollPane.border")); + LookAndFeel.installColorsAndFont(p, "ScrollPane.background", + "ScrollPane.foreground", + "ScrollPane.font"); + LookAndFeel.installBorder(p, "ScrollPane.border"); p.setOpaque(true); } @@ -85,16 +290,141 @@ public class BasicScrollPaneUI extends ScrollPaneUI public void installUI(final JComponent c) { super.installUI(c); - this.installDefaults((JScrollPane)c); + installDefaults((JScrollPane) c); + installListeners((JScrollPane) c); + installKeyboardActions((JScrollPane) c); + } + + /** + * Installs the listeners on the scrollbars, the viewport and the scrollpane. + * + * @param sp the scrollpane on which to install the listeners + */ + protected void installListeners(JScrollPane sp) + { + if (spPropertyChangeListener == null) + spPropertyChangeListener = createPropertyChangeListener(); + sp.addPropertyChangeListener(spPropertyChangeListener); + + if (hsbChangeListener == null) + hsbChangeListener = createHSBChangeListener(); + sp.getHorizontalScrollBar().getModel().addChangeListener(hsbChangeListener); + + if (vsbChangeListener == null) + vsbChangeListener = createVSBChangeListener(); + sp.getVerticalScrollBar().getModel().addChangeListener(vsbChangeListener); + + if (viewportChangeListener == null) + viewportChangeListener = createViewportChangeListener(); + sp.getViewport().addChangeListener(viewportChangeListener); + + if (mouseWheelListener == null) + mouseWheelListener = createMouseWheelListener(); + sp.addMouseWheelListener(mouseWheelListener); + } + + /** + * Installs additional keyboard actions on the scrollpane. This is a hook + * method provided to subclasses in order to install their own keyboard + * actions. + * + * @param sp the scrollpane to install keyboard actions on + */ + protected void installKeyboardActions(JScrollPane sp) + { + // TODO: Is this only a hook method or should we actually do something + // here? If the latter, than figure out what and implement this. + } + + /** + * Creates and returns the change listener for the horizontal scrollbar. + * + * @return the change listener for the horizontal scrollbar + */ + protected ChangeListener createHSBChangeListener() + { + return new HSBChangeListener(); + } + + /** + * Creates and returns the change listener for the vertical scrollbar. + * + * @return the change listener for the vertical scrollbar + */ + protected ChangeListener createVSBChangeListener() + { + return new VSBChangeListener(); + } + + /** + * Creates and returns the change listener for the viewport. + * + * @return the change listener for the viewport + */ + protected ChangeListener createViewportChangeListener() + { + return new ViewportChangeHandler(); + } + + /** + * Creates and returns the property change listener for the scrollpane. + * + * @return the property change listener for the scrollpane + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeHandler(); + } + + /** + * Creates and returns the mouse wheel listener for the scrollpane. + * + * @return the mouse wheel listener for the scrollpane + */ + protected MouseWheelListener createMouseWheelListener() + { + return new MouseWheelHandler(); } public void uninstallUI(final JComponent c) { super.uninstallUI(c); this.uninstallDefaults((JScrollPane)c); + uninstallListeners((JScrollPane) c); + installKeyboardActions((JScrollPane) c); + } + + /** + * Uninstalls all the listeners that have been installed in + * {@link #installListeners(JScrollPane)}. + * + * @param c the scrollpane from which to uninstall the listeners + */ + protected void uninstallListeners(JComponent c) + { + JScrollPane sp = (JScrollPane) c; + sp.removePropertyChangeListener(spPropertyChangeListener); + sp.getHorizontalScrollBar().getModel() + .removeChangeListener(hsbChangeListener); + sp.getVerticalScrollBar().getModel() + .removeChangeListener(vsbChangeListener); + sp.getViewport().removeChangeListener(viewportChangeListener); + sp.removeMouseWheelListener(mouseWheelListener); + } + + /** + * Uninstalls all keyboard actions from the JScrollPane that have been + * installed by {@link #installKeyboardActions}. This is a hook method + * provided to subclasses to add their own keyboard actions. + * + * @param sp the scrollpane to uninstall keyboard actions from + */ + protected void uninstallKeyboardActions(JScrollPane sp) + { + // TODO: Is this only a hook method or should we actually do something + // here? If the latter, than figure out what and implement this. } - public Dimension getMinimumSize(JComponent c) { JScrollPane p = (JScrollPane ) c; @@ -107,6 +437,76 @@ public class BasicScrollPaneUI extends ScrollPaneUI // do nothing; the normal painting-of-children algorithm, along with // ScrollPaneLayout, does all the relevant work. } + + /** + * Synchronizes the scrollbars with the viewport's extents. + */ + protected void syncScrollPaneWithViewport() + { + JViewport vp = scrollpane.getViewport(); + + // Update the horizontal scrollbar. + JScrollBar hsb = scrollpane.getHorizontalScrollBar(); + hsb.setMaximum(vp.getViewSize().width); + hsb.setValue(vp.getViewPosition().x); + hsb.setVisibleAmount(vp.getExtentSize().width); + + // Update the vertical scrollbar. + JScrollBar vsb = scrollpane.getVerticalScrollBar(); + vsb.setMaximum(vp.getViewSize().height); + vsb.setValue(vp.getViewPosition().y); + vsb.setVisibleAmount(vp.getExtentSize().height); + } + + /** + * Receives notification when the <code>columnHeader</code> property has + * changed on the scrollpane. + * + * @param ev the property change event + */ + protected void updateColumnHeader(PropertyChangeEvent ev) + { + // TODO: Find out what should be done here. Or is this only a hook? + } + + /** + * Receives notification when the <code>rowHeader</code> property has changed + * on the scrollpane. + * + * @param ev the property change event + */ + protected void updateRowHeader(PropertyChangeEvent ev) + { + // TODO: Find out what should be done here. Or is this only a hook? + } + + /** + * Receives notification when the <code>scrollBarDisplayPolicy</code> + * property has changed on the scrollpane. + * + * @param ev the property change event + */ + protected void updateScrollBarDisplayPolicy(PropertyChangeEvent ev) + { + // TODO: Find out what should be done here. Or is this only a hook? + } + + /** + * Receives notification when the <code>viewport</code> property has changed + * on the scrollpane. + * + * This method sets removes the viewportChangeListener from the old viewport + * and adds it to the new viewport. + * + * @param ev the property change event + */ + protected void updateViewport(PropertyChangeEvent ev) + { + JViewport oldViewport = (JViewport) ev.getOldValue(); + oldViewport.removeChangeListener(viewportChangeListener); + JViewport newViewport = (JViewport) ev.getNewValue(); + oldViewport.addChangeListener(viewportChangeListener); + } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java index 38c9c7a2820..97caa3af7bd 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java @@ -41,13 +41,11 @@ package javax.swing.plaf.basic; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; -import java.awt.Insets; import java.awt.Rectangle; import javax.swing.JComponent; import javax.swing.JSeparator; import javax.swing.SwingUtilities; -import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.SeparatorUI; @@ -121,10 +119,8 @@ public class BasicSeparatorUI extends SeparatorUI */ protected void installDefaults(JSeparator s) { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - shadow = defaults.getColor("Separator.shadow"); - highlight = defaults.getColor("Separator.highlight"); + shadow = UIManager.getColor("Separator.shadow"); + highlight = UIManager.getColor("Separator.highlight"); s.setOpaque(false); } @@ -165,8 +161,8 @@ public class BasicSeparatorUI extends SeparatorUI /** * The separator is made of two lines. The top line will be - * the highlight color (or left line if it's vertical). The bottom - * or right line will be the shadow color. The two lines will + * the shadow color (or left line if it's vertical). The bottom + * or right line will be the highlight color. The two lines will * be centered inside the bounds box. If the separator is horizontal, * then it will be vertically centered, or if it's vertical, it will * be horizontally centered. @@ -180,9 +176,6 @@ public class BasicSeparatorUI extends SeparatorUI SwingUtilities.calculateInnerArea(c, r); Color saved = g.getColor(); - int midAB = r.width / 2 + r.x; - int midAD = r.height / 2 + r.y; - JSeparator s; if (c instanceof JSeparator) s = (JSeparator) c; @@ -190,21 +183,24 @@ public class BasicSeparatorUI extends SeparatorUI return; if (s.getOrientation() == JSeparator.HORIZONTAL) - { - g.setColor(highlight); - g.drawLine(r.x, midAD, r.x + r.width, midAD); - - g.setColor(shadow); - g.drawLine(r.x, midAD + 1, r.x + r.width, midAD + 1); - } - else - { - g.setColor(highlight); - g.drawLine(midAB, r.y, midAB, r.y + r.height); - - g.setColor(shadow); - g.drawLine(midAB + 1, r.y, midAB + 1, r.y + r.height); - } + { + int midAB = r.height / 2; + g.setColor(shadow); + g.drawLine(r.x, r.y + midAB - 1, r.x + r.width, r.y + midAB - 1); + + g.setColor(highlight); + g.fillRect(r.x, r.y + midAB, r.x + r.width, r.y + midAB); + } + else + { + int midAD = r.height / 2 + r.y; + g.setColor(shadow); + g.drawLine(r.x, r.y, r.x, r.y + r.height); + + g.setColor(highlight); + g.fillRect(r.x + midAD, r.y + r.height, r.x + midAD, r.y + r.height); + } + g.setColor(saved); } /** @@ -217,28 +213,14 @@ public class BasicSeparatorUI extends SeparatorUI */ public Dimension getPreferredSize(JComponent c) { - Dimension dims = new Dimension(0, 0); - Insets insets = c.getInsets(); - + Dimension pref = new Dimension(2, 0); if (c instanceof JSeparator) { JSeparator s = (JSeparator) c; - if (s.getOrientation() == JSeparator.HORIZONTAL) - { - dims.height = 2; - dims.width = 40; - } - else - { - dims.width = 2; - dims.height = 40; - } + pref = new Dimension(0, 2); } - dims.width += insets.left + insets.right; - dims.height += insets.top + insets.bottom; - - return dims; + return pref; } /** @@ -251,7 +233,7 @@ public class BasicSeparatorUI extends SeparatorUI */ public Dimension getMinimumSize(JComponent c) { - return getPreferredSize(c); + return new Dimension(0, 0); } /** @@ -264,6 +246,7 @@ public class BasicSeparatorUI extends SeparatorUI */ public Dimension getMaximumSize(JComponent c) { - return getPreferredSize(c); + return new Dimension(Short.MAX_VALUE, + Short.MAX_VALUE); } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java index 0b4058429c5..26f58051902 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java @@ -60,13 +60,14 @@ import java.beans.PropertyChangeListener; import java.util.Dictionary; import java.util.Enumeration; +import javax.swing.AbstractAction; import javax.swing.BoundedRangeModel; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JSlider; +import javax.swing.LookAndFeel; import javax.swing.SwingUtilities; import javax.swing.Timer; -import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -470,6 +471,34 @@ public class BasicSliderUI extends SliderUI } } + /** + * This class is no longer used as of JDK1.3. + */ + public class ActionScroller extends AbstractAction + { + /** + * Not used. + * + * @param slider not used + * @param dir not used + * @param block not used + */ + public ActionScroller(JSlider slider, int dir, boolean block) + { + // Not used. + } + + /** + * Not used. + * + * @param event not used + */ + public void actionPerformed(ActionEvent event) + { + // Not used. + } + } + /** Listener for changes from the model. */ protected ChangeListener changeListener; @@ -680,16 +709,14 @@ public class BasicSliderUI extends SliderUI */ protected void installDefaults(JSlider slider) { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - slider.setForeground(defaults.getColor("Slider.foreground")); - slider.setBackground(defaults.getColor("Slider.background")); - shadowColor = defaults.getColor("Slider.shadow"); - highlightColor = defaults.getColor("Slider.highlight"); - focusColor = defaults.getColor("Slider.focus"); - slider.setBorder(defaults.getBorder("Slider.border")); + LookAndFeel.installColors(slider, "Slider.background", + "Slider.foreground"); + LookAndFeel.installBorder(slider, "Slider.border"); + shadowColor = UIManager.getColor("Slider.shadow"); + highlightColor = UIManager.getColor("Slider.highlight"); + focusColor = UIManager.getColor("Slider.focus"); + focusInsets = UIManager.getInsets("Slider.focusInsets"); slider.setOpaque(true); - focusInsets = defaults.getInsets("Slider.focusInsets"); } /** @@ -1465,7 +1492,7 @@ public class BasicSliderUI extends SliderUI // FIXME: Move this to propertyChangeEvent handler, when we get those. leftToRightCache = slider.getComponentOrientation() != ComponentOrientation.RIGHT_TO_LEFT; // FIXME: This next line is only here because the above line is here. - calculateThumbLocation(); + calculateGeometry(); if (slider.getPaintTrack()) paintTrack(g); @@ -1958,7 +1985,7 @@ public class BasicSliderUI extends SliderUI public void paintThumb(Graphics g) { Color saved_color = g.getColor(); - + Point a = new Point(thumbRect.x, thumbRect.y); Point b = new Point(a); Point c = new Point(a); diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java index 97ab97b8972..3b7399eafaa 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java @@ -53,9 +53,8 @@ import java.beans.PropertyChangeListener; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JSpinner; +import javax.swing.LookAndFeel; import javax.swing.Timer; -import javax.swing.UIDefaults; -import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.SpinnerUI; @@ -167,16 +166,9 @@ public class BasicSpinnerUI extends SpinnerUI */ protected void installDefaults() { - /* most of it copied from BasicLabelUI, I don't know what keys are - available, so someone may want to update this. Hence: TODO - */ - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - /* - spinner.setForeground(defaults.getColor("Spinner.foreground")); - spinner.setBackground(defaults.getColor("Spinner.background")); - spinner.setFont(defaults.getFont("Spinner.font")); - spinner.setBorder(defaults.getBorder("Spinner.border")); - */ + LookAndFeel.installColorsAndFont(spinner, "Spinner.background", + "Spinner.foreground", "Spinner.font"); + LookAndFeel.installBorder(spinner, "Spinner.border"); spinner.setLayout(createLayout()); spinner.setOpaque(true); } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java index b8674ed2f08..69ed2be7c61 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java @@ -802,6 +802,7 @@ public class BasicSplitPaneDivider extends Container */ protected DividerLayout() { + // Nothing to do here. } /** diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java index ef8e2282349..746f628df6f 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java @@ -58,7 +58,7 @@ import java.beans.PropertyChangeListener; import javax.swing.JComponent; import javax.swing.JSplitPane; import javax.swing.KeyStroke; -import javax.swing.UIDefaults; +import javax.swing.LookAndFeel; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.SplitPaneUI; @@ -404,7 +404,7 @@ public class BasicSplitPaneUI extends SplitPaneUI */ protected void setComponentToSize(Component c, int size, int location, Insets insets, Dimension containerSize) - { + { int w = size; int h = containerSize.height - insets.top - insets.bottom; int x = location; @@ -637,7 +637,6 @@ public class BasicSplitPaneUI extends SplitPaneUI int x = insets.left; int h = size; int w = containerSize.width - insets.left - insets.right; - c.setBounds(x, y, w, h); } @@ -817,15 +816,12 @@ public class BasicSplitPaneUI extends SplitPaneUI int newSize = splitPane.getDividerSize(); int[] tmpSizes = layoutManager.getSizes(); dividerSize = tmpSizes[2]; - Component left = splitPane.getLeftComponent(); - Component right = splitPane.getRightComponent(); - int newSpace = newSize - tmpSizes[2]; - + int newSpace = newSize - tmpSizes[2]; tmpSizes[2] = newSize; tmpSizes[0] += newSpace / 2; tmpSizes[1] += newSpace / 2; - + layoutManager.setSizes(tmpSizes); } else if (e.getPropertyName().equals(JSplitPane.ORIENTATION_PROPERTY)) @@ -942,6 +938,7 @@ public class BasicSplitPaneUI extends SplitPaneUI */ public BasicSplitPaneUI() { + // Nothing to do here. } /** @@ -991,16 +988,16 @@ public class BasicSplitPaneUI extends SplitPaneUI */ protected void installDefaults() { + LookAndFeel.installColors(splitPane, "SplitPane.background", + "SplitPane.foreground"); + LookAndFeel.installBorder(splitPane, "SplitPane.border"); divider = createDefaultDivider(); resetLayoutManager(); nonContinuousLayoutDivider = createDefaultNonContinuousLayoutDivider(); splitPane.add(divider, JSplitPane.DIVIDER); // There is no need to add the nonContinuousLayoutDivider - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - splitPane.setBackground(defaults.getColor("SplitPane.background")); - splitPane.setBorder(defaults.getBorder("SplitPane.border")); - splitPane.setDividerSize(defaults.getInt("SplitPane.dividerSize")); + splitPane.setDividerSize(UIManager.getInt("SplitPane.dividerSize")); splitPane.setOpaque(true); } @@ -1301,15 +1298,41 @@ public class BasicSplitPaneUI extends SplitPaneUI */ public void setDividerLocation(JSplitPane jc, int location) { + location = validLocation(location); + Container p = jc.getParent(); + Dimension rightPrefSize = jc.getRightComponent().getPreferredSize(); + Dimension size = jc.getSize(); + // check if the size has been set for the splitpane + if (size.width == 0 && size.height == 0) + size = jc.getPreferredSize(); + + if (getOrientation() == 0 && location > size.height) + { + location = size.height; + while (p != null) + { + p.setSize(p.getWidth(), p.getHeight() + rightPrefSize.height); + p = p.getParent(); + } + } + else if (location > size.width) + { + location = size.width; + while (p != null) + { + p.setSize(p.getWidth() + rightPrefSize.width, p.getHeight()); + p = p.getParent(); + } + } + setLastDragLocation(getDividerLocation(splitPane)); splitPane.setLastDividerLocation(getDividerLocation(splitPane)); int[] tmpSizes = layoutManager.getSizes(); - tmpSizes[0] = location + tmpSizes[0] = location - layoutManager.getInitialLocation(splitPane.getInsets()); tmpSizes[1] = layoutManager.getAvailableSize(splitPane.getSize(), splitPane.getInsets()) - - tmpSizes[0] - tmpSizes[1]; - + - tmpSizes[0]; layoutManager.setSizes(tmpSizes); splitPane.revalidate(); splitPane.repaint(); @@ -1338,11 +1361,9 @@ public class BasicSplitPaneUI extends SplitPaneUI */ public int getMinimumDividerLocation(JSplitPane jc) { - int value = layoutManager.getInitialLocation(jc.getInsets()) - - layoutManager.getAvailableSize(jc.getSize(), jc.getInsets()) - + splitPane.getDividerSize(); - if (layoutManager.components[1] != null) - value += layoutManager.minimumSizeOfComponent(1); + int value = layoutManager.getInitialLocation(jc.getInsets()); + if (layoutManager.components[0] != null) + value -= layoutManager.minimumSizeOfComponent(0); return value; } @@ -1388,6 +1409,7 @@ public class BasicSplitPaneUI extends SplitPaneUI */ public void paint(Graphics g, JComponent jc) { + // TODO: What should be done here? } /** @@ -1550,10 +1572,12 @@ public class BasicSplitPaneUI extends SplitPaneUI */ private int validLocation(int location) { - if (location < getMinimumDividerLocation(splitPane)) - return getMinimumDividerLocation(splitPane); - if (location > getMaximumDividerLocation(splitPane)) - return getMaximumDividerLocation(splitPane); + int min = getMinimumDividerLocation(splitPane); + int max = getMaximumDividerLocation(splitPane); + if (min > 0 && location < min) + return min; + if (max > 0 && location > max) + return max; return location; } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java index 7e9d9b9820c..ce9ea3ec7f1 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java @@ -64,9 +64,9 @@ import javax.swing.JPanel; import javax.swing.JTabbedPane; import javax.swing.JViewport; import javax.swing.KeyStroke; +import javax.swing.LookAndFeel; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; -import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -136,36 +136,36 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) { - if (e.getSource() == incrButton) - { - if (++currentScrollLocation >= tabCount) - currentScrollLocation = tabCount - 1; - - int width = 0; - for (int i = currentScrollLocation - 1; i < tabCount; i++) - width += rects[i].width; - if (width < viewport.getWidth()) - // FIXME: Still getting mouse events after the button is disabled. - // incrButton.setEnabled(false); - currentScrollLocation--; - else if (! decrButton.isEnabled()) - decrButton.setEnabled(true); - tabPane.revalidate(); - tabPane.repaint(); - return; - } - else if (e.getSource() == decrButton) - { - if (--currentScrollLocation < 0) - currentScrollLocation = 0; - if (currentScrollLocation == 0) - decrButton.setEnabled(false); - else if (! incrButton.isEnabled()) - incrButton.setEnabled(true); - tabPane.revalidate(); - tabPane.repaint(); - return; - } + if (e.getSource() == incrButton) + { + if (++currentScrollLocation >= tabCount) + currentScrollLocation = tabCount - 1; + + int width = 0; + for (int i = currentScrollLocation - 1; i < tabCount; i++) + width += rects[i].width; + if (width < viewport.getWidth()) + // FIXME: Still getting mouse events after the button is disabled. + // incrButton.setEnabled(false); + currentScrollLocation--; + else if (! decrButton.isEnabled()) + decrButton.setEnabled(true); + tabPane.revalidate(); + tabPane.repaint(); + return; + } + else if (e.getSource() == decrButton) + { + if (--currentScrollLocation < 0) + currentScrollLocation = 0; + if (currentScrollLocation == 0) + decrButton.setEnabled(false); + else if (! incrButton.isEnabled()) + incrButton.setEnabled(true); + tabPane.revalidate(); + tabPane.repaint(); + return; + } } int index = tabForCoordinate(tabPane, x, y); @@ -173,7 +173,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants // We need to check since there are areas where tabs cannot be // e.g. in the inset area. if (index != -1 && tabPane.isEnabledAt(index)) - tabPane.setSelectedIndex(index); + tabPane.setSelectedIndex(index); tabPane.revalidate(); tabPane.repaint(); } @@ -198,15 +198,15 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { if (e.getPropertyName().equals("tabLayoutPolicy")) { - layoutManager = createLayoutManager(); - - tabPane.setLayout(layoutManager); + layoutManager = createLayoutManager(); + + tabPane.setLayout(layoutManager); } else if (e.getPropertyName().equals("tabPlacement") - && tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) + && tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) { - incrButton = createIncreaseButton(); - decrButton = createDecreaseButton(); + incrButton = createIncreaseButton(); + decrButton = createDecreaseButton(); } tabPane.layout(); tabPane.repaint(); @@ -245,13 +245,13 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants if (tabPane.getSelectedIndex() != -1) { - Component visible = getVisibleComponent(); - Insets insets = getContentBorderInsets(tabPane.getTabPlacement()); - if (visible != null) - visible.setBounds(contentRect.x + insets.left, - contentRect.y + insets.top, - contentRect.width - insets.left - insets.right, - contentRect.height - insets.top - insets.bottom); + Component visible = getVisibleComponent(); + Insets insets = getContentBorderInsets(tabPane.getTabPlacement()); + if (visible != null) + visible.setBounds(contentRect.x + insets.left, + contentRect.y + insets.top, + contentRect.width - insets.left - insets.right, + contentRect.height - insets.top - insets.bottom); } } @@ -275,35 +275,35 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants Dimension dims; for (int i = 0; i < tabPane.getTabCount(); i++) { - c = tabPane.getComponentAt(i); - if (c == null) - continue; - calcRect = c.getBounds(); - dims = c.getPreferredSize(); - if (dims != null) - { - componentHeight = Math.max(componentHeight, dims.height); - componentWidth = Math.max(componentWidth, dims.width); - } + c = tabPane.getComponentAt(i); + if (c == null) + continue; + calcRect = c.getBounds(); + dims = c.getPreferredSize(); + if (dims != null) + { + componentHeight = Math.max(componentHeight, dims.height); + componentWidth = Math.max(componentWidth, dims.width); + } } Insets insets = tabPane.getInsets(); if (tabPlacement == SwingConstants.TOP || tabPlacement == SwingConstants.BOTTOM) { - int min = calculateMaxTabWidth(tabPlacement); - width = Math.max(min, componentWidth); - - int tabAreaHeight = preferredTabAreaHeight(tabPlacement, width); - height = tabAreaHeight + componentHeight; + int min = calculateMaxTabWidth(tabPlacement); + width = Math.max(min, componentWidth); + + int tabAreaHeight = preferredTabAreaHeight(tabPlacement, width); + height = tabAreaHeight + componentHeight; } else { - int min = calculateMaxTabHeight(tabPlacement); - height = Math.max(min, componentHeight); - - int tabAreaWidth = preferredTabAreaWidth(tabPlacement, height); - width = tabAreaWidth + componentWidth; + int min = calculateMaxTabHeight(tabPlacement); + height = Math.max(min, componentHeight); + + int tabAreaWidth = preferredTabAreaWidth(tabPlacement, height); + width = tabAreaWidth + componentWidth; } return new Dimension(width, height); @@ -330,7 +330,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants protected void calculateTabRects(int tabPlacement, int tabCount) { if (tabCount == 0) - return; + return; assureRectsCreated(tabCount); FontMetrics fm = getFontMetrics(); @@ -343,113 +343,112 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants if (tabPlacement == SwingConstants.TOP || tabPlacement == SwingConstants.BOTTOM) { - int maxHeight = calculateMaxTabHeight(tabPlacement); - - calcRect.width -= tabAreaInsets.left + tabAreaInsets.right; - max = calcRect.width + tabAreaInsets.left + insets.left; - start += tabAreaInsets.left + insets.left; - int width = 0; - int runWidth = start; - - for (int i = 0; i < tabCount; i++) - { - width = calculateTabWidth(tabPlacement, i, fm); - - if (runWidth + width > max) - { - runWidth = tabAreaInsets.left + insets.left - + getTabRunIndent(tabPlacement, ++runs); - rects[i] = new Rectangle(runWidth, - insets.top + tabAreaInsets.top, - width, maxHeight); - runWidth += width; - if (runs > tabRuns.length - 1) - expandTabRunsArray(); - tabRuns[runs] = i; - } - else - { - rects[i] = new Rectangle(runWidth, - insets.top + tabAreaInsets.top, - width, maxHeight); - runWidth += width; - } - } - runs++; - tabAreaRect.width = tabPane.getWidth() - insets.left - insets.right; - tabAreaRect.height = runs * maxTabHeight - - (runs - 1) * tabRunOverlay - + tabAreaInsets.top + tabAreaInsets.bottom; - contentRect.width = tabAreaRect.width; - contentRect.height = tabPane.getHeight() - insets.top - - insets.bottom - tabAreaRect.height; - contentRect.x = insets.left; - tabAreaRect.x = insets.left; - if (tabPlacement == SwingConstants.BOTTOM) - { - contentRect.y = insets.top; - tabAreaRect.y = contentRect.y + contentRect.height; - } - else - { - tabAreaRect.y = insets.top; - contentRect.y = tabAreaRect.y + tabAreaRect.height; - } + int maxHeight = calculateMaxTabHeight(tabPlacement); + + calcRect.width -= tabAreaInsets.left + tabAreaInsets.right; + max = calcRect.width + tabAreaInsets.left + insets.left; + start += tabAreaInsets.left + insets.left; + int width = 0; + int runWidth = start; + + for (int i = 0; i < tabCount; i++) + { + width = calculateTabWidth(tabPlacement, i, fm); + if (runWidth + width > max) + { + runWidth = tabAreaInsets.left + insets.left + + getTabRunIndent(tabPlacement, ++runs); + rects[i] = new Rectangle(runWidth, + insets.top + tabAreaInsets.top, + width, maxHeight); + runWidth += width; + if (runs > tabRuns.length - 1) + expandTabRunsArray(); + tabRuns[runs] = i; + } + else + { + rects[i] = new Rectangle(runWidth, + insets.top + tabAreaInsets.top, + width, maxHeight); + runWidth += width; + } + } + runs++; + tabAreaRect.width = tabPane.getWidth() - insets.left - insets.right; + tabAreaRect.height = runs * maxTabHeight + - (runs - 1) * tabRunOverlay + + tabAreaInsets.top + tabAreaInsets.bottom; + contentRect.width = tabAreaRect.width; + contentRect.height = tabPane.getHeight() - insets.top + - insets.bottom - tabAreaRect.height; + contentRect.x = insets.left; + tabAreaRect.x = insets.left; + if (tabPlacement == SwingConstants.BOTTOM) + { + contentRect.y = insets.top; + tabAreaRect.y = contentRect.y + contentRect.height; + } + else + { + tabAreaRect.y = insets.top; + contentRect.y = tabAreaRect.y + tabAreaRect.height; + } } else { - int maxWidth = calculateMaxTabWidth(tabPlacement); - calcRect.height -= tabAreaInsets.top + tabAreaInsets.bottom; - max = calcRect.height + tabAreaInsets.top + insets.top; - - int height = 0; - start += tabAreaInsets.top + insets.top; - int runHeight = start; - - int fontHeight = fm.getHeight(); - - for (int i = 0; i < tabCount; i++) - { - height = calculateTabHeight(tabPlacement, i, fontHeight); - if (runHeight + height > max) - { - runHeight = tabAreaInsets.top + insets.top - + getTabRunIndent(tabPlacement, ++runs); - rects[i] = new Rectangle(insets.left + tabAreaInsets.left, - runHeight, maxWidth, height); - runHeight += height; - if (runs > tabRuns.length - 1) - expandTabRunsArray(); - tabRuns[runs] = i; - } - else - { - rects[i] = new Rectangle(insets.left + tabAreaInsets.left, - runHeight, maxWidth, height); - runHeight += height; - } - } - runs++; - - tabAreaRect.width = runs * maxTabWidth - (runs - 1) * tabRunOverlay - + tabAreaInsets.left + tabAreaInsets.right; - tabAreaRect.height = tabPane.getHeight() - insets.top - - insets.bottom; - tabAreaRect.y = insets.top; - contentRect.width = tabPane.getWidth() - insets.left - insets.right - - tabAreaRect.width; - contentRect.height = tabAreaRect.height; - contentRect.y = insets.top; - if (tabPlacement == SwingConstants.LEFT) - { - tabAreaRect.x = insets.left; - contentRect.x = tabAreaRect.x + tabAreaRect.width; - } - else - { - contentRect.x = insets.left; - tabAreaRect.x = contentRect.x + contentRect.width; - } + int maxWidth = calculateMaxTabWidth(tabPlacement); + calcRect.height -= tabAreaInsets.top + tabAreaInsets.bottom; + max = calcRect.height + tabAreaInsets.top + insets.top; + + int height = 0; + start += tabAreaInsets.top + insets.top; + int runHeight = start; + + int fontHeight = fm.getHeight(); + + for (int i = 0; i < tabCount; i++) + { + height = calculateTabHeight(tabPlacement, i, fontHeight); + if (runHeight + height > max) + { + runHeight = tabAreaInsets.top + insets.top + + getTabRunIndent(tabPlacement, ++runs); + rects[i] = new Rectangle(insets.left + tabAreaInsets.left, + runHeight, maxWidth, height); + runHeight += height; + if (runs > tabRuns.length - 1) + expandTabRunsArray(); + tabRuns[runs] = i; + } + else + { + rects[i] = new Rectangle(insets.left + tabAreaInsets.left, + runHeight, maxWidth, height); + runHeight += height; + } + } + runs++; + + tabAreaRect.width = runs * maxTabWidth - (runs - 1) * tabRunOverlay + + tabAreaInsets.left + tabAreaInsets.right; + tabAreaRect.height = tabPane.getHeight() - insets.top + - insets.bottom; + tabAreaRect.y = insets.top; + contentRect.width = tabPane.getWidth() - insets.left - insets.right + - tabAreaRect.width; + contentRect.height = tabAreaRect.height; + contentRect.y = insets.top; + if (tabPlacement == SwingConstants.LEFT) + { + tabAreaRect.x = insets.left; + contentRect.x = tabAreaRect.x + tabAreaRect.width; + } + else + { + contentRect.x = insets.left; + tabAreaRect.x = contentRect.x + contentRect.width; + } } runCount = runs; @@ -457,62 +456,62 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants normalizeTabRuns(tabPlacement, tabCount, start, max); selectedRun = getRunForTab(tabCount, tabPane.getSelectedIndex()); if (shouldRotateTabRuns(tabPlacement)) - rotateTabRuns(tabPlacement, selectedRun); + rotateTabRuns(tabPlacement, selectedRun); // Need to pad the runs and move them to the correct location. for (int i = 0; i < runCount; i++) { - int first = lastTabInRun(tabCount, getPreviousTabRun(i)) + 1; - if (first == tabCount) - first = 0; - int last = lastTabInRun(tabCount, i); - if (shouldPadTabRun(tabPlacement, i)) - padTabRun(tabPlacement, first, last, max); - - // Done padding, now need to move it. - if (tabPlacement == SwingConstants.TOP && i > 0) - { - for (int j = first; j <= last; j++) - rects[j].y += (runCount - i) * maxTabHeight - - (runCount - i) * tabRunOverlay; - } - - if (tabPlacement == SwingConstants.BOTTOM) - { - int height = tabPane.getBounds().height - insets.bottom - - tabAreaInsets.bottom; - int adjustment; - if (i == 0) - adjustment = height - maxTabHeight; - else - adjustment = height - (runCount - i + 1) * maxTabHeight - - (runCount - i) * tabRunOverlay; - - for (int j = first; j <= last; j++) - rects[j].y = adjustment; - } - - if (tabPlacement == SwingConstants.LEFT && i > 0) - { - for (int j = first; j <= last; j++) - rects[j].x += (runCount - i) * maxTabWidth - - (runCount - i) * tabRunOverlay; - } - - if (tabPlacement == SwingConstants.RIGHT) - { - int width = tabPane.getBounds().width - insets.right - - tabAreaInsets.right; - int adjustment; - if (i == 0) - adjustment = width - maxTabWidth; - else - adjustment = width - (runCount - i + 1) * maxTabWidth - + (runCount - i) * tabRunOverlay; - - for (int j = first; j <= last; j++) - rects[j].x = adjustment; - } + int first = lastTabInRun(tabCount, getPreviousTabRun(i)) + 1; + if (first == tabCount) + first = 0; + int last = lastTabInRun(tabCount, i); + if (shouldPadTabRun(tabPlacement, i)) + padTabRun(tabPlacement, first, last, max); + + // Done padding, now need to move it. + if (tabPlacement == SwingConstants.TOP && i > 0) + { + for (int j = first; j <= last; j++) + rects[j].y += (runCount - i) * maxTabHeight + - (runCount - i) * tabRunOverlay; + } + + if (tabPlacement == SwingConstants.BOTTOM) + { + int height = tabPane.getBounds().height - insets.bottom + - tabAreaInsets.bottom; + int adjustment; + if (i == 0) + adjustment = height - maxTabHeight; + else + adjustment = height - (runCount - i + 1) * maxTabHeight + - (runCount - i) * tabRunOverlay; + + for (int j = first; j <= last; j++) + rects[j].y = adjustment; + } + + if (tabPlacement == SwingConstants.LEFT && i > 0) + { + for (int j = first; j <= last; j++) + rects[j].x += (runCount - i) * maxTabWidth + - (runCount - i) * tabRunOverlay; + } + + if (tabPlacement == SwingConstants.RIGHT) + { + int width = tabPane.getBounds().width - insets.right + - tabAreaInsets.right; + int adjustment; + if (i == 0) + adjustment = width - maxTabWidth; + else + adjustment = width - (runCount - i + 1) * maxTabWidth + + (runCount - i) * tabRunOverlay; + + for (int j = first; j <= last; j++) + rects[j].x = adjustment; + } } padSelectedTab(tabPlacement, tabPane.getSelectedIndex()); } @@ -565,74 +564,74 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants if (tabPlacement == SwingUtilities.TOP || tabPlacement == SwingUtilities.BOTTOM) { - // We should only do this for runCount - 1, cause we can only shift that many times between - // runs. - for (int i = 1; i < runCount; i++) - { - Rectangle currRun = rects[lastTabInRun(tabCount, i)]; - Rectangle nextRun = rects[lastTabInRun(tabCount, getNextTabRun(i))]; - int spaceInCurr = currRun.x + currRun.width; - int spaceInNext = nextRun.x + nextRun.width; - - int diffNow = spaceInCurr - spaceInNext; - int diffLater = (spaceInCurr - currRun.width) - - (spaceInNext + currRun.width); - while (Math.abs(diffLater) < Math.abs(diffNow) - && spaceInNext + currRun.width < max) - { - tabRuns[i]--; - spaceInNext += currRun.width; - spaceInCurr -= currRun.width; - currRun = rects[lastTabInRun(tabCount, i)]; - diffNow = spaceInCurr - spaceInNext; - diffLater = (spaceInCurr - currRun.width) - - (spaceInNext + currRun.width); - } - - // Fix the bounds. - int first = lastTabInRun(tabCount, i) + 1; - int last = lastTabInRun(tabCount, getNextTabRun(i)); - int currX = tabAreaInsets.left; - for (int j = first; j <= last; j++) - { - rects[j].x = currX; - currX += rects[j].width; - } - } + // We should only do this for runCount - 1, cause we can only shift that many times between + // runs. + for (int i = 1; i < runCount; i++) + { + Rectangle currRun = rects[lastTabInRun(tabCount, i)]; + Rectangle nextRun = rects[lastTabInRun(tabCount, getNextTabRun(i))]; + int spaceInCurr = currRun.x + currRun.width; + int spaceInNext = nextRun.x + nextRun.width; + + int diffNow = spaceInCurr - spaceInNext; + int diffLater = (spaceInCurr - currRun.width) + - (spaceInNext + currRun.width); + while (Math.abs(diffLater) < Math.abs(diffNow) + && spaceInNext + currRun.width < max) + { + tabRuns[i]--; + spaceInNext += currRun.width; + spaceInCurr -= currRun.width; + currRun = rects[lastTabInRun(tabCount, i)]; + diffNow = spaceInCurr - spaceInNext; + diffLater = (spaceInCurr - currRun.width) + - (spaceInNext + currRun.width); + } + + // Fix the bounds. + int first = lastTabInRun(tabCount, i) + 1; + int last = lastTabInRun(tabCount, getNextTabRun(i)); + int currX = tabAreaInsets.left; + for (int j = first; j <= last; j++) + { + rects[j].x = currX; + currX += rects[j].width; + } + } } else { - for (int i = 1; i < runCount; i++) - { - Rectangle currRun = rects[lastTabInRun(tabCount, i)]; - Rectangle nextRun = rects[lastTabInRun(tabCount, getNextTabRun(i))]; - int spaceInCurr = currRun.y + currRun.height; - int spaceInNext = nextRun.y + nextRun.height; - - int diffNow = spaceInCurr - spaceInNext; - int diffLater = (spaceInCurr - currRun.height) - - (spaceInNext + currRun.height); - while (Math.abs(diffLater) < Math.abs(diffNow) - && spaceInNext + currRun.height < max) - { - tabRuns[i]--; - spaceInNext += currRun.height; - spaceInCurr -= currRun.height; - currRun = rects[lastTabInRun(tabCount, i)]; - diffNow = spaceInCurr - spaceInNext; - diffLater = (spaceInCurr - currRun.height) - - (spaceInNext + currRun.height); - } - - int first = lastTabInRun(tabCount, i) + 1; - int last = lastTabInRun(tabCount, getNextTabRun(i)); - int currY = tabAreaInsets.top; - for (int j = first; j <= last; j++) - { - rects[j].y = currY; - currY += rects[j].height; - } - } + for (int i = 1; i < runCount; i++) + { + Rectangle currRun = rects[lastTabInRun(tabCount, i)]; + Rectangle nextRun = rects[lastTabInRun(tabCount, getNextTabRun(i))]; + int spaceInCurr = currRun.y + currRun.height; + int spaceInNext = nextRun.y + nextRun.height; + + int diffNow = spaceInCurr - spaceInNext; + int diffLater = (spaceInCurr - currRun.height) + - (spaceInNext + currRun.height); + while (Math.abs(diffLater) < Math.abs(diffNow) + && spaceInNext + currRun.height < max) + { + tabRuns[i]--; + spaceInNext += currRun.height; + spaceInCurr -= currRun.height; + currRun = rects[lastTabInRun(tabCount, i)]; + diffNow = spaceInCurr - spaceInNext; + diffLater = (spaceInCurr - currRun.height) + - (spaceInNext + currRun.height); + } + + int first = lastTabInRun(tabCount, i) + 1; + int last = lastTabInRun(tabCount, getNextTabRun(i)); + int currY = tabAreaInsets.top; + for (int j = first; j <= last; j++) + { + rects[j].y = currY; + currY += rects[j].height; + } + } } } @@ -673,42 +672,42 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants if (tabPlacement == SwingConstants.TOP || tabPlacement == SwingConstants.BOTTOM) { - int runWidth = rects[end].x + rects[end].width; - int spaceRemaining = max - runWidth; - int numTabs = end - start + 1; - - // now divvy up the space. - int spaceAllocated = spaceRemaining / numTabs; - int currX = rects[start].x; - for (int i = start; i <= end; i++) - { - rects[i].x = currX; - rects[i].width += spaceAllocated; - currX += rects[i].width; - // This is used because since the spaceAllocated - // variable is an int, it rounds down. Sometimes, - // we don't fill an entire row, so we make it do - // so now. - if (i == end && rects[i].x + rects[i].width != max) - rects[i].width = max - rects[i].x; - } + int runWidth = rects[end].x + rects[end].width; + int spaceRemaining = max - runWidth; + int numTabs = end - start + 1; + + // now divvy up the space. + int spaceAllocated = spaceRemaining / numTabs; + int currX = rects[start].x; + for (int i = start; i <= end; i++) + { + rects[i].x = currX; + rects[i].width += spaceAllocated; + currX += rects[i].width; + // This is used because since the spaceAllocated + // variable is an int, it rounds down. Sometimes, + // we don't fill an entire row, so we make it do + // so now. + if (i == end && rects[i].x + rects[i].width != max) + rects[i].width = max - rects[i].x; + } } else { - int runHeight = rects[end].y + rects[end].height; - int spaceRemaining = max - runHeight; - int numTabs = end - start + 1; - - int spaceAllocated = spaceRemaining / numTabs; - int currY = rects[start].y; - for (int i = start; i <= end; i++) - { - rects[i].y = currY; - rects[i].height += spaceAllocated; - currY += rects[i].height; - if (i == end && rects[i].y + rects[i].height != max) - rects[i].height = max - rects[i].y; - } + int runHeight = rects[end].y + rects[end].height; + int spaceRemaining = max - runHeight; + int numTabs = end - start + 1; + + int spaceAllocated = spaceRemaining / numTabs; + int currY = rects[start].y; + for (int i = start; i <= end; i++) + { + rects[i].y = currY; + rects[i].height += spaceAllocated; + currY += rects[i].height; + if (i == end && rects[i].y + rects[i].height != max) + rects[i].height = max - rects[i].y; + } } } @@ -736,7 +735,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants protected int preferredTabAreaHeight(int tabPlacement, int width) { if (tabPane.getTabCount() == 0) - return calculateTabAreaHeight(tabPlacement, 0, 0); + return calculateTabAreaHeight(tabPlacement, 0, 0); int runs = 0; int runWidth = 0; @@ -758,14 +757,14 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants // be IF we got our desired width. for (int i = 0; i < tabPane.getTabCount(); i++) { - tabWidth = calculateTabWidth(tabPlacement, i, fm); - if (runWidth + tabWidth > width) - { - runWidth = tabWidth; - runs++; - } - else - runWidth += tabWidth; + tabWidth = calculateTabWidth(tabPlacement, i, fm); + if (runWidth + tabWidth > width) + { + runWidth = tabWidth; + runs++; + } + else + runWidth += tabWidth; } runs++; @@ -787,7 +786,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants protected int preferredTabAreaWidth(int tabPlacement, int height) { if (tabPane.getTabCount() == 0) - return calculateTabAreaHeight(tabPlacement, 0, 0); + return calculateTabAreaHeight(tabPlacement, 0, 0); int runs = 0; int runHeight = 0; @@ -804,14 +803,14 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants for (int i = 0; i < tabPane.getTabCount(); i++) { - tabHeight = calculateTabHeight(tabPlacement, i, fontHeight); - if (runHeight + tabHeight > height) - { - runHeight = tabHeight; - runs++; - } - else - runHeight += tabHeight; + tabHeight = calculateTabHeight(tabPlacement, i, fontHeight); + if (runHeight + tabHeight > height) + { + runHeight = tabHeight; + runs++; + } + else + runHeight += tabHeight; } runs++; @@ -831,19 +830,19 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants protected void rotateTabRuns(int tabPlacement, int selectedRun) { if (runCount == 1 || selectedRun == 1 || selectedRun == -1) - return; + return; int[] newTabRuns = new int[tabRuns.length]; int currentRun = selectedRun; int i = 1; do { - newTabRuns[i] = tabRuns[currentRun]; - currentRun = getNextTabRun(currentRun); - i++; + newTabRuns[i] = tabRuns[currentRun]; + currentRun = getNextTabRun(currentRun); + i++; } while (i < runCount); if (runCount > 1) - newTabRuns[0] = tabRuns[currentRun]; + newTabRuns[0] = tabRuns[currentRun]; tabRuns = newTabRuns; BasicTabbedPaneUI.this.selectedRun = 1; @@ -902,7 +901,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants protected int preferredTabAreaHeight(int tabPlacement, int width) { if (tabPane.getTabCount() == 0) - return calculateTabAreaHeight(tabPlacement, 0, 0); + return calculateTabAreaHeight(tabPlacement, 0, 0); int runs = 1; @@ -923,7 +922,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants protected int preferredTabAreaWidth(int tabPlacement, int height) { if (tabPane.getTabCount() == 0) - return calculateTabAreaHeight(tabPlacement, 0, 0); + return calculateTabAreaHeight(tabPlacement, 0, 0); int runs = 1; @@ -944,7 +943,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants protected void calculateTabRects(int tabPlacement, int tabCount) { if (tabCount == 0) - return; + return; assureRectsCreated(tabCount); FontMetrics fm = getFontMetrics(); @@ -958,76 +957,76 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants if (tabPlacement == SwingConstants.TOP || tabPlacement == SwingConstants.BOTTOM) { - int maxHeight = calculateMaxTabHeight(tabPlacement); - calcRect.width -= tabAreaInsets.left + tabAreaInsets.right; - max = calcRect.width + tabAreaInsets.left + insets.left; - start = tabAreaInsets.left + insets.left; - int width = 0; - int runWidth = start; - top = insets.top + tabAreaInsets.top; - for (int i = 0; i < tabCount; i++) - { - width = calculateTabWidth(tabPlacement, i, fm); - - rects[i] = new Rectangle(runWidth, top, width, maxHeight); - runWidth += width; - } - tabAreaRect.width = tabPane.getWidth() - insets.left - insets.right; - tabAreaRect.height = runs * maxTabHeight - - (runs - 1) * tabRunOverlay - + tabAreaInsets.top + tabAreaInsets.bottom; - contentRect.width = tabAreaRect.width; - contentRect.height = tabPane.getHeight() - insets.top - - insets.bottom - tabAreaRect.height; - contentRect.x = insets.left; - tabAreaRect.x = insets.left; - if (tabPlacement == SwingConstants.BOTTOM) - { - contentRect.y = insets.top; - tabAreaRect.y = contentRect.y + contentRect.height; - } - else - { - tabAreaRect.y = insets.top; - contentRect.y = tabAreaRect.y + tabAreaRect.height; - } + int maxHeight = calculateMaxTabHeight(tabPlacement); + calcRect.width -= tabAreaInsets.left + tabAreaInsets.right; + max = calcRect.width + tabAreaInsets.left + insets.left; + start = tabAreaInsets.left + insets.left; + int width = 0; + int runWidth = start; + top = insets.top + tabAreaInsets.top; + for (int i = 0; i < tabCount; i++) + { + width = calculateTabWidth(tabPlacement, i, fm); + + rects[i] = new Rectangle(runWidth, top, width, maxHeight); + runWidth += width; + } + tabAreaRect.width = tabPane.getWidth() - insets.left - insets.right; + tabAreaRect.height = runs * maxTabHeight + - (runs - 1) * tabRunOverlay + + tabAreaInsets.top + tabAreaInsets.bottom; + contentRect.width = tabAreaRect.width; + contentRect.height = tabPane.getHeight() - insets.top + - insets.bottom - tabAreaRect.height; + contentRect.x = insets.left; + tabAreaRect.x = insets.left; + if (tabPlacement == SwingConstants.BOTTOM) + { + contentRect.y = insets.top; + tabAreaRect.y = contentRect.y + contentRect.height; + } + else + { + tabAreaRect.y = insets.top; + contentRect.y = tabAreaRect.y + tabAreaRect.height; + } } else { - int maxWidth = calculateMaxTabWidth(tabPlacement); - - calcRect.height -= tabAreaInsets.top + tabAreaInsets.bottom; - max = calcRect.height + tabAreaInsets.top; - int height = 0; - start = tabAreaInsets.top + insets.top; - int runHeight = start; - int fontHeight = fm.getHeight(); - top = insets.left + tabAreaInsets.left; - for (int i = 0; i < tabCount; i++) - { - height = calculateTabHeight(tabPlacement, i, fontHeight); - rects[i] = new Rectangle(top, runHeight, maxWidth, height); - runHeight += height; - } - tabAreaRect.width = runs * maxTabWidth - (runs - 1) * tabRunOverlay - + tabAreaInsets.left + tabAreaInsets.right; - tabAreaRect.height = tabPane.getHeight() - insets.top - - insets.bottom; - tabAreaRect.y = insets.top; - contentRect.width = tabPane.getWidth() - insets.left - insets.right - - tabAreaRect.width; - contentRect.height = tabAreaRect.height; - contentRect.y = insets.top; - if (tabPlacement == SwingConstants.LEFT) - { - tabAreaRect.x = insets.left; - contentRect.x = tabAreaRect.x + tabAreaRect.width; - } - else - { - contentRect.x = insets.left; - tabAreaRect.x = contentRect.x + contentRect.width; - } + int maxWidth = calculateMaxTabWidth(tabPlacement); + + calcRect.height -= tabAreaInsets.top + tabAreaInsets.bottom; + max = calcRect.height + tabAreaInsets.top; + int height = 0; + start = tabAreaInsets.top + insets.top; + int runHeight = start; + int fontHeight = fm.getHeight(); + top = insets.left + tabAreaInsets.left; + for (int i = 0; i < tabCount; i++) + { + height = calculateTabHeight(tabPlacement, i, fontHeight); + rects[i] = new Rectangle(top, runHeight, maxWidth, height); + runHeight += height; + } + tabAreaRect.width = runs * maxTabWidth - (runs - 1) * tabRunOverlay + + tabAreaInsets.left + tabAreaInsets.right; + tabAreaRect.height = tabPane.getHeight() - insets.top + - insets.bottom; + tabAreaRect.y = insets.top; + contentRect.width = tabPane.getWidth() - insets.left - insets.right + - tabAreaRect.width; + contentRect.height = tabAreaRect.height; + contentRect.y = insets.top; + if (tabPlacement == SwingConstants.LEFT) + { + tabAreaRect.x = insets.left; + contentRect.x = tabAreaRect.x + tabAreaRect.width; + } + else + { + contentRect.x = insets.left; + tabAreaRect.x = contentRect.x + contentRect.width; + } } runCount = runs; @@ -1047,68 +1046,68 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants int tabCount = tabPane.getTabCount(); Point p = null; if (tabCount == 0) - return; + return; int tabPlacement = tabPane.getTabPlacement(); incrButton.hide(); decrButton.hide(); if (tabPlacement == SwingConstants.TOP || tabPlacement == SwingConstants.BOTTOM) { - if (tabAreaRect.x + tabAreaRect.width < rects[tabCount - 1].x - + rects[tabCount - 1].width) - { - Dimension incrDims = incrButton.getPreferredSize(); - Dimension decrDims = decrButton.getPreferredSize(); - - decrButton.setBounds(tabAreaRect.x + tabAreaRect.width - - incrDims.width - decrDims.width, - tabAreaRect.y, decrDims.width, - tabAreaRect.height); - incrButton.setBounds(tabAreaRect.x + tabAreaRect.width - - incrDims.width, tabAreaRect.y, - decrDims.width, tabAreaRect.height); - - tabAreaRect.width -= decrDims.width + incrDims.width; - incrButton.show(); - decrButton.show(); - } + if (tabAreaRect.x + tabAreaRect.width < rects[tabCount - 1].x + + rects[tabCount - 1].width) + { + Dimension incrDims = incrButton.getPreferredSize(); + Dimension decrDims = decrButton.getPreferredSize(); + + decrButton.setBounds(tabAreaRect.x + tabAreaRect.width + - incrDims.width - decrDims.width, + tabAreaRect.y, decrDims.width, + tabAreaRect.height); + incrButton.setBounds(tabAreaRect.x + tabAreaRect.width + - incrDims.width, tabAreaRect.y, + decrDims.width, tabAreaRect.height); + + tabAreaRect.width -= decrDims.width + incrDims.width; + incrButton.show(); + decrButton.show(); + } } if (tabPlacement == SwingConstants.LEFT || tabPlacement == SwingConstants.RIGHT) { - if (tabAreaRect.y + tabAreaRect.height < rects[tabCount - 1].y - + rects[tabCount - 1].height) - { - Dimension incrDims = incrButton.getPreferredSize(); - Dimension decrDims = decrButton.getPreferredSize(); - - decrButton.setBounds(tabAreaRect.x, - tabAreaRect.y + tabAreaRect.height - - incrDims.height - decrDims.height, - tabAreaRect.width, decrDims.height); - incrButton.setBounds(tabAreaRect.x, - tabAreaRect.y + tabAreaRect.height - - incrDims.height, tabAreaRect.width, - incrDims.height); - - tabAreaRect.height -= decrDims.height + incrDims.height; - incrButton.show(); - decrButton.show(); - } + if (tabAreaRect.y + tabAreaRect.height < rects[tabCount - 1].y + + rects[tabCount - 1].height) + { + Dimension incrDims = incrButton.getPreferredSize(); + Dimension decrDims = decrButton.getPreferredSize(); + + decrButton.setBounds(tabAreaRect.x, + tabAreaRect.y + tabAreaRect.height + - incrDims.height - decrDims.height, + tabAreaRect.width, decrDims.height); + incrButton.setBounds(tabAreaRect.x, + tabAreaRect.y + tabAreaRect.height + - incrDims.height, tabAreaRect.width, + incrDims.height); + + tabAreaRect.height -= decrDims.height + incrDims.height; + incrButton.show(); + decrButton.show(); + } } viewport.setBounds(tabAreaRect.x, tabAreaRect.y, tabAreaRect.width, tabAreaRect.height); int tabC = tabPane.getTabCount() - 1; if (tabCount > 0) { - int w = Math.max(rects[tabC].width + rects[tabC].x, tabAreaRect.width); - int h = Math.max(rects[tabC].height, tabAreaRect.height); - p = findPointForIndex(currentScrollLocation); - - // we want to cover that entire space so that borders that run under - // the tab area don't show up when we move the viewport around. - panel.setSize(w + p.x, h + p.y); + int w = Math.max(rects[tabC].width + rects[tabC].x, tabAreaRect.width); + int h = Math.max(rects[tabC].height, tabAreaRect.height); + p = findPointForIndex(currentScrollLocation); + + // we want to cover that entire space so that borders that run under + // the tab area don't show up when we move the viewport around. + panel.setSize(w + p.x, h + p.y); } viewport.setViewPosition(p); viewport.repaint(); @@ -1160,7 +1159,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants */ public void paint(Graphics g, JComponent c) { - paintTabArea(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex()); + paintTabArea(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex()); } } @@ -1182,6 +1181,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants */ private class ScrollingViewport extends JViewport implements UIResource { + // TODO: Maybe remove this inner class. } /** @@ -1407,22 +1407,22 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants if (tabPlacement == TOP || tabPlacement == BOTTOM) { - if (index > 0) - { - w += rects[index - 1].x + rects[index - 1].width; - if (index > selectedIndex) - w -= insets.left + insets.right; - } + if (index > 0) + { + w += rects[index - 1].x + rects[index - 1].width; + if (index > selectedIndex) + w -= insets.left + insets.right; + } } else { - if (index > 0) - { - h += rects[index - 1].y + rects[index - 1].height; - if (index > selectedIndex) - h -= insets.top + insets.bottom; - } + if (index > 0) + { + h += rects[index - 1].y + rects[index - 1].height; + if (index > selectedIndex) + h -= insets.top + insets.bottom; + } } Point p = new Point(w, h); @@ -1451,16 +1451,16 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants super.installUI(c); if (c instanceof JTabbedPane) { - tabPane = (JTabbedPane) c; - - installComponents(); - installDefaults(); - installListeners(); - installKeyboardActions(); - - layoutManager = createLayoutManager(); - tabPane.setLayout(layoutManager); - tabPane.layout(); + tabPane = (JTabbedPane) c; + + installComponents(); + installDefaults(); + installListeners(); + installKeyboardActions(); + + layoutManager = createLayoutManager(); + tabPane.setLayout(layoutManager); + tabPane.layout(); } } @@ -1495,23 +1495,23 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants return new TabbedPaneLayout(); else { - incrButton = createIncreaseButton(); - decrButton = createDecreaseButton(); - viewport = new ScrollingViewport(); - viewport.setLayout(null); - panel = new ScrollingPanel(); - viewport.setView(panel); - tabPane.add(incrButton); - tabPane.add(decrButton); - tabPane.add(viewport); - currentScrollLocation = 0; - decrButton.setEnabled(false); - panel.addMouseListener(mouseListener); - incrButton.addMouseListener(mouseListener); - decrButton.addMouseListener(mouseListener); - viewport.setBackground(Color.LIGHT_GRAY); - - return new TabbedPaneScrollLayout(); + incrButton = createIncreaseButton(); + decrButton = createDecreaseButton(); + viewport = new ScrollingViewport(); + viewport.setLayout(null); + panel = new ScrollingPanel(); + viewport.setView(panel); + tabPane.add(incrButton); + tabPane.add(decrButton); + tabPane.add(viewport); + currentScrollLocation = 0; + decrButton.setEnabled(false); + panel.addMouseListener(mouseListener); + incrButton.addMouseListener(mouseListener); + decrButton.addMouseListener(mouseListener); + viewport.setBackground(Color.LIGHT_GRAY); + + return new TabbedPaneScrollLayout(); } } @@ -1536,28 +1536,26 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants */ protected void installDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - tabPane.setFont(defaults.getFont("TabbedPane.font")); - tabPane.setForeground(defaults.getColor("TabbedPane.foreground")); - tabPane.setBackground(defaults.getColor("TabbedPane.background")); + LookAndFeel.installColorsAndFont(tabPane, "TabbedPane.background", + "TabbedPane.foreground", + "TabbedPane.font"); tabPane.setOpaque(false); - highlight = defaults.getColor("TabbedPane.highlight"); - lightHighlight = defaults.getColor("TabbedPane.lightHighlight"); + highlight = UIManager.getColor("TabbedPane.highlight"); + lightHighlight = UIManager.getColor("TabbedPane.lightHighlight"); - shadow = defaults.getColor("TabbedPane.shadow"); - darkShadow = defaults.getColor("TabbedPane.darkShadow"); + shadow = UIManager.getColor("TabbedPane.shadow"); + darkShadow = UIManager.getColor("TabbedPane.darkShadow"); - focus = defaults.getColor("TabbedPane.focus"); + focus = UIManager.getColor("TabbedPane.focus"); - textIconGap = defaults.getInt("TabbedPane.textIconGap"); - tabRunOverlay = defaults.getInt("TabbedPane.tabRunOverlay"); + textIconGap = UIManager.getInt("TabbedPane.textIconGap"); + tabRunOverlay = UIManager.getInt("TabbedPane.tabRunOverlay"); - tabInsets = defaults.getInsets("TabbedPane.tabbedPaneTabInsets"); - selectedTabPadInsets = defaults.getInsets("TabbedPane.tabbedPaneTabPadInsets"); - tabAreaInsets = defaults.getInsets("TabbedPane.tabbedPaneTabAreaInsets"); - contentBorderInsets = defaults.getInsets("TabbedPane.tabbedPaneContentBorderInsets"); + tabInsets = UIManager.getInsets("TabbedPane.tabbedPaneTabInsets"); + selectedTabPadInsets = UIManager.getInsets("TabbedPane.tabbedPaneTabPadInsets"); + tabAreaInsets = UIManager.getInsets("TabbedPane.tabbedPaneTabAreaInsets"); + contentBorderInsets = UIManager.getInsets("TabbedPane.tabbedPaneContentBorderInsets"); calcRect = new Rectangle(); tabRuns = new int[10]; @@ -1737,38 +1735,42 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants // we WANT to paint the outermost run first and then work our way in. int tabCount = tabPane.getTabCount(); int currRun = 1; + + if (tabCount > runCount) + runCount = tabCount; + if (tabCount < 1) return; - + if (runCount > 1) - currRun = 0; + currRun = 0; for (int i = 0; i < runCount; i++) { - int first = lastTabInRun(tabCount, getPreviousTabRun(currRun)) + 1; - if (isScroll) - first = currentScrollLocation; - else if (first == tabCount) - first = 0; - int last = lastTabInRun(tabCount, currRun); - if (isScroll) - { - for (int k = first; k < tabCount; k++) - { - if (rects[k].x + rects[k].width - rects[first].x > viewport - .getWidth()) - { - last = k; - break; - } - } - } - - for (int j = first; j <= last; j++) - { - if (j != selectedIndex || isScroll) - paintTab(g, tabPlacement, rects, j, ir, tr); - } - currRun = getPreviousTabRun(currRun); + int first = lastTabInRun(tabCount, getPreviousTabRun(currRun)) + 1; + if (isScroll) + first = currentScrollLocation; + else if (first == tabCount) + first = 0; + int last = lastTabInRun(tabCount, currRun); + if (isScroll) + { + for (int k = first; k < tabCount; k++) + { + if (rects[k].x + rects[k].width - rects[first].x > viewport + .getWidth()) + { + last = k; + break; + } + } + } + + for (int j = first; j <= last; j++) + { + if (j != selectedIndex || isScroll) + paintTab(g, tabPlacement, rects, j, ir, tr); + } + currRun = getPreviousTabRun(currRun); } if (! isScroll) paintTab(g, tabPlacement, rects, selectedIndex, ir, tr); @@ -1800,24 +1802,24 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants int h = calcRect.height; if (getRunForTab(tabPane.getTabCount(), tabIndex) == 1) { - Insets insets = getTabAreaInsets(tabPlacement); - switch (tabPlacement) - { - case TOP: - h += insets.bottom; - break; - case LEFT: - w += insets.right; - break; - case BOTTOM: - y -= insets.top; - h += insets.top; - break; - case RIGHT: - x -= insets.left; - w += insets.left; - break; - } + Insets insets = getTabAreaInsets(tabPlacement); + switch (tabPlacement) + { + case TOP: + h += insets.bottom; + break; + case LEFT: + w += insets.right; + break; + case BOTTOM: + y -= insets.top; + h += insets.top; + break; + case RIGHT: + x -= insets.left; + w += insets.left; + break; + } } layoutLabel(tabPlacement, fm, tabIndex, title, icon, calcRect, iconRect, @@ -1856,7 +1858,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants SwingConstants.CENTER, SwingConstants.CENTER, SwingConstants.CENTER, - SwingConstants.CENTER, tabRect, + SwingConstants.RIGHT, tabRect, iconRect, textRect, textIconGap); int shiftX = getTabLabelShiftX(tabPlacement, tabIndex, isSelected); @@ -1904,8 +1906,8 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants View textView = getTextViewForTab(tabIndex); if (textView != null) { - textView.paint(g, textRect); - return; + textView.paint(g, textRect); + return; } Color fg = tabPane.getForegroundAt(tabIndex); @@ -1921,37 +1923,37 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants if (tabPane.isEnabledAt(tabIndex)) { - g.setColor(fg); + g.setColor(fg); - int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex); + int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex); - if (mnemIndex != -1) - BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, - textRect.x, - textRect.y - + metrics.getAscent()); - else - g.drawString(title, textRect.x, textRect.y + metrics.getAscent()); + if (mnemIndex != -1) + BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, + textRect.x, + textRect.y + + metrics.getAscent()); + else + g.drawString(title, textRect.x, textRect.y + metrics.getAscent()); } else { - g.setColor(bg.brighter()); - - int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex); - - if (mnemIndex != -1) - BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, - textRect.x, textRect.y); - else - g.drawString(title, textRect.x, textRect.y); - - g.setColor(bg.darker()); - if (mnemIndex != -1) - BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, - textRect.x + 1, - textRect.y + 1); - else - g.drawString(title, textRect.x + 1, textRect.y + 1); + g.setColor(bg.brighter()); + + int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex); + + if (mnemIndex != -1) + BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, + textRect.x, textRect.y); + else + g.drawString(title, textRect.x, textRect.y); + + g.setColor(bg.darker()); + if (mnemIndex != -1) + BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, + textRect.x + 1, + textRect.y + 1); + else + g.drawString(title, textRect.x + 1, textRect.y + 1); } g.setColor(saved_color); @@ -2037,30 +2039,30 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants if (! isSelected || tabPlacement != SwingConstants.TOP) { - g.setColor(shadow); - g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1); - g.setColor(darkShadow); - g.drawLine(x, y + h, x + w, y + h); + g.setColor(shadow); + g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1); + g.setColor(darkShadow); + g.drawLine(x, y + h, x + w, y + h); } if (! isSelected || tabPlacement != SwingConstants.LEFT) { - g.setColor(darkShadow); - g.drawLine(x + w, y, x + w, y + h); - g.setColor(shadow); - g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1); + g.setColor(darkShadow); + g.drawLine(x + w, y, x + w, y + h); + g.setColor(shadow); + g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1); } if (! isSelected || tabPlacement != SwingConstants.RIGHT) { - g.setColor(lightHighlight); - g.drawLine(x, y, x, y + h); + g.setColor(lightHighlight); + g.drawLine(x, y, x, y + h); } if (! isSelected || tabPlacement != SwingConstants.BOTTOM) { - g.setColor(lightHighlight); - g.drawLine(x, y, x + w, y); + g.setColor(lightHighlight); + g.drawLine(x, y, x + w, y); } g.setColor(saved); @@ -2087,10 +2089,10 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants g.setColor(Color.LIGHT_GRAY); else { - Color bg = tabPane.getBackgroundAt(tabIndex); - if (bg == null) - bg = Color.GRAY; - g.setColor(bg); + Color bg = tabPane.getBackgroundAt(tabIndex); + if (bg == null) + bg = Color.GRAY; + g.setColor(bg); } g.fillRect(x, y, w, h); @@ -2144,14 +2146,14 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants if (tabPlacement == SwingConstants.TOP) { - if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) - { - Point p = findPointForIndex(currentScrollLocation); - diff = p.x; - } - - g.drawLine(x, y, startgap - diff, y); - g.drawLine(endgap - diff, y, x + w, y); + if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) + { + Point p = findPointForIndex(currentScrollLocation); + diff = p.x; + } + + g.drawLine(x, y, startgap - diff, y); + g.drawLine(endgap - diff, y, x + w, y); } else g.drawLine(x, y, x + w, y); @@ -2184,14 +2186,14 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants if (tabPlacement == SwingConstants.LEFT) { - if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) - { - Point p = findPointForIndex(currentScrollLocation); - diff = p.y; - } - - g.drawLine(x, y, x, startgap - diff); - g.drawLine(x, endgap - diff, x, y + h); + if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) + { + Point p = findPointForIndex(currentScrollLocation); + diff = p.y; + } + + g.drawLine(x, y, x, startgap - diff); + g.drawLine(x, endgap - diff, x, y + h); } else g.drawLine(x, y, x, y + h); @@ -2223,26 +2225,26 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants if (tabPlacement == SwingConstants.BOTTOM) { - if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) - { - Point p = findPointForIndex(currentScrollLocation); - diff = p.x; - } - - g.setColor(shadow); - g.drawLine(x + 1, y + h - 1, startgap - diff, y + h - 1); - g.drawLine(endgap - diff, y + h - 1, x + w - 1, y + h - 1); - - g.setColor(darkShadow); - g.drawLine(x, y + h, startgap - diff, y + h); - g.drawLine(endgap - diff, y + h, x + w, y + h); + if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) + { + Point p = findPointForIndex(currentScrollLocation); + diff = p.x; + } + + g.setColor(shadow); + g.drawLine(x + 1, y + h - 1, startgap - diff, y + h - 1); + g.drawLine(endgap - diff, y + h - 1, x + w - 1, y + h - 1); + + g.setColor(darkShadow); + g.drawLine(x, y + h, startgap - diff, y + h); + g.drawLine(endgap - diff, y + h, x + w, y + h); } else { - g.setColor(shadow); - g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1); - g.setColor(darkShadow); - g.drawLine(x, y + h, x + w, y + h); + g.setColor(shadow); + g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1); + g.setColor(darkShadow); + g.drawLine(x, y + h, x + w, y + h); } g.setColor(saved); @@ -2271,26 +2273,26 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants if (tabPlacement == SwingConstants.RIGHT) { - if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) - { - Point p = findPointForIndex(currentScrollLocation); - diff = p.y; - } - - g.setColor(shadow); - g.drawLine(x + w - 1, y + 1, x + w - 1, startgap - diff); - g.drawLine(x + w - 1, endgap - diff, x + w - 1, y + h - 1); - - g.setColor(darkShadow); - g.drawLine(x + w, y, x + w, startgap - diff); - g.drawLine(x + w, endgap - diff, x + w, y + h); + if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) + { + Point p = findPointForIndex(currentScrollLocation); + diff = p.y; + } + + g.setColor(shadow); + g.drawLine(x + w - 1, y + 1, x + w - 1, startgap - diff); + g.drawLine(x + w - 1, endgap - diff, x + w - 1, y + h - 1); + + g.setColor(darkShadow); + g.drawLine(x + w, y, x + w, startgap - diff); + g.drawLine(x + w, endgap - diff, x + w, y + h); } else { - g.setColor(shadow); - g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1); - g.setColor(darkShadow); - g.drawLine(x + w, y, x + w, y + h); + g.setColor(shadow); + g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1); + g.setColor(darkShadow); + g.drawLine(x + w, y, x + w, y + h); } g.setColor(saved); @@ -2337,16 +2339,16 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants int currRun = 1; for (int i = 0; i < runCount; i++) { - int first = lastTabInRun(tabCount, getPreviousTabRun(currRun)) + 1; - if (first == tabCount) - first = 0; - int last = lastTabInRun(tabCount, currRun); - for (int j = first; j <= last; j++) - { - if (getTabBounds(pane, j).contains(p)) - return j; - } - currRun = getNextTabRun(currRun); + int first = lastTabInRun(tabCount, getPreviousTabRun(currRun)) + 1; + if (first == tabCount) + first = 0; + int last = lastTabInRun(tabCount, currRun); + for (int j = first; j <= last; j++) + { + if (getTabBounds(pane, j).contains(p)) + return j; + } + currRun = getNextTabRun(currRun); } return -1; } @@ -2400,10 +2402,10 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants return; else { - int numToCopy = Math.min(tabCount, rects.length); - Rectangle[] tmp = new Rectangle[tabCount]; - System.arraycopy(rects, 0, tmp, 0, numToCopy); - rects = tmp; + int numToCopy = Math.min(tabCount, rects.length); + Rectangle[] tmp = new Rectangle[tabCount]; + System.arraycopy(rects, 0, tmp, 0, numToCopy); + rects = tmp; } } @@ -2418,9 +2420,9 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants tabRuns = new int[10]; else { - int[] newRuns = new int[tabRuns.length + 10]; - System.arraycopy(tabRuns, 0, newRuns, 0, tabRuns.length); - tabRuns = newRuns; + int[] newRuns = new int[tabRuns.length + 10]; + System.arraycopy(tabRuns, 0, newRuns, 0, tabRuns.length); + tabRuns = newRuns; } } @@ -2438,12 +2440,12 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants return 1; for (int i = 0; i < runCount; i++) { - int first = lastTabInRun(tabCount, getPreviousTabRun(i)) + 1; - if (first == tabCount) - first = 0; - int last = lastTabInRun(tabCount, i); - if (last >= tabIndex && first <= tabIndex) - return i; + int first = lastTabInRun(tabCount, getPreviousTabRun(i)) + 1; + if (first == tabCount) + first = 0; + int last = lastTabInRun(tabCount, i); + if (last >= tabIndex && first <= tabIndex) + return i; } return -1; } @@ -2560,21 +2562,22 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants Icon icon = getIconForTab(tabIndex); Insets insets = getTabInsets(tabPlacement, tabIndex); + int height = 0; if (icon != null) { - Rectangle vr = new Rectangle(); - Rectangle ir = new Rectangle(); - Rectangle tr = new Rectangle(); - layoutLabel(tabPlacement, getFontMetrics(), tabIndex, - tabPane.getTitleAt(tabIndex), icon, vr, ir, tr, - tabIndex == tabPane.getSelectedIndex()); - calcRect = tr.union(ir); + Rectangle vr = new Rectangle(); + Rectangle ir = new Rectangle(); + Rectangle tr = new Rectangle(); + layoutLabel(tabPlacement, getFontMetrics(), tabIndex, + tabPane.getTitleAt(tabIndex), icon, vr, ir, tr, + tabIndex == tabPane.getSelectedIndex()); + height = tr.union(ir).height; } else - calcRect.height = fontHeight; + height = fontHeight; - calcRect.height += insets.top + insets.bottom; - return calcRect.height; + height += insets.top + insets.bottom; + return height; } /** @@ -2614,21 +2617,22 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants Icon icon = getIconForTab(tabIndex); Insets insets = getTabInsets(tabPlacement, tabIndex); + int width = 0; if (icon != null) { - Rectangle vr = new Rectangle(); - Rectangle ir = new Rectangle(); - Rectangle tr = new Rectangle(); - layoutLabel(tabPlacement, getFontMetrics(), tabIndex, - tabPane.getTitleAt(tabIndex), icon, vr, ir, tr, - tabIndex == tabPane.getSelectedIndex()); - calcRect = tr.union(ir); + Rectangle vr = new Rectangle(); + Rectangle ir = new Rectangle(); + Rectangle tr = new Rectangle(); + layoutLabel(tabPlacement, getFontMetrics(), tabIndex, + tabPane.getTitleAt(tabIndex), icon, vr, ir, tr, + tabIndex == tabPane.getSelectedIndex()); + width = tr.union(ir).width; } else - calcRect.width = metrics.stringWidth(tabPane.getTitleAt(tabIndex)); + width = metrics.stringWidth(tabPane.getTitleAt(tabIndex)); - calcRect.width += insets.left + insets.right; - return calcRect.width; + width += insets.left + insets.right; + return width; } /** @@ -2775,37 +2779,37 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants if (tabPlacement == SwingConstants.TOP || tabPlacement == SwingConstants.BOTTOM) { - if (direction == SwingConstants.WEST) - selectPreviousTabInRun(tabPane.getSelectedIndex()); - else if (direction == SwingConstants.EAST) - selectNextTabInRun(tabPane.getSelectedIndex()); - - else - { - int offset = getTabRunOffset(tabPlacement, tabPane.getTabCount(), - tabPane.getSelectedIndex(), - (tabPlacement == SwingConstants.RIGHT) - ? true : false); - selectAdjacentRunTab(tabPlacement, tabPane.getSelectedIndex(), - offset); - } + if (direction == SwingConstants.WEST) + selectPreviousTabInRun(tabPane.getSelectedIndex()); + else if (direction == SwingConstants.EAST) + selectNextTabInRun(tabPane.getSelectedIndex()); + + else + { + int offset = getTabRunOffset(tabPlacement, tabPane.getTabCount(), + tabPane.getSelectedIndex(), + (tabPlacement == SwingConstants.RIGHT) + ? true : false); + selectAdjacentRunTab(tabPlacement, tabPane.getSelectedIndex(), + offset); + } } if (tabPlacement == SwingConstants.LEFT || tabPlacement == SwingConstants.RIGHT) { - if (direction == SwingConstants.NORTH) - selectPreviousTabInRun(tabPane.getSelectedIndex()); - else if (direction == SwingConstants.SOUTH) - selectNextTabInRun(tabPane.getSelectedIndex()); - else - { - int offset = getTabRunOffset(tabPlacement, tabPane.getTabCount(), - tabPane.getSelectedIndex(), - (tabPlacement == SwingConstants.RIGHT) - ? true : false); - selectAdjacentRunTab(tabPlacement, tabPane.getSelectedIndex(), - offset); - } + if (direction == SwingConstants.NORTH) + selectPreviousTabInRun(tabPane.getSelectedIndex()); + else if (direction == SwingConstants.SOUTH) + selectNextTabInRun(tabPane.getSelectedIndex()); + else + { + int offset = getTabRunOffset(tabPlacement, tabPane.getTabCount(), + tabPane.getSelectedIndex(), + (tabPlacement == SwingConstants.RIGHT) + ? true : false); + selectAdjacentRunTab(tabPlacement, tabPane.getSelectedIndex(), + offset); + } } } @@ -2869,16 +2873,16 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants int y = rects[tabIndex].y + rects[tabIndex].height / 2; switch (tabPlacement) - { - case SwingConstants.TOP: - case SwingConstants.BOTTOM: - y += offset; - break; - case SwingConstants.RIGHT: - case SwingConstants.LEFT: - x += offset; - break; - } + { + case SwingConstants.TOP: + case SwingConstants.BOTTOM: + y += offset; + break; + case SwingConstants.RIGHT: + case SwingConstants.LEFT: + x += offset; + break; + } int index = tabForCoordinate(tabPane, x, y); if (index != -1) @@ -3042,31 +3046,31 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants // Sun's version will happily throw an NPE if params are null, // so I won't check it either. switch (targetPlacement) - { - case SwingConstants.TOP: - targetInsets.top = topInsets.top; - targetInsets.left = topInsets.left; - targetInsets.right = topInsets.right; - targetInsets.bottom = topInsets.bottom; - break; - case SwingConstants.LEFT: - targetInsets.left = topInsets.top; - targetInsets.top = topInsets.left; - targetInsets.right = topInsets.bottom; - targetInsets.bottom = topInsets.right; - break; - case SwingConstants.BOTTOM: - targetInsets.top = topInsets.bottom; - targetInsets.bottom = topInsets.top; - targetInsets.left = topInsets.left; - targetInsets.right = topInsets.right; - break; - case SwingConstants.RIGHT: - targetInsets.top = topInsets.left; - targetInsets.left = topInsets.bottom; - targetInsets.bottom = topInsets.right; - targetInsets.right = topInsets.top; - break; - } + { + case SwingConstants.TOP: + targetInsets.top = topInsets.top; + targetInsets.left = topInsets.left; + targetInsets.right = topInsets.right; + targetInsets.bottom = topInsets.bottom; + break; + case SwingConstants.LEFT: + targetInsets.left = topInsets.top; + targetInsets.top = topInsets.left; + targetInsets.right = topInsets.bottom; + targetInsets.bottom = topInsets.right; + break; + case SwingConstants.BOTTOM: + targetInsets.top = topInsets.bottom; + targetInsets.bottom = topInsets.top; + targetInsets.left = topInsets.left; + targetInsets.right = topInsets.right; + break; + case SwingConstants.RIGHT: + targetInsets.top = topInsets.left; + targetInsets.left = topInsets.bottom; + targetInsets.bottom = topInsets.right; + targetInsets.right = topInsets.top; + break; + } } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java index 700b406d076..ec0467a74f3 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java @@ -46,7 +46,7 @@ import java.awt.event.MouseEvent; import javax.swing.CellRendererPane; import javax.swing.JComponent; -import javax.swing.UIDefaults; +import javax.swing.LookAndFeel; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.event.MouseInputListener; @@ -57,8 +57,7 @@ import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; -public class BasicTableHeaderUI - extends TableHeaderUI +public class BasicTableHeaderUI extends TableHeaderUI { public static ComponentUI createUI(JComponent h) @@ -71,16 +70,42 @@ public class BasicTableHeaderUI protected CellRendererPane rendererPane; protected Border cellBorder; - class MouseInputHandler - implements MouseInputListener + public class MouseInputHandler implements MouseInputListener { - public void mouseClicked(MouseEvent e) {} - public void mouseDragged(MouseEvent e) {} - public void mouseEntered(MouseEvent e) {} - public void mouseExited(MouseEvent e) {} - public void mouseMoved(MouseEvent e) {} - public void mousePressed(MouseEvent e) {} - public void mouseReleased(MouseEvent e) {} + public void mouseClicked(MouseEvent e) + { + // TODO: Implement this properly. + } + + public void mouseDragged(MouseEvent e) + { + // TODO: Implement this properly. + } + + public void mouseEntered(MouseEvent e) + { + // TODO: Implement this properly. + } + + public void mouseExited(MouseEvent e) + { + // TODO: Implement this properly. + } + + public void mouseMoved(MouseEvent e) + { + // TODO: Implement this properly. + } + + public void mousePressed(MouseEvent e) + { + // TODO: Implement this properly. + } + + public void mouseReleased(MouseEvent e) + { + // TODO: Implement this properly. + } } protected MouseInputListener createMouseInputListener() @@ -95,15 +120,15 @@ public class BasicTableHeaderUI protected void installDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - header.setBackground(defaults.getColor("TableHeader.background")); - header.setForeground(defaults.getColor("TableHeader.foreground")); - header.setFont(defaults.getFont("TableHeader.font")); - cellBorder = defaults.getBorder("TableHeader.cellBorder"); + LookAndFeel.installColorsAndFont(header, "TableHeader.background", + "TableHeader.foreground", + "TableHeader.font"); + cellBorder = UIManager.getBorder("TableHeader.cellBorder"); } protected void installKeyboardActions() { + // TODO: Implement this properly. } protected void installListeners() @@ -128,6 +153,7 @@ public class BasicTableHeaderUI protected void uninstallKeyboardActions() { + // TODO: Implement this properly. } protected void uninstallListeners() @@ -157,6 +183,7 @@ public class BasicTableHeaderUI Rectangle bounds = header.getHeaderRect(i); if (bounds.intersects(clip)) { + Rectangle oldClip = gfx.getClipBounds(); TableColumn col = cmod.getColumn(i); TableCellRenderer rend = col.getHeaderRenderer(); if (rend == null) @@ -173,10 +200,12 @@ public class BasicTableHeaderUI if (comp instanceof JComponent) ((JComponent)comp).setBorder(cellBorder); gfx.translate(bounds.x, bounds.y); + gfx.setClip(0, 0, bounds.width, bounds.height); comp.setSize(bounds.width, bounds.height); comp.setLocation(0,0); comp.paint(gfx); gfx.translate(-bounds.x, -bounds.y); + gfx.setClip(oldClip); } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java index 4559937eb69..25a845b36b8 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java @@ -49,35 +49,38 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; -import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import javax.swing.AbstractAction; import javax.swing.ActionMap; -import javax.swing.BorderFactory; import javax.swing.CellRendererPane; +import javax.swing.DefaultListSelectionModel; import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.ListSelectionModel; +import javax.swing.LookAndFeel; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.event.ChangeEvent; import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ActionMapUIResource; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.InputMapUIResource; import javax.swing.plaf.TableUI; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; +import javax.swing.table.TableModel; -public class BasicTableUI - extends TableUI +public class BasicTableUI extends TableUI { public static ComponentUI createUI(JComponent comp) { @@ -93,23 +96,72 @@ public class BasicTableUI /** The normal cell border. */ Border cellBorder; - /** The cell border for selected/highlighted cells. */ - Border highlightCellBorder; - /** The action bound to KeyStrokes. */ TableAction action; - class FocusHandler implements FocusListener + /** + * Listens for changes to the tables properties. + */ + private PropertyChangeListener propertyChangeListener; + + /** + * Handles key events for the JTable. Key events should be handled through + * the InputMap/ActionMap mechanism since JDK1.3. This class is only there + * for backwards compatibility. + * + * @author Roman Kennke (kennke@aicas.com) + */ + public class KeyHandler implements KeyListener + { + + /** + * Receives notification that a key has been pressed and released. + * + * @param event the key event + */ + public void keyTyped(KeyEvent event) + { + // Key events should be handled through the InputMap/ActionMap mechanism + // since JDK1.3. This class is only there for backwards compatibility. + } + + /** + * Receives notification that a key has been pressed. + * + * @param event the key event + */ + public void keyPressed(KeyEvent event) + { + // Key events should be handled through the InputMap/ActionMap mechanism + // since JDK1.3. This class is only there for backwards compatibility. + } + + /** + * Receives notification that a key has been released. + * + * @param event the key event + */ + public void keyReleased(KeyEvent event) + { + // Key events should be handled through the InputMap/ActionMap mechanism + // since JDK1.3. This class is only there for backwards compatibility. + } + } + + public class FocusHandler implements FocusListener { public void focusGained(FocusEvent e) { + // TODO: Implement this properly. } + public void focusLost(FocusEvent e) { + // TODO: Implement this properly. } } - class MouseInputHandler implements MouseInputListener + public class MouseInputHandler implements MouseInputListener { Point begin, curr; @@ -145,54 +197,123 @@ public class BasicTableUI public void mouseClicked(MouseEvent e) { + // TODO: What should be done here, if anything? } + public void mouseDragged(MouseEvent e) { - curr = new Point(e.getX(), e.getY()); - updateSelection(e.isControlDown()); + if (table.isEnabled()) + { + curr = new Point(e.getX(), e.getY()); + updateSelection(e.isControlDown()); + } } + public void mouseEntered(MouseEvent e) { + // TODO: What should be done here, if anything? } + public void mouseExited(MouseEvent e) { + // TODO: What should be done here, if anything? } + public void mouseMoved(MouseEvent e) { + // TODO: What should be done here, if anything? } + public void mousePressed(MouseEvent e) { - ListSelectionModel rowModel = table.getSelectionModel(); - ListSelectionModel colModel = table.getColumnModel().getSelectionModel(); - int rowLead = rowModel.getLeadSelectionIndex(); - int colLead = colModel.getLeadSelectionIndex(); + if (table.isEnabled()) + { + ListSelectionModel rowModel = table.getSelectionModel(); + ListSelectionModel colModel = table.getColumnModel().getSelectionModel(); + int rowLead = rowModel.getLeadSelectionIndex(); + int colLead = colModel.getLeadSelectionIndex(); - begin = new Point(e.getX(), e.getY()); - curr = new Point(e.getX(), e.getY()); - //if control is pressed and the cell is already selected, deselect it - if (e.isControlDown() && table. - isCellSelected(table.rowAtPoint(begin),table.columnAtPoint(begin))) - { - table.getSelectionModel(). - removeSelectionInterval(table.rowAtPoint(begin), - table.rowAtPoint(begin)); - table.getColumnModel().getSelectionModel(). - removeSelectionInterval(table.columnAtPoint(begin), - table.columnAtPoint(begin)); - } - else - updateSelection(e.isControlDown()); + begin = new Point(e.getX(), e.getY()); + curr = new Point(e.getX(), e.getY()); + //if control is pressed and the cell is already selected, deselect it + if (e.isControlDown() && table. + isCellSelected(table.rowAtPoint(begin),table.columnAtPoint(begin))) + { + table.getSelectionModel(). + removeSelectionInterval(table.rowAtPoint(begin), + table.rowAtPoint(begin)); + table.getColumnModel().getSelectionModel(). + removeSelectionInterval(table.columnAtPoint(begin), + table.columnAtPoint(begin)); + } + else + updateSelection(e.isControlDown()); - // If we were editing, but the moved to another cell, stop editing - if (rowLead != rowModel.getLeadSelectionIndex() || - colLead != colModel.getLeadSelectionIndex()) - if (table.isEditing()) - table.editingStopped(new ChangeEvent(e)); + // If we were editing, but the moved to another cell, stop editing + if (rowLead != rowModel.getLeadSelectionIndex() || + colLead != colModel.getLeadSelectionIndex()) + if (table.isEditing()) + table.editingStopped(new ChangeEvent(e)); + } } + public void mouseReleased(MouseEvent e) { - begin = null; - curr = null; + if (table.isEnabled()) + { + begin = null; + curr = null; + } + } + } + + /** + * Listens for changes to the model property of the JTable and adjusts some + * settings. + * + * @author Roman Kennke (kennke@aicas.com) + */ + private class PropertyChangeHandler implements PropertyChangeListener + { + /** + * Receives notification if one of the JTable's properties changes. + * + * @param ev the property change event + */ + public void propertyChange(PropertyChangeEvent ev) + { + String propName = ev.getPropertyName(); + if (propName.equals("model")) + { + ListSelectionModel rowSel = table.getSelectionModel(); + rowSel.clearSelection(); + ListSelectionModel colSel = table.getColumnModel().getSelectionModel(); + colSel.clearSelection(); + TableModel model = table.getModel(); + + // Adjust lead and anchor selection indices of the row and column + // selection models. + if (model.getRowCount() > 0) + { + rowSel.setAnchorSelectionIndex(0); + rowSel.setLeadSelectionIndex(0); + } + else + { + rowSel.setAnchorSelectionIndex(-1); + rowSel.setLeadSelectionIndex(-1); + } + if (model.getColumnCount() > 0) + { + colSel.setAnchorSelectionIndex(0); + colSel.setLeadSelectionIndex(0); + } + else + { + colSel.setAnchorSelectionIndex(-1); + colSel.setLeadSelectionIndex(-1); + } + } } } @@ -206,6 +327,17 @@ public class BasicTableUI return new MouseInputHandler(); } + + /** + * Creates and returns a key listener for the JTable. + * + * @return a key listener for the JTable + */ + protected KeyListener createKeyListener() + { + return new KeyHandler(); + } + /** * Return the maximum size of the table. The maximum height is the row * height times the number of rows. The maximum width is the sum of @@ -255,47 +387,13 @@ public class BasicTableUI protected void installDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - table.setFont(defaults.getFont("Table.font")); - table.setGridColor(defaults.getColor("Table.gridColor")); - table.setForeground(defaults.getColor("Table.foreground")); - table.setBackground(defaults.getColor("Table.background")); - table.setSelectionForeground(defaults.getColor("Table.selectionForeground")); - table.setSelectionBackground(defaults.getColor("Table.selectionBackground")); + LookAndFeel.installColorsAndFont(table, "Table.background", + "Table.foreground", "Table.font"); + table.setGridColor(UIManager.getColor("Table.gridColor")); + table.setSelectionForeground(UIManager.getColor("Table.selectionForeground")); + table.setSelectionBackground(UIManager.getColor("Table.selectionBackground")); table.setOpaque(true); - - highlightCellBorder = defaults.getBorder("Table.focusCellHighlightBorder"); - cellBorder = BorderFactory.createEmptyBorder(1, 1, 1, 1); - } - - private int convertModifiers(int mod) - { - if ((mod & KeyEvent.SHIFT_DOWN_MASK) != 0) - { - mod |= KeyEvent.SHIFT_MASK; - mod &= ~KeyEvent.SHIFT_DOWN_MASK; - } - if ((mod & KeyEvent.CTRL_DOWN_MASK) != 0) - { - mod |= KeyEvent.CTRL_MASK; - mod &= ~KeyEvent.CTRL_DOWN_MASK; - } - if ((mod & KeyEvent.META_DOWN_MASK) != 0) - { - mod |= KeyEvent.META_MASK; - mod &= ~KeyEvent.META_DOWN_MASK; - } - if ((mod & KeyEvent.ALT_DOWN_MASK) != 0) - { - mod |= KeyEvent.ALT_MASK; - mod &= ~KeyEvent.ALT_DOWN_MASK; - } - if ((mod & KeyEvent.ALT_GRAPH_DOWN_MASK) != 0) - { - mod |= KeyEvent.ALT_GRAPH_MASK; - mod &= ~KeyEvent.ALT_GRAPH_DOWN_MASK; - } - return mod; + rendererPane = new CellRendererPane(); } protected void installKeyboardActions() @@ -304,27 +402,21 @@ public class BasicTableUI InputMap ancestorMap = (InputMap)defaults.get("Table.ancestorInputMap"); InputMapUIResource parentInputMap = new InputMapUIResource(); // FIXME: The JDK uses a LazyActionMap for parentActionMap - ActionMap parentActionMap = new ActionMap(); + ActionMap parentActionMap = new ActionMapUIResource(); action = new TableAction(); Object keys[] = ancestorMap.allKeys(); // Register key bindings in the UI InputMap-ActionMap pair - // Note that we register key bindings with both the old and new modifier - // masks: InputEvent.SHIFT_MASK and InputEvent.SHIFT_DOWN_MASK and so on. for (int i = 0; i < keys.length; i++) { - parentInputMap.put(KeyStroke.getKeyStroke - (((KeyStroke)keys[i]).getKeyCode(), convertModifiers - (((KeyStroke)keys[i]).getModifiers())), - (String)ancestorMap.get((KeyStroke)keys[i])); + KeyStroke stroke = (KeyStroke)keys[i]; + String actionString = (String) ancestorMap.get(stroke); - parentInputMap.put(KeyStroke.getKeyStroke - (((KeyStroke)keys[i]).getKeyCode(), - ((KeyStroke)keys[i]).getModifiers()), - (String)ancestorMap.get((KeyStroke)keys[i])); + parentInputMap.put(KeyStroke.getKeyStroke(stroke.getKeyCode(), + stroke.getModifiers()), + actionString); - parentActionMap.put - ((String)ancestorMap.get((KeyStroke)keys[i]), new ActionListenerProxy - (action, (String)ancestorMap.get((KeyStroke)keys[i]))); + parentActionMap.put (actionString, + new ActionListenerProxy (action, actionString)); } // Set the UI InputMap-ActionMap pair to be the parents of the @@ -383,8 +475,8 @@ public class BasicTableUI */ public void actionPerformed (ActionEvent e) { - ListSelectionModel rowModel = table.getSelectionModel(); - ListSelectionModel colModel = table.getColumnModel().getSelectionModel(); + DefaultListSelectionModel rowModel = (DefaultListSelectionModel) table.getSelectionModel(); + DefaultListSelectionModel colModel = (DefaultListSelectionModel) table.getColumnModel().getSelectionModel(); int rowLead = rowModel.getLeadSelectionIndex(); int rowMax = table.getModel().getRowCount() - 1; @@ -392,74 +484,75 @@ public class BasicTableUI int colLead = colModel.getLeadSelectionIndex(); int colMax = table.getModel().getColumnCount() - 1; - if (e.getActionCommand().equals("selectPreviousRowExtendSelection")) + String command = e.getActionCommand(); + + if (command.equals("selectPreviousRowExtendSelection")) { rowModel.setLeadSelectionIndex(Math.max(rowLead - 1, 0)); colModel.setLeadSelectionIndex(colLead); } - else if (e.getActionCommand().equals("selectLastColumn")) + else if (command.equals("selectLastColumn")) { - table.clearSelection(); rowModel.setSelectionInterval(rowLead, rowLead); colModel.setSelectionInterval(colMax, colMax); } - else if (e.getActionCommand().equals("startEditing")) + else if (command.equals("startEditing")) { if (table.isCellEditable(rowLead, colLead)) table.editCellAt(rowLead,colLead); } - else if (e.getActionCommand().equals("selectFirstRowExtendSelection")) + else if (command.equals("selectFirstRowExtendSelection")) { rowModel.setLeadSelectionIndex(0); colModel.setLeadSelectionIndex(colLead); } - else if (e.getActionCommand().equals("selectFirstColumn")) + else if (command.equals("selectFirstColumn")) { rowModel.setSelectionInterval(rowLead, rowLead); colModel.setSelectionInterval(0, 0); } - else if (e.getActionCommand().equals("selectFirstColumnExtendSelection")) + else if (command.equals("selectFirstColumnExtendSelection")) { colModel.setLeadSelectionIndex(0); rowModel.setLeadSelectionIndex(rowLead); - } - else if (e.getActionCommand().equals("selectLastRow")) + } + else if (command.equals("selectLastRow")) { rowModel.setSelectionInterval(rowMax,rowMax); colModel.setSelectionInterval(colLead, colLead); } - else if (e.getActionCommand().equals("selectNextRowExtendSelection")) + else if (command.equals("selectNextRowExtendSelection")) { rowModel.setLeadSelectionIndex(Math.min(rowLead + 1, rowMax)); colModel.setLeadSelectionIndex(colLead); } - else if (e.getActionCommand().equals("selectFirstRow")) + else if (command.equals("selectFirstRow")) { rowModel.setSelectionInterval(0,0); colModel.setSelectionInterval(colLead, colLead); } - else if (e.getActionCommand().equals("selectNextColumnExtendSelection")) + else if (command.equals("selectNextColumnExtendSelection")) { colModel.setLeadSelectionIndex(Math.min(colLead + 1, colMax)); rowModel.setLeadSelectionIndex(rowLead); } - else if (e.getActionCommand().equals("selectLastColumnExtendSelection")) + else if (command.equals("selectLastColumnExtendSelection")) { colModel.setLeadSelectionIndex(colMax); rowModel.setLeadSelectionIndex(rowLead); } - else if (e.getActionCommand().equals("selectPreviousColumnExtendSelection")) + else if (command.equals("selectPreviousColumnExtendSelection")) { colModel.setLeadSelectionIndex(Math.max(colLead - 1, 0)); rowModel.setLeadSelectionIndex(rowLead); } - else if (e.getActionCommand().equals("selectNextRow")) + else if (command.equals("selectNextRow")) { rowModel.setSelectionInterval(Math.min(rowLead + 1, rowMax), Math.min(rowLead + 1, rowMax)); colModel.setSelectionInterval(colLead,colLead); } - else if (e.getActionCommand().equals("scrollUpExtendSelection")) + else if (command.equals("scrollUpExtendSelection")) { int target; if (rowLead == getFirstVisibleRowIndex()) @@ -472,13 +565,13 @@ public class BasicTableUI rowModel.setLeadSelectionIndex(target); colModel.setLeadSelectionIndex(colLead); } - else if (e.getActionCommand().equals("selectPreviousRow")) + else if (command.equals("selectPreviousRow")) { rowModel.setSelectionInterval(Math.max(rowLead - 1, 0), Math.max(rowLead - 1, 0)); colModel.setSelectionInterval(colLead,colLead); } - else if (e.getActionCommand().equals("scrollRightChangeSelection")) + else if (command.equals("scrollRightChangeSelection")) { int target; if (colLead == getLastVisibleColumnIndex()) @@ -491,13 +584,13 @@ public class BasicTableUI colModel.setSelectionInterval(target, target); rowModel.setSelectionInterval(rowLead, rowLead); } - else if (e.getActionCommand().equals("selectPreviousColumn")) + else if (command.equals("selectPreviousColumn")) { rowModel.setSelectionInterval(rowLead,rowLead); colModel.setSelectionInterval(Math.max(colLead - 1, 0), Math.max(colLead - 1, 0)); } - else if (e.getActionCommand().equals("scrollLeftChangeSelection")) + else if (command.equals("scrollLeftChangeSelection")) { int target; if (colLead == getFirstVisibleColumnIndex()) @@ -510,11 +603,11 @@ public class BasicTableUI colModel.setSelectionInterval(target, target); rowModel.setSelectionInterval(rowLead, rowLead); } - else if (e.getActionCommand().equals("clearSelection")) + else if (command.equals("clearSelection")) { table.clearSelection(); } - else if (e.getActionCommand().equals("cancel")) + else if (command.equals("cancel")) { // FIXME: implement other parts of "cancel" like undo-ing last // selection. Right now it just calls editingCancelled if @@ -522,10 +615,10 @@ public class BasicTableUI if (table.isEditing()) table.editingCanceled(new ChangeEvent("cancel")); } - else if (e.getActionCommand().equals("selectNextRowCell") - || e.getActionCommand().equals("selectPreviousRowCell") - || e.getActionCommand().equals("selectNextColumnCell") - || e.getActionCommand().equals("selectPreviousColumnCell")) + else if (command.equals("selectNextRowCell") + || command.equals("selectPreviousRowCell") + || command.equals("selectNextColumnCell") + || command.equals("selectPreviousColumnCell")) { // If nothing is selected, select the first cell in the table if (table.getSelectedRowCount() == 0 && @@ -561,13 +654,13 @@ public class BasicTableUI // when you get to the edges of the table. if (!multColsSelected && !multRowsSelected) { - if (e.getActionCommand().indexOf("Column") != -1) + if (command.indexOf("Column") != -1) advanceSingleSelection(colModel, colMax, rowModel, rowMax, - (e.getActionCommand().equals + (command.equals ("selectPreviousColumnCell"))); else advanceSingleSelection(rowModel, rowMax, colModel, colMax, - (e.getActionCommand().equals + (command.equals ("selectPreviousRowCell"))); return; } @@ -588,25 +681,25 @@ public class BasicTableUI // If there are multiple rows and columns selected, select the next // cell and wrap at the edges of the selection. - if (e.getActionCommand().indexOf("Column") != -1) + if (command.indexOf("Column") != -1) advanceMultipleSelection(colModel, colMinSelected, colMaxSelected, rowModel, rowMinSelected, rowMaxSelected, - (e.getActionCommand().equals + (command.equals ("selectPreviousColumnCell")), true); else advanceMultipleSelection(rowModel, rowMinSelected, rowMaxSelected, colModel, colMinSelected, colMaxSelected, - (e.getActionCommand().equals + (command.equals ("selectPreviousRowCell")), false); } - else if (e.getActionCommand().equals("selectNextColumn")) + else if (command.equals("selectNextColumn")) { rowModel.setSelectionInterval(rowLead,rowLead); colModel.setSelectionInterval(Math.min(colLead + 1, colMax), Math.min(colLead + 1, colMax)); } - else if (e.getActionCommand().equals("scrollLeftExtendSelection")) + else if (command.equals("scrollLeftExtendSelection")) { int target; if (colLead == getFirstVisibleColumnIndex()) @@ -619,7 +712,7 @@ public class BasicTableUI colModel.setLeadSelectionIndex(target); rowModel.setLeadSelectionIndex(rowLead); } - else if (e.getActionCommand().equals("scrollDownChangeSelection")) + else if (command.equals("scrollDownChangeSelection")) { int target; if (rowLead == getLastVisibleRowIndex()) @@ -632,7 +725,7 @@ public class BasicTableUI rowModel.setSelectionInterval(target, target); colModel.setSelectionInterval(colLead, colLead); } - else if (e.getActionCommand().equals("scrollRightExtendSelection")) + else if (command.equals("scrollRightExtendSelection")) { int target; if (colLead == getLastVisibleColumnIndex()) @@ -645,16 +738,16 @@ public class BasicTableUI colModel.setLeadSelectionIndex(target); rowModel.setLeadSelectionIndex(rowLead); } - else if (e.getActionCommand().equals("selectAll")) + else if (command.equals("selectAll")) { table.selectAll(); } - else if (e.getActionCommand().equals("selectLastRowExtendSelection")) + else if (command.equals("selectLastRowExtendSelection")) { rowModel.setLeadSelectionIndex(rowMax); colModel.setLeadSelectionIndex(colLead); } - else if (e.getActionCommand().equals("scrollDownExtendSelection")) + else if (command.equals("scrollDownExtendSelection")) { int target; if (rowLead == getLastVisibleRowIndex()) @@ -666,8 +759,8 @@ public class BasicTableUI rowModel.setLeadSelectionIndex(target); colModel.setLeadSelectionIndex(colLead); - } - else if (e.getActionCommand().equals("scrollUpChangeSelection")) + } + else if (command.equals("scrollUpChangeSelection")) { int target; if (rowLead == getFirstVisibleRowIndex()) @@ -680,22 +773,119 @@ public class BasicTableUI rowModel.setSelectionInterval(target, target); colModel.setSelectionInterval(colLead, colLead); } + else if (command.equals("selectNextRowChangeLead")) + { + if (rowModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) + { + // just "selectNextRow" + rowModel.setSelectionInterval(Math.min(rowLead + 1, rowMax), + Math.min(rowLead + 1, rowMax)); + colModel.setSelectionInterval(colLead,colLead); + } + else + rowModel.moveLeadSelectionIndex(Math.min(rowLead + 1, rowMax)); + } + else if (command.equals("selectPreviousRowChangeLead")) + { + if (rowModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) + { + // just selectPreviousRow + rowModel.setSelectionInterval(Math.max(rowLead - 1, 0), + Math.min(rowLead -1, 0)); + colModel.setSelectionInterval(colLead,colLead); + } + else + rowModel.moveLeadSelectionIndex(Math.max(rowLead - 1, 0)); + } + else if (command.equals("selectNextColumnChangeLead")) + { + if (colModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) + { + // just selectNextColumn + rowModel.setSelectionInterval(rowLead,rowLead); + colModel.setSelectionInterval(Math.min(colLead + 1, colMax), + Math.min(colLead + 1, colMax)); + } + else + colModel.moveLeadSelectionIndex(Math.min(colLead + 1, colMax)); + } + else if (command.equals("selectPreviousColumnChangeLead")) + { + if (colModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) + { + // just selectPreviousColumn + rowModel.setSelectionInterval(rowLead,rowLead); + colModel.setSelectionInterval(Math.max(colLead - 1, 0), + Math.max(colLead - 1, 0)); + + } + else + colModel.moveLeadSelectionIndex(Math.max(colLead - 1, 0)); + } + else if (command.equals("addToSelection")) + { + if (!table.isEditing()) + { + int oldRowAnchor = rowModel.getAnchorSelectionIndex(); + int oldColAnchor = colModel.getAnchorSelectionIndex(); + rowModel.addSelectionInterval(rowLead, rowLead); + colModel.addSelectionInterval(colLead, colLead); + rowModel.setAnchorSelectionIndex(oldRowAnchor); + colModel.setAnchorSelectionIndex(oldColAnchor); + } + } + else if (command.equals("extendTo")) + { + rowModel.setSelectionInterval(rowModel.getAnchorSelectionIndex(), + rowLead); + colModel.setSelectionInterval(colModel.getAnchorSelectionIndex(), + colLead); + } + else if (command.equals("toggleAndAnchor")) + { + if (rowModel.isSelectedIndex(rowLead)) + rowModel.removeSelectionInterval(rowLead, rowLead); + else + rowModel.addSelectionInterval(rowLead, rowLead); + + if (colModel.isSelectedIndex(colLead)) + colModel.removeSelectionInterval(colLead, colLead); + else + colModel.addSelectionInterval(colLead, colLead); + + rowModel.setAnchorSelectionIndex(rowLead); + colModel.setAnchorSelectionIndex(colLead); + } else { // If we're here that means we bound this TableAction class // to a keyboard input but we either want to ignore that input // or we just haven't implemented its action yet. + + // Uncomment the following line to print the names of unused bindings + // when their keys are pressed + + // System.out.println ("not implemented: "+e.getActionCommand()); } - if (table.isEditing() && e.getActionCommand() != "startEditing") - table.editingCanceled(new ChangeEvent("update")); - table.repaint(); - + // Any commands whose keyStrokes should be used by the Editor should not + // cause editing to be stopped: ie, the SPACE sends "addToSelection" but + // if the table is in editing mode, the space should not cause us to stop + // editing because it should be used by the Editor. + if (table.isEditing() && command != "startEditing" + && command != "addToSelection") + table.editingStopped(new ChangeEvent("update")); + table.scrollRectToVisible (table.getCellRect(rowModel.getLeadSelectionIndex(), colModel.getLeadSelectionIndex(), false)); + table.repaint(); } + /** + * Returns the column index of the first visible column. + * @return the column index of the first visible column. + */ int getFirstVisibleColumnIndex() { ComponentOrientation or = table.getComponentOrientation(); @@ -922,10 +1112,19 @@ public class BasicTableUI protected void installListeners() { - table.addFocusListener(focusListener); + if (focusListener == null) + focusListener = createFocusListener(); + table.addFocusListener(focusListener); + if (keyListener == null) + keyListener = createKeyListener(); table.addKeyListener(keyListener); + if (mouseInputListener == null) + mouseInputListener = createMouseInputListener(); table.addMouseListener(mouseInputListener); table.addMouseMotionListener(mouseInputListener); + if (propertyChangeListener == null) + propertyChangeListener = new PropertyChangeHandler(); + table.addPropertyChangeListener(propertyChangeListener); } protected void uninstallDefaults() @@ -950,6 +1149,7 @@ public class BasicTableUI protected void uninstallKeyboardActions() { + // TODO: Implement this properly. } protected void uninstallListeners() @@ -958,13 +1158,13 @@ public class BasicTableUI table.removeKeyListener(keyListener); table.removeMouseListener(mouseInputListener); table.removeMouseMotionListener(mouseInputListener); + table.removePropertyChangeListener(propertyChangeListener); + propertyChangeListener = null; } public void installUI(JComponent comp) { table = (JTable)comp; - focusListener = createFocusListener(); - mouseInputListener = createMouseInputListener(); installDefaults(); installKeyboardActions(); installListeners(); @@ -977,6 +1177,60 @@ public class BasicTableUI uninstallDefaults(); } + /** + * Paints a single cell in the table. + * + * @param g The graphics context to paint in + * @param row The row number to paint + * @param col The column number to paint + * @param bounds The bounds of the cell to paint, assuming a coordinate + * system beginning at <code>(0,0)</code> in the upper left corner of the + * table + * @param rend A cell renderer to paint with + * @param data The data to provide to the cell renderer + * @param rowLead The lead selection for the rows of the table. + * @param colLead The lead selection for the columns of the table. + */ + void paintCell(Graphics g, int row, int col, Rectangle bounds, + TableCellRenderer rend, TableModel data, + int rowLead, int colLead) + { + boolean rowSelAllowed = table.getRowSelectionAllowed(); + boolean colSelAllowed = table.getColumnSelectionAllowed(); + boolean isSel = false; + if (rowSelAllowed && colSelAllowed || !rowSelAllowed && !colSelAllowed) + isSel = table.isCellSelected(row, col); + else + isSel = table.isRowSelected(row) && table.getRowSelectionAllowed() + || table.isColumnSelected(col) && table.getColumnSelectionAllowed(); + + // Determine the focused cell. The focused cell is the cell at the + // leadSelectionIndices of the row and column selection model. + ListSelectionModel rowSel = table.getSelectionModel(); + ListSelectionModel colSel = table.getColumnModel().getSelectionModel(); + boolean hasFocus = table.hasFocus() && table.isEnabled() + && rowSel.getLeadSelectionIndex() == row + && colSel.getLeadSelectionIndex() == col; + + Component comp = rend.getTableCellRendererComponent(table, + data.getValueAt(row, col), + isSel, hasFocus, row, col); + + rendererPane.paintComponent(g, comp, table, bounds); + + // FIXME: this is manual painting of the Caret, why doesn't the + // JTextField take care of this itself? + if (comp instanceof JTextField) + { + Rectangle oldClip = g.getClipBounds(); + g.translate(bounds.x, bounds.y); + g.clipRect(0, 0, bounds.width, bounds.height); + ((JTextField)comp).getCaret().paint(g); + g.translate(-bounds.x, -bounds.y); + g.setClip(oldClip); + } + } + public void paint(Graphics gfx, JComponent ignored) { int ncols = table.getColumnCount(); @@ -1002,40 +1256,24 @@ public class BasicTableUI y = y0; TableColumn col = cols.getColumn(c); int width = col.getWidth(); - int modelCol = col.getModelIndex(); - + int halfGapWidth = gap.width / 2; + int halfGapHeight = gap.height / 2; for (int r = 0; r < nrows && y < ymax; ++r) { - Rectangle bounds = new Rectangle(x, y, width, height); - if (bounds.intersects(clip)) - { - TableCellRenderer rend = table.getCellRenderer(r, c); - Component comp = table.prepareRenderer(rend, r, c); - gfx.translate(x, y); - comp.setBounds(new Rectangle(0, 0, width, height)); - // Set correct border on cell renderer. - // Only the lead selection cell gets a border - if (comp instanceof JComponent) - { - if (table.getSelectionModel().getLeadSelectionIndex() == r - && table.getColumnModel().getSelectionModel(). - getLeadSelectionIndex() == c) - ((JComponent) comp).setBorder(highlightCellBorder); - else - ((JComponent) comp).setBorder(cellBorder); - } - comp.paint(gfx); - if (comp instanceof JTextField) - ((JTextField)comp).getCaret().paint(gfx); - gfx.translate(-x, -y); + Rectangle bounds = new Rectangle(x + halfGapWidth, + y + halfGapHeight + 1, + width - gap.width + 1, + height - gap.height); + if (bounds.intersects(clip)) + { + paintCell(gfx, r, c, bounds, table.getCellRenderer(r, c), + table.getModel(), + table.getSelectionModel().getLeadSelectionIndex(), + table.getColumnModel().getSelectionModel().getLeadSelectionIndex()); } - y += height; - if (gap != null) - y += gap.height; + y += height; } x += width; - if (gap != null) - x += gap.width; } // tighten up the x and y max bounds @@ -1044,7 +1282,7 @@ public class BasicTableUI Color grid = table.getGridColor(); - // paint vertical grid lines + // paint vertical grid lines if (grid != null && table.getShowVerticalLines()) { x = x0; @@ -1053,9 +1291,7 @@ public class BasicTableUI boolean paintedLine = false; for (int c = 0; c < ncols && x < xmax; ++c) { - x += cols.getColumn(c).getWidth();; - if (gap != null) - x += gap.width; + x += cols.getColumn(c).getWidth(); gfx.drawLine(x, y0, x, ymax); paintedLine = true; } @@ -1072,8 +1308,6 @@ public class BasicTableUI for (int r = 0; r < nrows && y < ymax; ++r) { y += height; - if (gap != null) - y += gap.height; gfx.drawLine(x0, y, xmax, y); paintedLine = true; } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java index 97b0ccb6ee6..36854e07fe0 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java @@ -39,11 +39,16 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import java.beans.PropertyChangeEvent; + import javax.swing.JComponent; +import javax.swing.JTextArea; +import javax.swing.UIDefaults; import javax.swing.plaf.ComponentUI; import javax.swing.text.Element; import javax.swing.text.PlainView; import javax.swing.text.View; +import javax.swing.text.WrappedPlainView; public class BasicTextAreaUI extends BasicTextUI { @@ -54,15 +59,55 @@ public class BasicTextAreaUI extends BasicTextUI public BasicTextAreaUI() { + // Nothing to do here. } + /** + * Create the view. Returns a WrappedPlainView if the text area + * has lineWrap set to true, otherwise returns a PlainView. If + * lineWrap is true has to check whether the wrap style is word + * or character and return an appropriate WrappedPlainView. + * + * @param elem the element to create a View for + * @return an appropriate View for the element + */ public View create(Element elem) { - return new PlainView(elem); + JTextArea comp = (JTextArea)getComponent(); + if (comp.getLineWrap()) + { + if (comp.getWrapStyleWord()) + return new WrappedPlainView(elem, true); + else + return new WrappedPlainView(elem, false); + } + else + return new PlainView(elem); } + /** + * Returns the prefix for entries in the {@link UIDefaults} table. + * + * @return "TextArea" + */ protected String getPropertyPrefix() { return "TextArea"; } + + /** + * Receives notification whenever one of the text component's bound + * properties changes. This changes the view to WrappedPlainView + * if setLineWrap(true) is called, and back to PlainView if + * setLineWrap(false) is called. + * + * @param ev the property change event + */ + protected void propertyChange(PropertyChangeEvent ev) + { + JTextArea comp = (JTextArea)getComponent(); + if (ev.getPropertyName() == "lineWrap" + || ev.getPropertyName() == "wrapStyleWord") + modelChanged(); + } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java index a300446c262..4e2ca9f93df 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java @@ -41,6 +41,7 @@ package javax.swing.plaf.basic; import java.beans.PropertyChangeEvent; import javax.swing.JComponent; +import javax.swing.UIDefaults; import javax.swing.plaf.ComponentUI; import javax.swing.text.Element; import javax.swing.text.FieldView; @@ -63,6 +64,11 @@ public class BasicTextFieldUI extends BasicTextUI return new BasicTextFieldUI(); } + /** + * Returns the prefix for entries in the {@link UIDefaults} table. + * + * @return "TextField" + */ protected String getPropertyPrefix() { return "TextField"; @@ -73,8 +79,22 @@ public class BasicTextFieldUI extends BasicTextUI super.installUI(c); } + /** + * 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. + * + * @param event the property change event + */ protected void propertyChange(PropertyChangeEvent event) { - // Does nothing by default. + if (event.getPropertyName().equals("editable")) + { + boolean editable = ((Boolean) event.getNewValue()).booleanValue(); + if (editable) + textComponent.setBackground(background); + else + textComponent.setBackground(inactiveBackground); + } } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java index 55d908e1b88..decbed56829 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java @@ -38,10 +38,18 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import java.awt.Color; + import javax.swing.JComponent; +import javax.swing.JTextPane; +import javax.swing.plaf.ColorUIResource; +import javax.swing.UIDefaults; import javax.swing.plaf.ComponentUI; import javax.swing.text.Element; import javax.swing.text.PlainView; +import javax.swing.text.Style; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyleContext; import javax.swing.text.View; public class BasicTextPaneUI extends BasicEditorPaneUI @@ -61,8 +69,32 @@ public class BasicTextPaneUI extends BasicEditorPaneUI return new PlainView(elem); } + /** + * Returns the prefix for entries in the {@link UIDefaults} table. + * + * @return "TextPane" + */ protected String getPropertyPrefix() { return "TextPane"; } + + /** + * Installs this UI on the specified <code>JTextPane</code>. This calls the + * super implementation and then adds a default style to the text pane. + * + * @param c the text pane to install the UI to + */ + public void installUI(JComponent c) + { + super.installUI(c); + JTextPane tp = (JTextPane) c; + Style defaultStyle = tp.getStyle(StyleContext.DEFAULT_STYLE); + defaultStyle.addAttribute(StyleConstants.Foreground, + new ColorUIResource(Color.BLACK)); + defaultStyle.addAttribute(StyleConstants.FontFamily, "Serif"); + defaultStyle.addAttribute(StyleConstants.Italic, Boolean.FALSE); + defaultStyle.addAttribute(StyleConstants.Bold, Boolean.FALSE); + defaultStyle.addAttribute(StyleConstants.FontSize, new Integer(12)); + } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java index 91ccb0056bb..b9de92640c8 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java @@ -38,6 +38,7 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.Graphics; @@ -54,6 +55,8 @@ import javax.swing.Action; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.JComponent; +import javax.swing.LookAndFeel; +import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.UIDefaults; import javax.swing.UIManager; @@ -73,7 +76,6 @@ import javax.swing.text.Element; import javax.swing.text.Highlighter; import javax.swing.text.JTextComponent; import javax.swing.text.Keymap; -import javax.swing.text.PlainView; import javax.swing.text.Position; import javax.swing.text.View; import javax.swing.text.ViewFactory; @@ -92,11 +94,11 @@ public abstract class BasicTextUI extends TextUI /** * A {@link DefaultCaret} that implements {@link UIResource}. */ - public static class BasicCaret extends DefaultCaret - implements UIResource + public static class BasicCaret extends DefaultCaret implements UIResource { public BasicCaret() { + // Nothing to do here. } } @@ -108,6 +110,7 @@ public abstract class BasicTextUI extends TextUI { public BasicHighlighter() { + // Nothing to do here. } } @@ -241,7 +244,7 @@ public abstract class BasicTextUI extends TextUI public void paint(Graphics g, Shape s) { if (view != null) - view.paint(g, s); + view.paint(g, s); } @@ -252,10 +255,10 @@ public abstract class BasicTextUI extends TextUI * * This is delegated to the real root view. * - * @param pos the position of the character in the model + * @param position the position of the character in the model * @param a the area that is occupied by the view - * @param bias either {@link Position.Bias.Forward} or - * {@link Position.Bias.Backward} depending on the preferred + * @param bias either {@link Position.Bias#Forward} or + * {@link Position.Bias#Backward} depending on the preferred * direction bias. If <code>null</code> this defaults to * <code>Position.Bias.Forward</code> * @@ -327,12 +330,41 @@ public abstract class BasicTextUI extends TextUI { view.changedUpdate(ev, shape, vf); } + + /** + * Returns the document position that is (visually) nearest to the given + * document position <code>pos</code> in the given direction <code>d</code>. + * + * @param c the text component + * @param pos the document position + * @param b the bias for <code>pos</code> + * @param d the direction, must be either {@link SwingConstants#NORTH}, + * {@link SwingConstants#SOUTH}, {@link SwingConstants#WEST} or + * {@link SwingConstants#EAST} + * @param biasRet an array of {@link Position.Bias} that can hold at least + * one element, which is filled with the bias of the return position + * on method exit + * + * @return the document position that is (visually) nearest to the given + * document position <code>pos</code> in the given direction + * <code>d</code> + * + * @throws BadLocationException if <code>pos</code> is not a valid offset in + * the document model + */ + public int getNextVisualPositionFrom(JTextComponent c, int pos, + Position.Bias b, int d, + Position.Bias[] biasRet) + throws BadLocationException + { + return view.getNextVisualPositionFrom(c, pos, b, d, biasRet); + } } /** * Receives notifications when properties of the text component change. */ - class UpdateHandler implements PropertyChangeListener + class PropertyChangeHandler implements PropertyChangeListener { /** * Notifies when a property of the text component changes. @@ -342,10 +374,12 @@ public abstract class BasicTextUI extends TextUI public void propertyChange(PropertyChangeEvent event) { if (event.getPropertyName().equals("document")) - { + { // Document changed. - modelChanged(); - } + modelChanged(); + } + + BasicTextUI.this.propertyChange(event); } } @@ -364,11 +398,10 @@ public abstract class BasicTextUI extends TextUI */ public void changedUpdate(DocumentEvent ev) { - Dimension size = textComponent.getSize(); - rootView.changedUpdate(ev, new Rectangle(0, 0, size.width, size.height), + rootView.changedUpdate(ev, getVisibleEditorRect(), rootView.getViewFactory()); } - + /** * Notification about a document insert event. * @@ -376,12 +409,8 @@ public abstract class BasicTextUI extends TextUI */ public void insertUpdate(DocumentEvent ev) { - Dimension size = textComponent.getSize(); - rootView.insertUpdate(ev, new Rectangle(0, 0, size.width, size.height), + rootView.insertUpdate(ev, getVisibleEditorRect(), rootView.getViewFactory()); - int caretPos = textComponent.getCaretPosition(); - if (caretPos >= ev.getOffset()) - textComponent.setCaretPosition(caretPos + ev.getLength()); } /** @@ -391,12 +420,8 @@ public abstract class BasicTextUI extends TextUI */ public void removeUpdate(DocumentEvent ev) { - Dimension size = textComponent.getSize(); - rootView.removeUpdate(ev, new Rectangle(0, 0, size.width, size.height), + rootView.removeUpdate(ev, getVisibleEditorRect(), rootView.getViewFactory()); - int caretPos = textComponent.getCaretPosition(); - if (caretPos >= ev.getOffset()) - textComponent.setCaretPosition(ev.getOffset()); } } @@ -419,16 +444,29 @@ public abstract class BasicTextUI extends TextUI /** * Receives notification when the model changes. */ - UpdateHandler updateHandler = new UpdateHandler(); + PropertyChangeHandler updateHandler = new PropertyChangeHandler(); /** The DocumentEvent handler. */ DocumentHandler documentHandler = new DocumentHandler(); /** + * The standard background color. This is the color which is used to paint + * text in enabled text components. + */ + Color background; + + /** + * The inactive background color. This is the color which is used to paint + * text in disabled text components. + */ + Color inactiveBackground; + + /** * Creates a new <code>BasicTextUI</code> instance. */ public BasicTextUI() { + // Nothing to do here. } /** @@ -506,14 +544,20 @@ public abstract class BasicTextUI extends TextUI textComponent.setHighlighter(createHighlighter()); String prefix = getPropertyPrefix(); - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - textComponent.setBackground(defaults.getColor(prefix + ".background")); - textComponent.setForeground(defaults.getColor(prefix + ".foreground")); - textComponent.setMargin(defaults.getInsets(prefix + ".margin")); - textComponent.setBorder(defaults.getBorder(prefix + ".border")); - textComponent.setFont(defaults.getFont(prefix + ".font")); - - caret.setBlinkRate(defaults.getInt(prefix + ".caretBlinkRate")); + LookAndFeel.installColorsAndFont(textComponent, prefix + ".background", + prefix + ".foreground", prefix + ".font"); + LookAndFeel.installBorder(textComponent, prefix + ".border"); + textComponent.setMargin(UIManager.getInsets(prefix + ".margin")); + + caret.setBlinkRate(UIManager.getInt(prefix + ".caretBlinkRate")); + + // Fetch the colors for enabled/disabled text components. + background = UIManager.getColor(prefix + ".background"); + inactiveBackground = UIManager.getColor(prefix + ".inactiveBackground"); + textComponent.setDisabledTextColor + (UIManager.getColor(prefix + ".inactiveForeground")); + textComponent.setSelectedTextColor(UIManager.getColor(prefix + ".selectionForeground")); + textComponent.setSelectionColor(UIManager.getColor(prefix + ".selectionBackground")); } /** @@ -704,6 +748,7 @@ public abstract class BasicTextUI extends TextUI protected void uninstallListeners() { textComponent.removeFocusListener(focuslistener); + textComponent.getDocument().removeDocumentListener(documentHandler); } /** @@ -757,6 +802,18 @@ public abstract class BasicTextUI extends TextUI } /** + * Returns the minimum size for text components. This returns the size + * of the component's insets. + * + * @return the minimum size for text components + */ + public Dimension getMinimumSize(JComponent c) + { + Insets i = c.getInsets(); + return new Dimension(i.left + i.right, i.top + i.bottom); + } + + /** * Paints the text component. * * @param g the <code>Graphics</code> context to paint to @@ -776,10 +833,10 @@ public abstract class BasicTextUI extends TextUI { Caret caret = textComponent.getCaret(); Highlighter highlighter = textComponent.getHighlighter(); - + if (textComponent.isOpaque()) paintBackground(g); - + if (highlighter != null && textComponent.getSelectionStart() != textComponent.getSelectionEnd()) highlighter.paint(g); @@ -797,8 +854,10 @@ public abstract class BasicTextUI extends TextUI */ protected void paintBackground(Graphics g) { - g.setColor(textComponent.getBackground()); - g.fillRect(0, 0, textComponent.getWidth(), textComponent.getHeight()); + // This method does nothing. All the background filling is done by the + // ComponentUI update method. However, the method is called by paint + // to provide a way for subclasses to draw something different (e.g. + // background images etc) on the background. } /** @@ -885,10 +944,10 @@ public abstract class BasicTextUI extends TextUI /** * Maps a position in the document into the coordinate space of the View. * The output rectangle usually reflects the font height but has a width - * of zero. A bias of {@link Position.Bias.Forward} is used in this method. + * of zero. A bias of {@link Position.Bias#Forward} is used in this method. * + * @param t the text component * @param pos the position of the character in the model - * @param a the area that is occupied by the view * * @return a rectangle that gives the location of the document position * inside the view coordinate space @@ -908,10 +967,10 @@ public abstract class BasicTextUI extends TextUI * The output rectangle usually reflects the font height but has a width * of zero. * + * @param t the text component * @param pos the position of the character in the model - * @param a the area that is occupied by the view - * @param bias either {@link Position.Bias.Forward} or - * {@link Position.Bias.Backward} depending on the preferred + * @param bias either {@link Position.Bias#Forward} or + * {@link Position.Bias#Backward} depending on the preferred * direction bias. If <code>null</code> this defaults to * <code>Position.Bias.Forward</code> * @@ -957,7 +1016,7 @@ public abstract class BasicTextUI extends TextUI */ public int viewToModel(JTextComponent t, Point pt, Position.Bias[] biasReturn) { - return 0; // FIXME: Implement me. + return rootView.viewToModel(pt.x, pt.y, getVisibleEditorRect(), biasReturn); } /** @@ -999,16 +1058,17 @@ public abstract class BasicTextUI extends TextUI */ protected Rectangle getVisibleEditorRect() { + JTextComponent textComponent = getComponent(); int width = textComponent.getWidth(); int height = textComponent.getHeight(); if (width <= 0 || height <= 0) - return null; + return new Rectangle(0, 0, 0, 0); Insets insets = textComponent.getInsets(); return new Rectangle(insets.left, insets.top, - width - insets.left + insets.right, - height - insets.top + insets.bottom); + width - insets.left - insets.right, + height - insets.top - insets.bottom); } /** @@ -1020,6 +1080,8 @@ public abstract class BasicTextUI extends TextUI { rootView.setView(view); view.setParent(rootView); + textComponent.revalidate(); + textComponent.repaint(); } /** @@ -1043,4 +1105,17 @@ public abstract class BasicTextUI extends TextUI View view = factory.create(elem); setView(view); } + + /** + * Receives notification whenever one of the text component's bound + * properties changes. This default implementation does nothing. + * It is a hook that enables subclasses to react to property changes + * on the text component. + * + * @param ev the property change event + */ + protected void propertyChange(PropertyChangeEvent ev) + { + // The default implementation does nothing. + } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java index 9106b0b6673..896ea0c89dc 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java @@ -38,7 +38,13 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Rectangle; + +import javax.swing.AbstractButton; import javax.swing.JComponent; +import javax.swing.SwingUtilities; import javax.swing.plaf.ComponentUI; public class BasicToggleButtonUI extends BasicButtonUI @@ -58,5 +64,62 @@ public class BasicToggleButtonUI extends BasicButtonUI { return "ToggleButton."; } -} + /** + * Paint the component, which is an {@link AbstractButton}, according to + * its current state. + * + * @param g The graphics context to paint with + * @param c The component to paint the state of + */ + public void paint(Graphics g, JComponent c) + { + AbstractButton b = (AbstractButton) c; + + Rectangle tr = new Rectangle(); + Rectangle ir = new Rectangle(); + Rectangle vr = new Rectangle(); + + Font f = c.getFont(); + + g.setFont(f); + + if (b.isBorderPainted()) + SwingUtilities.calculateInnerArea(b, vr); + else + vr = SwingUtilities.getLocalBounds(b); + String text = SwingUtilities.layoutCompoundLabel(c, g.getFontMetrics(f), + b.getText(), + currentIcon(b), + b.getVerticalAlignment(), + b.getHorizontalAlignment(), + b.getVerticalTextPosition(), + b.getHorizontalTextPosition(), + vr, ir, tr, + b.getIconTextGap() + + defaultTextShiftOffset); + + if ((b.getModel().isArmed() && b.getModel().isPressed()) + || b.isSelected()) + paintButtonPressed(g, b); + + paintIcon(g, b, ir); + if (text != null) + paintText(g, b, tr, text); + if (b.isFocusOwner() && b.isFocusPainted()) + paintFocus(g, b, vr, tr, ir); + } + + /** + * Paints the icon for the toggle button. This delegates to + * {@link BasicButtonUI#paintIcon(Graphics, JComponent, Rectangle)}. + * + * @param g the graphics context + * @param b the button to paint the icon for + * @param iconRect the area allocated for the icon + */ + protected void paintIcon(Graphics g, AbstractButton b, Rectangle iconRect) + { + super.paintIcon(g, b, iconRect); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java index db29fdca583..79cf0b0c213 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java @@ -43,7 +43,6 @@ import java.awt.Graphics; import javax.swing.JComponent; import javax.swing.JSeparator; -import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; @@ -73,9 +72,7 @@ public class BasicToolBarSeparatorUI extends BasicSeparatorUI */ protected void installDefaults(JSeparator s) { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - size = defaults.getDimension("ToolBar.separatorSize"); + size = UIManager.getDimension("ToolBar.separatorSize"); } /** diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java index 8be89efcfa6..ef4ed835f86 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java @@ -65,10 +65,11 @@ import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JToolBar; +import javax.swing.KeyStroke; +import javax.swing.LookAndFeel; import javax.swing.RootPaneContainer; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; -import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.event.MouseInputListener; @@ -133,6 +134,26 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants protected FocusListener toolBarFocusListener; /** + * @deprecated since JDK1.3. + */ + protected KeyStroke leftKey; + + /** + * @deprecated since JDK1.3. + */ + protected KeyStroke rightKey; + + /** + * @deprecated since JDK1.3. + */ + protected KeyStroke upKey; + + /** + * @deprecated since JDK1.3. + */ + protected KeyStroke downKey; + + /** * The floating window that is responsible for holding the JToolBar when it * is dragged outside of its original parent. */ @@ -566,18 +587,16 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants */ protected void installDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + LookAndFeel.installBorder(toolBar, "ToolBar.border"); + LookAndFeel.installColorsAndFont(toolBar, "ToolBar.background", + "ToolBar.foreground", "ToolBar.font"); - toolBar.setBorder(new ToolBarBorder()); - toolBar.setBackground(defaults.getColor("ToolBar.background")); - toolBar.setForeground(defaults.getColor("ToolBar.foreground")); - toolBar.setFont(defaults.getFont("ToolBar.font")); + dockingBorderColor = UIManager.getColor("ToolBar.dockingForeground"); + dockingColor = UIManager.getColor("ToolBar.dockingBackground"); - dockingBorderColor = defaults.getColor("ToolBar.dockingForeground"); - dockingColor = defaults.getColor("ToolBar.dockingBackground"); - - floatingBorderColor = defaults.getColor("ToolBar.floatingForeground"); - floatingColor = defaults.getColor("ToolBar.floatingBackground"); + floatingBorderColor = UIManager.getColor("ToolBar.floatingForeground"); + floatingColor = UIManager.getColor("ToolBar.floatingBackground"); + setRolloverBorders(toolBar.isRollover()); } /** @@ -591,10 +610,8 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants /** * This method installs listeners for the JToolBar. - * - * @param toolbar The JToolBar to register listeners for. */ - protected void installListeners(JToolBar toolbar) + protected void installListeners() { dockingListener = createDockingListener(); toolBar.addMouseListener(dockingListener); @@ -694,7 +711,7 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants toolBar.setOpaque(true); installDefaults(); installComponents(); - installListeners(toolBar); + installListeners(); installKeyboardActions(); } } @@ -1000,6 +1017,7 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants */ public void mouseMoved(MouseEvent e) { + // TODO: What should be done here, if anything? } /** @@ -1030,13 +1048,15 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants } origin = new Point(0, 0); - SwingUtilities.convertPointToScreen(ssd, toolBar); + if (toolBar.isShowing()) + SwingUtilities.convertPointToScreen(ssd, toolBar); if (! (SwingUtilities.getAncestorOfClass(Window.class, toolBar) instanceof UIResource)) // Need to know who keeps the toolBar if it gets dragged back into it. origParent = toolBar.getParent(); - - SwingUtilities.convertPointToScreen(origin, toolBar); + + if (toolBar.isShowing()) + SwingUtilities.convertPointToScreen(origin, toolBar); isDragging = true; diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java index b7a08aa728e..5cec2e33365 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java @@ -1,5 +1,5 @@ /* BasicToolTipUI.java -- - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -39,20 +39,18 @@ exception statement from your version. */ package javax.swing.plaf.basic; import java.awt.Color; -import java.awt.Component; import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Insets; import java.awt.Rectangle; +import java.awt.Toolkit; import javax.swing.JComponent; import javax.swing.JToolTip; +import javax.swing.LookAndFeel; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; -import javax.swing.UIDefaults; -import javax.swing.UIManager; -import javax.swing.border.Border; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ToolTipUI; @@ -61,58 +59,12 @@ import javax.swing.plaf.ToolTipUI; */ public class BasicToolTipUI extends ToolTipUI { - /** The default Border around the JToolTip. */ - private static Border defaultBorder = new Border() - { - // FIXME: This needs to go into Basic Look and Feel - // defaults. - /** - * This method returns the border insets. - * - * @param c The Component to find Border insets for. - * - * @return The Border insets. - */ - public Insets getBorderInsets(Component c) - { - return new Insets(4, 4, 4, 4); - } + /** The shared instance of BasicToolTipUI used for all ToolTips. */ + private static BasicToolTipUI shared; - /** - * This method returns whether the border is opaque. - * - * @return Whether the border is opaque. - */ - public boolean isBorderOpaque() - { - return false; - } - - /** - * This method paints the border. - * - * @param c The Component to paint this border around. - * @param g The Graphics object to paint with. - * @param x The x coordinate to start painting at. - * @param y The y coordinate to start painting at. - * @param w The width of the Component. - * @param h The height of the Component. - */ - public void paintBorder(Component c, Graphics g, int x, int y, int w, - int h) - { - Color saved = g.getColor(); - g.setColor(Color.BLACK); - - g.drawRect(0, 0, w - 1, h - 1); - - g.setColor(saved); - } - }; - - /** The shared instance of BasicToolTipUI used for all ToolTips. */ - private static BasicToolTipUI shared; + /** The tooltip's text */ + private String text; /** * Creates a new BasicToolTipUI object. @@ -124,7 +76,7 @@ public class BasicToolTipUI extends ToolTipUI /** * This method creates a new BasicToolTip UI for the given - * JComponent. + * JComponent. * * @param c The JComponent to create a UI for. * @@ -132,9 +84,9 @@ public class BasicToolTipUI extends ToolTipUI */ public static ComponentUI createUI(JComponent c) { - if (shared == null) - shared = new BasicToolTipUI(); - return shared; + if (shared == null) + shared = new BasicToolTipUI(); + return shared; } /** @@ -171,12 +123,16 @@ public class BasicToolTipUI extends ToolTipUI public Dimension getPreferredSize(JComponent c) { JToolTip tip = (JToolTip) c; + FontMetrics fm; + Toolkit g = tip.getToolkit(); + text = tip.getTipText(); + Rectangle vr = new Rectangle(); Rectangle ir = new Rectangle(); Rectangle tr = new Rectangle(); Insets insets = tip.getInsets(); - FontMetrics fm = tip.getToolkit().getFontMetrics(tip.getFont()); - SwingUtilities.layoutCompoundLabel(tip, fm, tip.getTipText(), null, + fm = g.getFontMetrics(tip.getFont()); + SwingUtilities.layoutCompoundLabel(tip, fm, text, null, SwingConstants.CENTER, SwingConstants.CENTER, SwingConstants.CENTER, @@ -192,11 +148,9 @@ public class BasicToolTipUI extends ToolTipUI */ protected void installDefaults(JComponent c) { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - c.setBackground(defaults.getColor("ToolTip.background")); - c.setForeground(defaults.getColor("ToolTip.foreground")); - c.setFont(defaults.getFont("ToolTip.font")); - c.setBorder(defaultBorder); + LookAndFeel.installColorsAndFont(c, "ToolTip.background", + "ToolTip.foreground", "ToolTip.font"); + LookAndFeel.installBorder(c, "ToolTip.border"); } /** @@ -206,6 +160,7 @@ public class BasicToolTipUI extends ToolTipUI */ protected void installListeners(JComponent c) { + // TODO: Implement this properly. } /** @@ -231,6 +186,7 @@ public class BasicToolTipUI extends ToolTipUI JToolTip tip = (JToolTip) c; String text = tip.getTipText(); + Toolkit t = tip.getToolkit(); if (text == null) return; @@ -238,19 +194,19 @@ public class BasicToolTipUI extends ToolTipUI vr = SwingUtilities.calculateInnerArea(tip, vr); Rectangle ir = new Rectangle(); Rectangle tr = new Rectangle(); - FontMetrics fm = tip.getToolkit().getFontMetrics(tip.getFont()); - SwingUtilities.layoutCompoundLabel(tip, fm, tip.getTipText(), null, + FontMetrics fm = t.getFontMetrics(tip.getFont()); + int ascent = fm.getAscent(); + SwingUtilities.layoutCompoundLabel(tip, fm, text, null, SwingConstants.CENTER, SwingConstants.CENTER, SwingConstants.CENTER, SwingConstants.CENTER, vr, ir, tr, 0); - Color saved = g.getColor(); g.setColor(Color.BLACK); - g.drawString(text, vr.x, vr.y + fm.getAscent()); + g.drawString(text, vr.x, vr.y + ascent); - g.setColor(saved); + g.setColor(saved); } /** @@ -273,6 +229,7 @@ public class BasicToolTipUI extends ToolTipUI */ protected void uninstallListeners(JComponent c) { + // TODO: Implement this properly. } /** diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java index 6f714a39cb2..e967cd424fc 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java @@ -44,6 +44,7 @@ import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; +import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ActionEvent; @@ -62,6 +63,7 @@ import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.Enumeration; import java.util.Hashtable; import javax.swing.AbstractAction; @@ -76,6 +78,7 @@ import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.KeyStroke; +import javax.swing.LookAndFeel; import javax.swing.SwingUtilities; import javax.swing.Timer; import javax.swing.UIDefaults; @@ -89,6 +92,7 @@ import javax.swing.event.TreeModelEvent; import javax.swing.event.TreeModelListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; +import javax.swing.plaf.ActionMapUIResource; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.InputMapUIResource; import javax.swing.plaf.TreeUI; @@ -96,7 +100,6 @@ import javax.swing.text.Caret; import javax.swing.tree.AbstractLayoutCache; import javax.swing.tree.DefaultTreeCellEditor; import javax.swing.tree.DefaultTreeCellRenderer; -import javax.swing.tree.ExpandVetoException; import javax.swing.tree.FixedHeightLayoutCache; import javax.swing.tree.TreeCellEditor; import javax.swing.tree.TreeCellRenderer; @@ -110,11 +113,11 @@ import javax.swing.tree.TreeSelectionModel; * the Basic look and feel. * * @see javax.swing.JTree - * @author Sascha Brawer (brawer@dandelis.ch) + * * @author Lillian Angel (langel@redhat.com) + * @author Sascha Brawer (brawer@dandelis.ch) */ -public class BasicTreeUI - extends TreeUI +public class BasicTreeUI extends TreeUI { /** Collapse Icon for the tree. */ protected transient Icon collapsedIcon; @@ -136,9 +139,6 @@ public class BasicTreeUI */ protected int totalChildIndent; - /** Minimum preferred size. */ - protected Dimension preferredMinsize; - /** Index of the row that was last selected. */ protected int lastSelectedRow; @@ -174,6 +174,9 @@ public class BasicTreeUI /** Size needed to completely display all the nodes. */ protected Dimension preferredSize; + + /** Minimum size needed to completely display all the nodes. */ + protected Dimension preferredMinSize; /** Is the preferredSize valid? */ protected boolean validCachedPreferredSize; @@ -223,38 +226,38 @@ public class BasicTreeUI /** Set to true if the editor has a different size than the renderer. */ protected boolean editorHasDifferentSize; - + /** The action listener for the editor's Timer. */ - private Timer editorTimer = new EditorUpdateTimer(); + Timer editorTimer = new EditorUpdateTimer(); /** The new value of the node after editing. */ - private Object newVal; + Object newVal; /** The action bound to KeyStrokes. */ - private TreeAction action; + TreeAction action; /** Boolean to keep track of editing. */ - private boolean isEditing; + boolean isEditing; + + /** The bounds of the current cell. */ + Rectangle bounds; + + /** The current path of the visible nodes in the tree. */ + TreePath currentVisiblePath; + + /** The gap between the icon and text. */ + int gap = 4; /** Listeners */ private PropertyChangeListener propertyChangeListener; - private FocusListener focusListener; - private TreeSelectionListener treeSelectionListener; - - private MouseInputListener mouseInputListener; - + private MouseListener mouseListener; private KeyListener keyListener; - private PropertyChangeListener selectionModelPropertyChangeListener; - private ComponentListener componentListener; - - private CellEditorListener cellEditorListener; - + CellEditorListener cellEditorListener; private TreeExpansionListener treeExpansionListener; - private TreeModelListener treeModelListener; /** @@ -262,6 +265,7 @@ public class BasicTreeUI */ public BasicTreeUI() { + validCachedPreferredSize = false; drawingCache = new Hashtable(); nodeDimensions = createNodeDimensions(); configureLayoutCache(); @@ -269,7 +273,7 @@ public class BasicTreeUI propertyChangeListener = createPropertyChangeListener(); focusListener = createFocusListener(); treeSelectionListener = createTreeSelectionListener(); - mouseInputListener = new MouseInputHandler(null, null, null); + mouseListener = createMouseListener(); keyListener = createKeyListener(); selectionModelPropertyChangeListener = createSelectionModelPropertyChangeListener(); componentListener = createComponentListener(); @@ -331,7 +335,7 @@ public class BasicTreeUI * * @return the indent value for the left child. */ - public int getLeftChildIndent(int newAmount) + public int getLeftChildIndent() { return leftChildIndent; } @@ -456,7 +460,6 @@ public class BasicTreeUI protected void setCellRenderer(TreeCellRenderer tcr) { currentCellRenderer = tcr; - tree.setCellRenderer(tcr); updateRenderer(); } @@ -625,14 +628,13 @@ public class BasicTreeUI { Object cell = path.getLastPathComponent(); - TreeModel mod = tree.getModel(); - if (mod != null) + if (treeModel != null) { - Object root = mod.getRoot(); + Object root = treeModel.getRoot(); + if (!tree.isRootVisible() && tree.isExpanded(new TreePath(root))) root = getNextNode(root); - - Point loc = getCellLocation(0, 0, tree, mod, cell, root); + Point loc = getCellLocation(0, 0, tree, treeModel, cell, root); return getCellBounds(loc.x, loc.y, cell); } } @@ -650,21 +652,11 @@ public class BasicTreeUI */ public TreePath getPathForRow(JTree tree, int row) { - TreeModel mod = tree.getModel(); - if (mod != null) + if (treeModel != null && currentVisiblePath != null) { - Object node = mod.getRoot(); - if (!tree.isRootVisible() - && tree.isExpanded(new TreePath(getPathToRoot(node, 0)))) - node = getNextNode(node); - - for (int i = 0; i < row; i++) - node = getNextVisibleNode(node); - - if (node == null) - return null; - - return new TreePath(getPathToRoot(node, 0)); + Object[] nodes = currentVisiblePath.getPath(); + if (row < nodes.length) + return new TreePath(getPathToRoot(nodes[row], 0)); } return null; } @@ -683,17 +675,20 @@ public class BasicTreeUI */ public int getRowForPath(JTree tree, TreePath path) { - int row = path.getPathCount(); - if (tree.isVisible(path)) - return row; - - path = path.getParentPath(); - while (row > 0 && !tree.isVisible(path)) + int row = 0; + Object dest = path.getLastPathComponent(); + int rowCount = getRowCount(tree); + if (currentVisiblePath != null) { - path = path.getParentPath(); - row--; + Object[] nodes = currentVisiblePath.getPath(); + while (row < rowCount) + { + if (dest.equals(nodes[row])) + return row; + row++; + } } - return row; + return -1; } /** @@ -705,22 +700,10 @@ public class BasicTreeUI */ public int getRowCount(JTree tree) { - TreeModel mod = tree.getModel(); - int count = 0; - if (mod != null) - { - Object node = mod.getRoot(); - if (!tree.isRootVisible() - && tree.isExpanded(new TreePath((getPathToRoot(node, 0))))) - node = getNextNode(node); - - while (node != null) - { - count++; - node = getNextVisibleNode(node); - } - } - return count; + updateCurrentVisiblePath(); + if (currentVisiblePath != null) + return currentVisiblePath.getPathCount(); + return 0; } /** @@ -739,9 +722,6 @@ public class BasicTreeUI */ public TreePath getClosestPathForLocation(JTree tree, int x, int y) { - // FIXME: what if root is hidden? should not depend on (0,0) - // should start counting rows from where root is. - int row = Math.round(y / getRowHeight()); TreePath path = getPathForRow(tree, row); @@ -828,7 +808,7 @@ public class BasicTreeUI */ protected void prepareForUIInstall() { - // FIXME: not implemented + // TODO: Implement this properly. } /** @@ -837,7 +817,7 @@ public class BasicTreeUI */ protected void completeUIInstall() { - // FIXME: not implemented + // TODO: Implement this properly. } /** @@ -846,7 +826,7 @@ public class BasicTreeUI */ protected void completeUIUninstall() { - // FIXME: not implemented + // TODO: Implement this properly. } /** @@ -854,7 +834,10 @@ public class BasicTreeUI */ protected void installComponents() { - // FIXME: not implemented + currentCellRenderer = createDefaultCellRenderer(); + rendererPane = createCellRendererPane(); + createdRenderer = true; + setCellRenderer(currentCellRenderer); } /** @@ -865,8 +848,7 @@ public class BasicTreeUI */ protected AbstractLayoutCache.NodeDimensions createNodeDimensions() { - // FIXME: not implemented - return null; + return new NodeDimensionsHandler(); } /** @@ -1035,7 +1017,7 @@ public class BasicTreeUI tree.removePropertyChangeListener(propertyChangeListener); tree.removeFocusListener(focusListener); tree.removeTreeSelectionListener(treeSelectionListener); - tree.removeMouseListener(mouseInputListener); + tree.removeMouseListener(mouseListener); tree.removeKeyListener(keyListener); tree.removePropertyChangeListener(selectionModelPropertyChangeListener); tree.removeComponentListener(componentListener); @@ -1044,9 +1026,8 @@ public class BasicTreeUI TreeCellEditor tce = tree.getCellEditor(); if (tce != null) tce.removeCellEditorListener(cellEditorListener); - TreeModel tm = tree.getModel(); - if (tm != null) - tm.removeTreeModelListener(treeModelListener); + if (treeModel != null) + treeModel.removeTreeModelListener(treeModelListener); } /** @@ -1054,6 +1035,7 @@ public class BasicTreeUI */ protected void uninstallKeyboardActions() { + // TODO: Implement this properly. } /** @@ -1061,7 +1043,10 @@ public class BasicTreeUI */ protected void uninstallComponents() { - // FIXME: not implemented + currentCellRenderer = null; + rendererPane = null; + createdRenderer = false; + setCellRenderer(currentCellRenderer); } /** @@ -1072,8 +1057,7 @@ public class BasicTreeUI */ protected int getVerticalLegBuffer() { - // FIXME: not implemented - return 0; + return getRowHeight() / 2; } /** @@ -1085,17 +1069,17 @@ public class BasicTreeUI */ protected int getHorizontalLegBuffer() { - // FIXME: not implemented - return 0; + return rightChildIndent / 2; } /** * Make all the nodes that are expanded in JTree expanded in LayoutCache. This - * invokes update ExpandedDescendants with the root path. + * invokes updateExpandedDescendants with the root path. */ protected void updateLayoutCacheExpandedNodes() { - // FIXME: not implemented + if (treeModel != null) + updateExpandedDescendants(new TreePath(treeModel.getRoot())); } /** @@ -1108,7 +1092,9 @@ public class BasicTreeUI */ protected void updateExpandedDescendants(TreePath path) { - // FIXME: not implemented + Enumeration expanded = tree.getExpandedDescendants(path); + while (expanded.hasMoreElements()) + treeState.setExpandedState(((TreePath) expanded.nextElement()), true); } /** @@ -1128,7 +1114,7 @@ public class BasicTreeUI */ protected void updateDepthOffset() { - // FIXME: not implemented + depthOffset += getVerticalLegBuffer(); } /** @@ -1148,7 +1134,15 @@ public class BasicTreeUI */ protected void updateRenderer() { - // FIXME: not implemented + if (tree != null) + { + if(tree.getCellRenderer() == null) + { + if(currentCellRenderer == null) + currentCellRenderer = createDefaultCellRenderer(); + tree.setCellRenderer(currentCellRenderer); + } + } } /** @@ -1166,19 +1160,36 @@ public class BasicTreeUI */ protected void updateSize() { - // FIXME: not implemented + preferredSize = null; + updateCachedPreferredSize(); + tree.treeDidChange(); } /** * Updates the <code>preferredSize</code> instance variable, which is - * returned from <code>getPreferredSize()</code>. For left to right - * orientations, the size is determined from the current AbstractLayoutCache. - * For RTL orientations, the preferred size becomes the width minus the - * minimum x position. + * returned from <code>getPreferredSize()</code>. */ protected void updateCachedPreferredSize() { - // FIXME: not implemented + int maxWidth = 0; + boolean isLeaf = false; + if (currentVisiblePath != null) + { + Object[] path = currentVisiblePath.getPath(); + for (int i = 0; i < path.length; i++) + { + TreePath curr = new TreePath(getPathToRoot(path[i], 0)); + Rectangle bounds = getPathBounds(tree, curr); + if (treeModel != null) + isLeaf = treeModel.isLeaf(path[i]); + if (!isLeaf && hasControlIcons()) + bounds.width += getCurrentControlIcon(curr).getIconWidth(); + maxWidth = Math.max(maxWidth, bounds.x + bounds.width); + } + preferredSize = new Dimension(maxWidth, (getRowHeight() * path.length)); + } + else preferredSize = new Dimension(0, 0); + validCachedPreferredSize = true; } /** @@ -1189,7 +1200,9 @@ public class BasicTreeUI */ protected void pathWasExpanded(TreePath path) { - // FIXME: not implemented + validCachedPreferredSize = false; + tree.revalidate(); + tree.repaint(); } /** @@ -1197,28 +1210,28 @@ public class BasicTreeUI */ protected void pathWasCollapsed(TreePath path) { - // FIXME: not implemented + validCachedPreferredSize = false; + tree.revalidate(); + tree.repaint(); } /** * Install all defaults for the tree. - * - * @param tree - * is the JTree to install defaults for */ - protected void installDefaults(JTree tree) + protected void installDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - tree.setFont(defaults.getFont("Tree.font")); - tree.setForeground(defaults.getColor("Tree.foreground")); - tree.setBackground(defaults.getColor("Tree.background")); + LookAndFeel.installColorsAndFont(tree, "Tree.background", + "Tree.foreground", "Tree.font"); tree.setOpaque(true); - rightChildIndent = defaults.getInt("Tree.rightChildIndent"); - leftChildIndent = defaults.getInt("Tree.leftChildIndent"); - setRowHeight(defaults.getInt("Tree.rowHeight")); + rightChildIndent = UIManager.getInt("Tree.rightChildIndent"); + leftChildIndent = UIManager.getInt("Tree.leftChildIndent"); + setRowHeight(UIManager.getInt("Tree.rowHeight")); + tree.setRowHeight(UIManager.getInt("Tree.rowHeight")); tree.requestFocusInWindow(false); + tree.setScrollsOnExpand(UIManager.getBoolean("Tree.scrollsOnExpand")); + setExpandedIcon(UIManager.getIcon("Tree.expandedIcon")); + setCollapsedIcon(UIManager.getIcon("Tree.collapsedIcon")); } /** @@ -1229,7 +1242,7 @@ public class BasicTreeUI UIDefaults defaults = UIManager.getLookAndFeelDefaults(); InputMap focusInputMap = (InputMap) defaults.get("Tree.focusInputMap"); InputMapUIResource parentInputMap = new InputMapUIResource(); - ActionMap parentActionMap = new ActionMap(); + ActionMap parentActionMap = new ActionMapUIResource(); action = new TreeAction(); Object keys[] = focusInputMap.allKeys(); @@ -1308,7 +1321,7 @@ public class BasicTreeUI tree.addPropertyChangeListener(propertyChangeListener); tree.addFocusListener(focusListener); tree.addTreeSelectionListener(treeSelectionListener); - tree.addMouseListener(mouseInputListener); + tree.addMouseListener(mouseListener); tree.addKeyListener(keyListener); tree.addPropertyChangeListener(selectionModelPropertyChangeListener); tree.addComponentListener(componentListener); @@ -1325,37 +1338,36 @@ public class BasicTreeUI */ public void installUI(JComponent c) { - super.installUI(c); - installDefaults((JTree) c); tree = (JTree) c; + prepareForUIInstall(); + super.installUI(c); + installDefaults(); - currentCellRenderer = createDefaultCellRenderer(); - rendererPane = createCellRendererPane(); - createdRenderer = true; - + installComponents(); + installKeyboardActions(); + installListeners(); + setCellEditor(createDefaultCellEditor()); createdCellEditor = true; isEditing = false; - + TreeModel mod = tree.getModel(); setModel(mod); - tree.setRootVisible(true); if (mod != null) - tree.expandPath(new TreePath(mod.getRoot())); + { + TreePath path = new TreePath(mod.getRoot()); + if (!tree.isExpanded(path)) + toggleExpandState(path); + } treeSelectionModel = tree.getSelectionModel(); - installKeyboardActions(); - installListeners(); completeUIInstall(); } /** * Uninstall the defaults for the tree - * - * @param tree - * to uninstall defaults for */ - protected void uninstallDefaults(JTree tree) + protected void uninstallDefaults() { tree.setFont(null); tree.setForeground(null); @@ -1370,10 +1382,12 @@ public class BasicTreeUI */ public void uninstallUI(JComponent c) { - uninstallDefaults((JTree) c); + prepareForUIUninstall(); + uninstallDefaults(); uninstallKeyboardActions(); uninstallListeners(); tree = null; + uninstallComponents(); completeUIUninstall(); } @@ -1393,20 +1407,16 @@ public class BasicTreeUI public void paint(Graphics g, JComponent c) { JTree tree = (JTree) c; - - TreeModel mod = tree.getModel(); - - if (mod != null) + if (currentVisiblePath == null) + updateCurrentVisiblePath(); + + if (currentVisiblePath != null && treeModel != null) { - Object root = mod.getRoot(); - - if (!tree.isRootVisible()) - tree.expandPath(new TreePath(root)); - - paintRecursive(g, 0, 0, 0, 0, tree, mod, root); - + Object root = treeModel.getRoot(); + paintRecursive(g, 0, 0, 0, tree, treeModel, root); + if (hasControlIcons()) - paintControlIcons(g, 0, 0, 0, 0, tree, mod, root); + paintControlIcons(g, 0, 0, 0, tree, treeModel, root); } } @@ -1420,7 +1430,19 @@ public class BasicTreeUI */ protected void ensureRowsAreVisible(int beginRow, int endRow) { - // FIXME: not implemented + if (beginRow < endRow) + { + int temp = endRow; + endRow = beginRow; + beginRow = temp; + } + + for (int i = beginRow; i < endRow; i++) + { + TreePath path = getPathForRow(tree, i); + if (!tree.isVisible(path)) + tree.makeVisible(path); + } } /** @@ -1431,7 +1453,7 @@ public class BasicTreeUI */ public void setPreferredMinSize(Dimension newSize) { - // FIXME: not implemented + preferredMinSize = newSize; } /** @@ -1441,8 +1463,7 @@ public class BasicTreeUI */ public Dimension getPreferredMinSize() { - // FIXME: not implemented - return null; + return preferredMinSize; } /** @@ -1472,28 +1493,10 @@ public class BasicTreeUI */ public Dimension getPreferredSize(JComponent c, boolean checkConsistancy) { - // FIXME: checkConsistancy not implemented, c not used - TreeModel model = tree.getModel(); - int maxWidth = 0; - int count = 0; - if (model != null) - { - Object node = model.getRoot(); - if (node != null) - { - maxWidth = (int) (getCellBounds(0, 0, node).getWidth()); - while (node != null) - { - count++; - Object nextNode = getNextVisibleNode(node); - if (nextNode != null) - maxWidth = Math.max(maxWidth, - (int) (getCellBounds(0, 0, nextNode).getWidth())); - node = nextNode; - } - } - } - return new Dimension(maxWidth, (getRowHeight() * count)); + // FIXME: checkConsistancy not implemented, c not used + if(!validCachedPreferredSize) + updateCachedPreferredSize(); + return preferredSize; } /** @@ -1506,8 +1509,10 @@ public class BasicTreeUI */ public Dimension getMinimumSize(JComponent c) { - // FIXME: not implemented - return getPreferredSize(c); + Dimension min = getPreferredMinSize(); + if (min == null) + return new Dimension(); + return min; } /** @@ -1520,8 +1525,9 @@ public class BasicTreeUI */ public Dimension getMaximumSize(JComponent c) { - // FIXME: not implemented - return getPreferredSize(c); + if (c instanceof JTree) + return ((JTree) c).getPreferredSize(); + return new Dimension(); } /** @@ -1565,7 +1571,7 @@ public class BasicTreeUI } if (messageTree) - tree.getModel().valueForPathChanged(tree.getLeadSelectionPath(), newVal); + treeModel.valueForPathChanged(tree.getLeadSelectionPath(), newVal); } /** @@ -1584,7 +1590,7 @@ public class BasicTreeUI int y; if (event == null) { - Rectangle bounds = getPathBounds(tree, path); + bounds = getPathBounds(tree, path); x = bounds.x; y = bounds.y; } @@ -1600,6 +1606,7 @@ public class BasicTreeUI { editingPath = path; editingRow = tree.getRowForPath(editingPath); + Object val = editingPath.getLastPathComponent(); cellEditor.addCellEditorListener(cellEditorListener); stopEditingInCompleteEditing = false; @@ -1613,6 +1620,8 @@ public class BasicTreeUI editingComponent.getParent().validate(); tree.add(editingComponent.getParent()); editingComponent.getParent().validate(); + validCachedPreferredSize = false; + tree.revalidate(); ((JTextField) editingComponent).requestFocusInWindow(false); editorTimer.start(); return true; @@ -1634,7 +1643,8 @@ public class BasicTreeUI protected void checkForClickInExpandControl(TreePath path, int mouseX, int mouseY) { - // FIXME: not implemented + if (isLocationInExpandControl(path, mouseX, mouseY)) + toggleExpandState(path); } /** @@ -1655,8 +1665,18 @@ public class BasicTreeUI protected boolean isLocationInExpandControl(TreePath path, int mouseX, int mouseY) { - // FIXME: not implemented - return false; + boolean cntlClick = false; + int row = getRowForPath(tree, path); + + if (!isLeaf(row)) + { + bounds = getPathBounds(tree, path); + + if (hasControlIcons() && (mouseX < bounds.x) + && (mouseX > (bounds.x - getCurrentControlIcon(path).getIconWidth() - gap))) + cntlClick = true; + } + return cntlClick; } /** @@ -1672,7 +1692,7 @@ public class BasicTreeUI */ protected void handleExpandControlClick(TreePath path, int mouseX, int mouseY) { - // FIXME: not implemented + toggleExpandState(path); } /** @@ -1686,7 +1706,11 @@ public class BasicTreeUI */ protected void toggleExpandState(TreePath path) { - // FIXME: not implemented + if (tree.isExpanded(path)) + tree.collapsePath(path); + else + tree.expandPath(path); + updateCurrentVisiblePath(); } /** @@ -1700,8 +1724,8 @@ public class BasicTreeUI */ protected boolean isToggleSelectionEvent(MouseEvent event) { - // FIXME: not implemented - return false; + return (tree.getSelectionModel().getSelectionMode() == + TreeSelectionModel.SINGLE_TREE_SELECTION); } /** @@ -1715,8 +1739,8 @@ public class BasicTreeUI */ protected boolean isMultiSelectEvent(MouseEvent event) { - // FIXME: not implemented - return false; + return (tree.getSelectionModel().getSelectionMode() == + TreeSelectionModel.CONTIGUOUS_TREE_SELECTION); } /** @@ -1731,8 +1755,7 @@ public class BasicTreeUI */ protected boolean isToggleEvent(MouseEvent event) { - // FIXME: not implemented - return false; + return true; } /** @@ -1749,7 +1772,29 @@ public class BasicTreeUI */ protected void selectPathForEvent(TreePath path, MouseEvent event) { - // FIXME: not implemented + if (isToggleSelectionEvent(event)) + { + if (tree.isPathSelected(path)) + tree.removeSelectionPath(path); + else + { + tree.addSelectionPath(path); + tree.setAnchorSelectionPath(path); + } + } + else if (isMultiSelectEvent(event)) + { + TreePath anchor = tree.getAnchorSelectionPath(); + if (anchor != null) + { + int aRow = getRowForPath(tree, anchor); + tree.addSelectionInterval(aRow, getRowForPath(tree, path)); + } + else + tree.addSelectionPath(path); + } + else + tree.addSelectionPath(path); } /** @@ -1766,7 +1811,7 @@ public class BasicTreeUI return true; Object node = pathForRow.getLastPathComponent(); - return tree.getModel().isLeaf(node); + return treeModel.isLeaf(node); } /** @@ -1800,9 +1845,9 @@ public class BasicTreeUI (new TreeTraverseAction(0, "")).actionPerformed(e); else if (e.getActionCommand().equals("selectAll")) { - TreePath[] paths = new TreePath[tree.getRowCount()]; + TreePath[] paths = new TreePath[tree.getVisibleRowCount()]; - Object curr = getNextVisibleNode(tree.getModel().getRoot()); + Object curr = getNextVisibleNode(treeModel.getRoot()); int i = 0; while (curr != null && i < paths.length) { @@ -1822,13 +1867,8 @@ public class BasicTreeUI { Object last = lead.getLastPathComponent(); TreePath path = new TreePath(getPathToRoot(last, 0)); - if (!tree.getModel().isLeaf(last)) - { - if (tree.isExpanded(path)) - tree.collapsePath(path); - else - tree.expandPath(path); - } + if (!treeModel.isLeaf(last)) + toggleExpandState(path); } } else if (e.getActionCommand().equals("clearSelection")) @@ -1920,8 +1960,7 @@ public class BasicTreeUI /** * Updates the preferred size when scrolling, if necessary. */ - public class ComponentHandler - extends ComponentAdapter + public class ComponentHandler extends ComponentAdapter implements ActionListener { /** @@ -1937,6 +1976,7 @@ public class BasicTreeUI */ public ComponentHandler() { + // Nothing to do here. } /** @@ -1947,6 +1987,7 @@ public class BasicTreeUI */ public void componentMoved(ComponentEvent e) { + // TODO: What should be done here, if anything? } /** @@ -1955,6 +1996,7 @@ public class BasicTreeUI */ protected void startTimer() { + // TODO: Implement this properly. } /** @@ -1976,21 +2018,22 @@ public class BasicTreeUI */ public void actionPerformed(ActionEvent ae) { + // TODO: Implement this properly. } - }// ComponentHandler + } /** * Listener responsible for getting cell editing events and updating the tree * accordingly. */ - public class CellEditorHandler - implements CellEditorListener + public class CellEditorHandler implements CellEditorListener { /** * Constructor */ public CellEditorHandler() { + // Nothing to do here. } /** @@ -2023,6 +2066,9 @@ public class BasicTreeUI isEditing = false; tree.requestFocusInWindow(false); editorTimer.stop(); + validCachedPreferredSize = false; + tree.revalidate(); + tree.repaint(); } /** @@ -2051,6 +2097,8 @@ public class BasicTreeUI tree.requestFocusInWindow(false); editorTimer.stop(); isEditing = false; + validCachedPreferredSize = false; + tree.revalidate(); tree.repaint(); } }// CellEditorHandler @@ -2066,6 +2114,7 @@ public class BasicTreeUI */ public FocusHandler() { + // Nothing to do here. } /** @@ -2077,6 +2126,7 @@ public class BasicTreeUI */ public void focusGained(FocusEvent e) { + // TODO: Implement this properly. } /** @@ -2088,8 +2138,9 @@ public class BasicTreeUI */ public void focusLost(FocusEvent e) { + // TODO: Implement this properly. } - }// FocusHandler + } /** * This is used to get multiple key down events to appropriately genereate @@ -2109,6 +2160,7 @@ public class BasicTreeUI */ public KeyHandler() { + // Nothing to do here. } /** @@ -2122,6 +2174,7 @@ public class BasicTreeUI */ public void keyTyped(KeyEvent e) { + // TODO: What should be done here, if anything? } /** @@ -2132,6 +2185,7 @@ public class BasicTreeUI */ public void keyPressed(KeyEvent e) { + // TODO: What should be done here, if anything? } /** @@ -2142,22 +2196,22 @@ public class BasicTreeUI */ public void keyReleased(KeyEvent e) { + // TODO: What should be done here, if anything? } - }// KeyHandler + } /** * MouseListener is responsible for updating the selection based on mouse * events. */ - public class MouseHandler - extends MouseAdapter - implements MouseMotionListener + public class MouseHandler extends MouseAdapter implements MouseMotionListener { /** * Constructor */ public MouseHandler() { + // Nothing to do here. } /** @@ -2168,6 +2222,57 @@ public class BasicTreeUI */ public void mousePressed(MouseEvent e) { + Point click = e.getPoint(); + TreePath path = getClosestPathForLocation(tree, click.x, click.y); + + if (path != null) + { + bounds = getPathBounds(tree, path); + int row = getRowForPath(tree, path); + boolean cntlClick = isLocationInExpandControl(path, click.x, click.y); + + boolean isLeaf = isLeaf(row); + + TreeCellRenderer tcr = getCellRenderer(); + Icon icon; + if (isLeaf) + icon = UIManager.getIcon("Tree.leafIcon"); + else if (tree.isExpanded(path)) + icon = UIManager.getIcon("Tree.openIcon"); + else + icon = UIManager.getIcon("Tree.closedIcon"); + + if (tcr instanceof DefaultTreeCellRenderer) + { + Icon tmp = ((DefaultTreeCellRenderer) tcr).getIcon(); + if (tmp != null) + icon = tmp; + } + + // add gap*2 for the space before and after the text + if (icon != null) + bounds.width += icon.getIconWidth() + gap*2; + + boolean inBounds = bounds.contains(click.x, click.y); + if ((inBounds || cntlClick) && tree.isVisible(path)) + { + if (inBounds) + { + selectPath(tree, path); + if (e.getClickCount() == 2 && !isLeaf(row)) + toggleExpandState(path); + } + + if (cntlClick) + { + handleExpandControlClick(path, click.x, click.y); + if (cellEditor != null) + cellEditor.cancelCellEditing(); + } + else if (tree.isEditable()) + startEditing(path, e); + } + } } /** @@ -2181,6 +2286,7 @@ public class BasicTreeUI */ public void mouseDragged(MouseEvent e) { + // TODO: What should be done here, if anything? } /** @@ -2192,6 +2298,7 @@ public class BasicTreeUI */ public void mouseMoved(MouseEvent e) { + // TODO: What should be done here, if anything? } /** @@ -2202,16 +2309,16 @@ public class BasicTreeUI */ public void mouseReleased(MouseEvent e) { + // TODO: What should be done here, if anything? } - }// MouseHandler + } /** * MouseInputHandler handles passing all mouse events, including mouse motion * events, until the mouse is released to the destination it is constructed * with. */ - public class MouseInputHandler - implements MouseInputListener + public class MouseInputHandler implements MouseInputListener { /** Source that events are coming from */ protected Component source; @@ -2232,6 +2339,8 @@ public class BasicTreeUI public MouseInputHandler(Component source, Component destination, MouseEvent e) { + this.source = source; + this.destination = destination; } /** @@ -2243,6 +2352,7 @@ public class BasicTreeUI */ public void mouseClicked(MouseEvent e) { + // TODO: What should be done here, if anything? } /** @@ -2253,42 +2363,7 @@ public class BasicTreeUI */ public void mousePressed(MouseEvent e) { - Point click = e.getPoint(); - int row = Math.round(click.y / getRowHeight()); - TreePath path = getClosestPathForLocation(tree, click.x, click.y); - - if (path != null) - { - boolean inBounds = false; - boolean cntlClick = false; - Rectangle bounds = getPathBounds(tree, path); - - bounds.x -= rightChildIndent - 4; - bounds.width += rightChildIndent + 4; - - if (bounds.contains(click.x, click.y)) - inBounds = true; - else if (hasControlIcons() - && (click.x < (bounds.x - rightChildIndent + 5) && - click.x > (bounds.x - rightChildIndent - 5))) - cntlClick = true; - - if ((inBounds || cntlClick) && tree.isVisible(path)) - { - selectPath(tree, path); - - if ((e.getClickCount() == 2 || cntlClick) && !isLeaf(row)) - { - if (tree.isExpanded(path)) - tree.collapsePath(path); - else - tree.expandPath(path); - } - - if (!cntlClick && tree.isEditable()) - startEditing(path, e); - } - } + // TODO: What should be done here, if anything? } /** @@ -2299,6 +2374,7 @@ public class BasicTreeUI */ public void mouseReleased(MouseEvent e) { + // TODO: What should be done here, if anything? } /** @@ -2309,6 +2385,7 @@ public class BasicTreeUI */ public void mouseEntered(MouseEvent e) { + // TODO: What should be done here, if anything? } /** @@ -2319,6 +2396,7 @@ public class BasicTreeUI */ public void mouseExited(MouseEvent e) { + // TODO: What should be done here, if anything? } /** @@ -2332,6 +2410,7 @@ public class BasicTreeUI */ public void mouseDragged(MouseEvent e) { + // TODO: What should be done here, if anything? } /** @@ -2343,6 +2422,7 @@ public class BasicTreeUI */ public void mouseMoved(MouseEvent e) { + // TODO: What should be done here, if anything? } /** @@ -2350,8 +2430,9 @@ public class BasicTreeUI */ protected void removeFromSource() { + // TODO: Implement this properly. } - }// MouseInputHandler + } /** * Class responsible for getting size of node, method is forwarded to @@ -2366,6 +2447,7 @@ public class BasicTreeUI */ public NodeDimensionsHandler() { + // Nothing to do here. } /** @@ -2413,6 +2495,7 @@ public class BasicTreeUI */ public PropertyChangeHandler() { + // Nothing to do here. } /** @@ -2424,8 +2507,15 @@ public class BasicTreeUI */ public void propertyChange(PropertyChangeEvent event) { + if ((event.getPropertyName()).equals("rootVisible")) + { + validCachedPreferredSize = false; + updateCurrentVisiblePath(); + tree.revalidate(); + tree.repaint(); + } } - }// PropertyChangeHandler + } /** * Listener on the TreeSelectionModel, resets the row selection if any of the @@ -2440,6 +2530,7 @@ public class BasicTreeUI */ public SelectionModelPropertyChangeHandler() { + // Nothing to do here. } /** @@ -2451,8 +2542,9 @@ public class BasicTreeUI */ public void propertyChange(PropertyChangeEvent event) { + // TODO: What should be done here, if anything? } - }// SelectionModelPropertyChangeHandler + } /** * ActionListener that invokes cancelEditing when action performed. @@ -2464,8 +2556,9 @@ public class BasicTreeUI /** * Constructor */ - public TreeCancelEditingAction() + public TreeCancelEditingAction(String name) { + // TODO: Implement this properly. } /** @@ -2476,6 +2569,7 @@ public class BasicTreeUI */ public void actionPerformed(ActionEvent e) { + // TODO: Implement this properly. } /** @@ -2485,9 +2579,10 @@ public class BasicTreeUI */ public boolean isEnabled() { + // TODO: Implement this properly. return false; } - }// TreeCancelEditingAction + } /** * Updates the TreeState in response to nodes expanding/collapsing. @@ -2501,6 +2596,7 @@ public class BasicTreeUI */ public TreeExpansionHandler() { + // Nothing to do here. } /** @@ -2511,6 +2607,9 @@ public class BasicTreeUI */ public void treeExpanded(TreeExpansionEvent event) { + validCachedPreferredSize = false; + updateCurrentVisiblePath(); + tree.revalidate(); tree.repaint(); } @@ -2522,6 +2621,9 @@ public class BasicTreeUI */ public void treeCollapsed(TreeExpansionEvent event) { + validCachedPreferredSize = false; + updateCurrentVisiblePath(); + tree.revalidate(); tree.repaint(); } }// TreeExpansionHandler @@ -2547,6 +2649,7 @@ public class BasicTreeUI */ public TreeHomeAction(int direction, String name) { + // TODO: Implement this properly } /** @@ -2557,6 +2660,7 @@ public class BasicTreeUI */ public void actionPerformed(ActionEvent e) { + // TODO: Implement this properly } /** @@ -2566,9 +2670,10 @@ public class BasicTreeUI */ public boolean isEnabled() { + // TODO: Implement this properly return false; } - }// TreeHomeAction + } /** * TreeIncrementAction is used to handle up/down actions. Selection is moved @@ -2591,6 +2696,7 @@ public class BasicTreeUI */ public TreeIncrementAction(int direction, String name) { + // TODO: Implement this properly } /** @@ -2606,11 +2712,11 @@ public class BasicTreeUI if (e.getActionCommand().equals("selectPreviousChangeLead")) { Object prev = getPreviousVisibleNode(last); - + if (prev != null) { TreePath newPath = new TreePath(getPathToRoot(prev, 0)); - selectPath(tree, new TreePath(getPathToRoot(prev, 0))); + selectPath(tree, newPath); tree.setLeadSelectionPath(newPath); } } @@ -2627,15 +2733,17 @@ public class BasicTreeUI else if (e.getActionCommand().equals("selectPrevious")) { Object prev = getPreviousVisibleNode(last); + if (prev != null) { TreePath newPath = new TreePath(getPathToRoot(prev, 0)); - selectPath(tree, new TreePath(getPathToRoot(prev, 0))); + selectPath(tree, newPath); } } else if (e.getActionCommand().equals("selectNext")) { Object next = getNextVisibleNode(last); + if (next != null) { TreePath newPath = new TreePath(getPathToRoot(next, 0)); @@ -2671,21 +2779,22 @@ public class BasicTreeUI */ public boolean isEnabled() { + // TODO: Implement this properly return false; } - }// TreeIncrementAction + } /** * Forwards all TreeModel events to the TreeState. */ - public class TreeModelHandler - implements TreeModelListener + public class TreeModelHandler implements TreeModelListener { /** * Constructor */ public TreeModelHandler() { + // Nothing to do here. } /** @@ -2703,6 +2812,9 @@ public class BasicTreeUI */ public void treeNodesChanged(TreeModelEvent e) { + validCachedPreferredSize = false; + updateCurrentVisiblePath(); + tree.revalidate(); tree.repaint(); } @@ -2716,6 +2828,9 @@ public class BasicTreeUI */ public void treeNodesInserted(TreeModelEvent e) { + validCachedPreferredSize = false; + updateCurrentVisiblePath(); + tree.revalidate(); tree.repaint(); } @@ -2732,6 +2847,9 @@ public class BasicTreeUI */ public void treeNodesRemoved(TreeModelEvent e) { + validCachedPreferredSize = false; + updateCurrentVisiblePath(); + tree.revalidate(); tree.repaint(); } @@ -2747,6 +2865,12 @@ public class BasicTreeUI */ public void treeStructureChanged(TreeModelEvent e) { + if (e.getPath().length == 1 + && !e.getPath()[0].equals(treeModel.getRoot())) + tree.expandPath(new TreePath(treeModel.getRoot())); + updateCurrentVisiblePath(); + validCachedPreferredSize = false; + tree.revalidate(); tree.repaint(); } }// TreeModelHandler @@ -2754,8 +2878,7 @@ public class BasicTreeUI /** * TreePageAction handles page up and page down events. */ - public class TreePageAction - extends AbstractAction + public class TreePageAction extends AbstractAction { /** Specifies the direction to adjust the selection by. */ protected int direction; @@ -2770,6 +2893,7 @@ public class BasicTreeUI */ public TreePageAction(int direction, String name) { + this.direction = direction; } /** @@ -2780,6 +2904,7 @@ public class BasicTreeUI */ public void actionPerformed(ActionEvent e) { + // TODO: Implement this properly. } /** @@ -2797,14 +2922,14 @@ public class BasicTreeUI * Listens for changes in the selection model and updates the display * accordingly. */ - public class TreeSelectionHandler - implements TreeSelectionListener + public class TreeSelectionHandler implements TreeSelectionListener { /** * Constructor */ public TreeSelectionHandler() { + // Nothing to do here. } /** @@ -2824,8 +2949,7 @@ public class BasicTreeUI /** * For the first selected row expandedness will be toggled. */ - public class TreeToggleAction - extends AbstractAction + public class TreeToggleAction extends AbstractAction { /** * Constructor @@ -2835,6 +2959,7 @@ public class BasicTreeUI */ public TreeToggleAction(String name) { + // Nothing to do here. } /** @@ -2845,6 +2970,7 @@ public class BasicTreeUI */ public void actionPerformed(ActionEvent e) { + // TODO: Implement this properly. } /** @@ -2862,8 +2988,7 @@ public class BasicTreeUI * TreeTraverseAction is the action used for left/right keys. Will toggle the * expandedness of a node, as well as potentially incrementing the selection. */ - public class TreeTraverseAction - extends AbstractAction + public class TreeTraverseAction extends AbstractAction { /** * Determines direction to traverse, 1 means expand, -1 means collapse. @@ -2880,6 +3005,7 @@ public class BasicTreeUI */ public TreeTraverseAction(int direction, String name) { + this.direction = direction; } /** @@ -2890,16 +3016,15 @@ public class BasicTreeUI */ public void actionPerformed(ActionEvent e) { - TreeModel mod = tree.getModel(); Object last = tree.getLeadSelectionPath().getLastPathComponent(); if (e.getActionCommand().equals("selectParent")) { TreePath path = new TreePath(getPathToRoot(last, 0)); - Object p = getParent(mod.getRoot(), last); + Object p = getParent(treeModel.getRoot(), last); - if (!mod.isLeaf(last) && tree.isExpanded(path)) - tree.collapsePath(path); + if (!treeModel.isLeaf(last)) + toggleExpandState(path); else if (p != null) selectPath(tree, new TreePath(getPathToRoot(p, 0))); } @@ -2907,8 +3032,8 @@ public class BasicTreeUI { TreePath path = new TreePath(getPathToRoot(last, 0)); - if (!mod.isLeaf(last) && tree.isCollapsed(path)) - tree.expandPath(path); + if (!treeModel.isLeaf(last)) + toggleExpandState(path); else { Object next = getNextVisibleNode(last); @@ -2926,9 +3051,10 @@ public class BasicTreeUI */ public boolean isEnabled() { + // TODO: Implement this properly return false; } - } // TreeTraverseAction + } /** * Returns the cell bounds for painting selected cells Package private for use @@ -2951,8 +3077,7 @@ public class BasicTreeUI FontMetrics fm = tree.getToolkit().getFontMetrics(f); if (s != null) - return new Rectangle(x, y, - SwingUtilities.computeStringWidth(fm, s) + 4, + return new Rectangle(x, y, SwingUtilities.computeStringWidth(fm, s), fm.getHeight()); } return new Rectangle(x, y, 0, 0); @@ -2982,80 +3107,19 @@ public class BasicTreeUI int rowHeight = getRowHeight(); if (startNode == null || startNode.equals(node)) { - if (!tree.isRootVisible() - && tree.isExpanded(new TreePath(mod.getRoot()))) - return new Point(x + ((getLevel(node)) * rightChildIndent), y); - - return new Point(x + ((getLevel(node) + 1) * rightChildIndent), y); - } - - if (!mod.isLeaf(startNode) - && tree.isExpanded(new TreePath(getPathToRoot(startNode, 0))) - && !mod.isLeaf(startNode) && mod.getChildCount(startNode) > 0) - { - Object child = mod.getChild(startNode, 0); - if (child != null) - return getCellLocation(x, y + rowHeight, tree, mod, node, child); + int level = getLevel(node); + if (level == 0) + return new Point(x, y); + if (!tree.isRootVisible() && + tree.isExpanded(new TreePath(mod.getRoot()))) + return new Point(x + ((level - 1) * rightChildIndent), y); + return new Point(x + (level * rightChildIndent), y); } - return getCellLocation(x, y + rowHeight, tree, mod, node, getNextVisibleNode(startNode)); } /** - * Paints a node in the tree Package private for use in inner classes. - * - * @param g - * the Graphics context in which to paint - * @param x - * the x location of the node - * @param y - * the y location of the node - * @param tree - * the tree to draw on - * @param node - * the object to draw - */ - void paintNode(Graphics g, int x, int y, JTree tree, Object node, - boolean isLeaf) - { - TreePath curr = new TreePath(getPathToRoot(node, 0)); - boolean selected = tree.isPathSelected(curr); - boolean expanded = false; - boolean hasIcons = false; - - if (tree.isVisible(curr)) - { - if (!isLeaf) - expanded = tree.isExpanded(curr); - - if (editingComponent != null && editingPath != null && isEditing(tree) - && node.equals(editingPath.getLastPathComponent())) - { - Rectangle bounds = getPathBounds(tree, editingPath); - rendererPane.paintComponent(g, editingComponent.getParent(), null, - new Rectangle(0, 0, bounds.width, - bounds.height)); - } - else - { - TreeCellRenderer dtcr = tree.getCellRenderer(); - if (dtcr == null) - dtcr = createDefaultCellRenderer(); - - int row = getRowForPath(tree, curr); - - Component c = dtcr.getTreeCellRendererComponent(tree, node, - selected, expanded, - isLeaf, row, false); - - rendererPane.paintComponent(g, c, c.getParent(), - getCellBounds(x, y, node)); - } - } - } - - /** * Recursively paints all elements of the tree Package private for use in * inner classes. * @@ -3065,8 +3129,6 @@ public class BasicTreeUI * of the current object * @param descent * is the number of elements drawn - * @param childNumber - * is the index of the current child in the tree * @param depth * is the depth of the current object in the tree * @param tree @@ -3077,71 +3139,79 @@ public class BasicTreeUI * is the current object to draw * @return int - current descent of the tree */ - int paintRecursive(Graphics g, int indentation, int descent, int childNumber, + int paintRecursive(Graphics g, int indentation, int descent, int depth, JTree tree, TreeModel mod, Object curr) { - Rectangle clip = g.getClipBounds(); + Rectangle clip = tree.getVisibleRect(); if (indentation > clip.x + clip.width + rightChildIndent || descent > clip.y + clip.height + getRowHeight()) return descent; + TreePath path = new TreePath(getPathToRoot(curr, 0)); int halfHeight = getRowHeight() / 2; int halfWidth = rightChildIndent / 2; int y0 = descent + halfHeight; int heightOfLine = descent + halfHeight; + int row = getRowForPath(tree, path); boolean isRootVisible = tree.isRootVisible(); - - if (mod.isLeaf(curr)) + boolean isExpanded = tree.isExpanded(path); + boolean isLeaf = mod.isLeaf(curr); + Rectangle bounds = getPathBounds(tree, path); + Object root = mod.getRoot(); + + if (isLeaf) { - paintNode(g, indentation + 4, descent, tree, curr, true); + paintRow(g, clip, null, bounds, path, row, true, false, true); descent += getRowHeight(); } else { if (depth > 0 || isRootVisible) { - paintNode(g, indentation + 4, descent, tree, curr, false); + paintRow(g, clip, null, bounds, path, row, isExpanded, false, false); descent += getRowHeight(); y0 += halfHeight; } - - int max = 0; - if (!mod.isLeaf(curr)) - max = mod.getChildCount(curr); - if (tree.isExpanded(new TreePath(getPathToRoot(curr, 0)))) + + if (isExpanded) { + int max = mod.getChildCount(curr); for (int i = 0; i < max; i++) { + Object child = mod.getChild(curr, i); + boolean childVis = tree.isVisible(new TreePath + (getPathToRoot(child, 0))); int indent = indentation + rightChildIndent; if (!isRootVisible && depth == 0) indent = 0; - else if ((!isRootVisible && !curr.equals(mod.getRoot())) - || isRootVisible) + else if (isRootVisible || + (!isRootVisible && !curr.equals(root)) && childVis) { g.setColor(getHashColor()); heightOfLine = descent + halfHeight; - g.drawLine(indentation + halfWidth, heightOfLine, - indentation + rightChildIndent, heightOfLine); + paintHorizontalLine(g, (JComponent) tree, heightOfLine, + indentation + halfWidth, indentation + rightChildIndent); } - descent = paintRecursive(g, indent, descent, i, depth + 1, - tree, mod, mod.getChild(curr, i)); + descent = paintRecursive(g, indent, descent, depth + 1, + tree, mod, child); } } } - if (tree.isExpanded(new TreePath(getPathToRoot(curr, 0)))) - if (y0 != heightOfLine && !mod.isLeaf(curr) - && mod.getChildCount(curr) > 0) + if (isExpanded) + if (y0 != heightOfLine + && (mod.getChildCount(curr) > 0 && + tree.isVisible(new TreePath(getPathToRoot(mod.getChild + (curr, 0), 0))))) { g.setColor(getHashColor()); - g.drawLine(indentation + halfWidth, y0, indentation + halfWidth, - heightOfLine); + paintVerticalLine(g, (JComponent) tree, indentation + halfWidth, y0, + heightOfLine); } - return descent; } - + /** * Recursively paints all the control icons on the tree. Package private for * use in inner classes. @@ -3152,76 +3222,99 @@ public class BasicTreeUI * of the current object * @param descent * is the number of elements drawn - * @param childNumber - * is the index of the current child in the tree * @param depth * is the depth of the current object in the tree * @param tree * is the tree to draw to * @param mod * is the TreeModel we are using to draw - * @param curr + * @param node * is the current object to draw - * @return int - current descent of the tree + * @return int current descent of the tree */ int paintControlIcons(Graphics g, int indentation, int descent, - int childNumber, int depth, JTree tree, TreeModel mod, + int depth, JTree tree, TreeModel mod, Object node) { - int h = descent; int rowHeight = getRowHeight(); - Icon ei = UIManager.getLookAndFeelDefaults().getIcon("Tree.expandedIcon"); - Icon ci = UIManager.getLookAndFeelDefaults().getIcon("Tree.collapsedIcon"); - Rectangle clip = g.getClipBounds(); + TreePath path = new TreePath(getPathToRoot(node, 0)); + Icon icon = getCurrentControlIcon(path); + + Rectangle clip = tree.getVisibleRect(); if (indentation > clip.x + clip.width + rightChildIndent || descent > clip.y + clip.height + getRowHeight()) return descent; - + if (mod.isLeaf(node)) descent += rowHeight; else - { + { + if (!node.equals(mod.getRoot()) && + (tree.isRootVisible() || getLevel(node) != 1)) + { + int width = icon.getIconWidth(); + int height = icon.getIconHeight() + 2; + int posX = indentation - rightChildIndent; + int posY = descent; + if (width > rightChildIndent) + posX -= gap; + else posX += width/2; + + if (height < rowHeight) + posY += height/2; + + icon.paintIcon(tree, g, posX, posY); + } + if (depth > 0 || tree.isRootVisible()) descent += rowHeight; - - int max = 0; - if (!mod.isLeaf(node)) - max = mod.getChildCount(node); - if (tree.isExpanded(new TreePath(getPathToRoot(node, 0)))) + + if (tree.isExpanded(path)) { - if (!node.equals(mod.getRoot())) - ei.paintIcon(tree, g, indentation - rightChildIndent - 3, h); - + int max = 0; + if (!mod.isLeaf(node)) + max = mod.getChildCount(node); + for (int i = 0; i < max; i++) { int indent = indentation + rightChildIndent; + Object child = mod.getChild(node, i); if (depth == 0 && !tree.isRootVisible()) - indent = -1; - - descent = paintControlIcons(g, indent, descent, i, depth + 1, - tree, mod, mod.getChild(node, i)); + indent = 1; + if (tree.isVisible(new TreePath(getPathToRoot(child, 0)))) + descent = paintControlIcons(g, indent, descent, depth + 1, + tree, mod, child); } } - else if (!node.equals(mod.getRoot())) - ci.paintIcon(tree, g, indentation - rightChildIndent - 3, - descent - getRowHeight()); } - + return descent; } /** - * Returns true if the LookAndFeel implements the control icons Package + * Returns true if the LookAndFeel implements the control icons. Package * private for use in inner classes. * - * @return true if control icons are visible + * @returns true if there are control icons */ boolean hasControlIcons() { - if (UIManager.getLookAndFeelDefaults().getIcon("Tree.expandedIcon") == null - || UIManager.getLookAndFeelDefaults().getIcon("Tree.collapsedIcon") == null) - return false; - return true; + if (expandedIcon != null || collapsedIcon != null) + return true; + return false; + } + + /** + * Returns control icon. It is null if the LookAndFeel does not implements the + * control icons. Package private for use in inner classes. + * + * @return control icon if it exists. + */ + Icon getCurrentControlIcon(TreePath path) + { + if (tree.isExpanded(path)) + return expandedIcon; + return collapsedIcon; } /** @@ -3235,8 +3328,10 @@ public class BasicTreeUI */ Object getParent(Object root, Object node) { - if (root == null || node == null) + if (root == null || node == null || + root.equals(node)) return null; + if (node instanceof TreeNode) return ((TreeNode) node).getParent(); return findNode(root, node); @@ -3253,113 +3348,69 @@ public class BasicTreeUI */ private Object findNode(Object root, Object node) { - TreeModel mod = tree.getModel(); - int size = 0; - if (!mod.isLeaf(root)) - size = mod.getChildCount(root); - for (int i = 0; i < size; i++) - { - if (mod.getIndexOfChild(root, node) != -1) - return root; - - Object n = findNode(mod.getChild(root, i), node); - if (n != null) - return n; - } - return null; - } - - /** - * Get next visible node in the tree. Package private for use in inner - * classes. - * - * @param the - * current node - * @return the next visible node in the JTree. Return null if there are no - * more. - */ - Object getNextVisibleNode(Object node) - { - Object next = null; - TreePath current = null; - - if (node != null) - next = getNextNode(node); - - if (next != null) + if (!treeModel.isLeaf(root) && !root.equals(node)) { - current = new TreePath(getPathToRoot(next, 0)); - if (tree.isVisible(current)) - return next; - - while (next != null && !tree.isVisible(current)) + int size = treeModel.getChildCount(root); + for (int j = 0; j < size; j++) { - next = getNextNode(next); + Object child = treeModel.getChild(root, j); + if (node.equals(child)) + return root; - if (next != null) - current = new TreePath(getPathToRoot(next, 0)); + Object n = findNode(child, node); + if (n != null) + return n; } } - return next; + return null; } - + /** * Get previous visible node in the tree. Package private for use in inner * classes. * - * @param the + * @param node - * current node * @return the next visible node in the JTree. Return null if there are no * more. */ Object getPreviousVisibleNode(Object node) { - Object prev = null; - TreePath current = null; - - if (node != null) - prev = getPreviousNode(node); - - if (prev != null) + updateCurrentVisiblePath(); + if (currentVisiblePath != null) { - current = new TreePath(getPathToRoot(prev, 0)); - if (tree.isVisible(current)) - return prev; - - while (prev != null && !tree.isVisible(current)) - { - prev = getPreviousNode(prev); - - if (prev != null) - current = new TreePath(getPathToRoot(prev, 0)); - } + Object[] nodes = currentVisiblePath.getPath(); + int i = 0; + while (i < nodes.length && !node.equals(nodes[i])) + i++; + // return the next node + if (i-1 >= 0) + return nodes[i-1]; } - return prev; + return null; } /** * Returns the next node in the tree Package private for use in inner classes. * - * @param the + * @param curr - * current node * @return the next node in the tree */ Object getNextNode(Object curr) { - TreeModel mod = tree.getModel(); - if (!mod.isLeaf(curr) && mod.getChildCount(curr) > 0) - return mod.getChild(curr, 0); + if (!treeModel.isLeaf(curr) && treeModel.getChildCount(curr) > 0) + return treeModel.getChild(curr, 0); Object node = curr; Object sibling = null; - do { sibling = getNextSibling(node); - node = getParent(mod.getRoot(), node); + node = getParent(treeModel.getRoot(), node); } while (sibling == null && node != null); - + return sibling; } @@ -3367,14 +3418,13 @@ public class BasicTreeUI * Returns the previous node in the tree Package private for use in inner * classes. * - * @param the + * @param node * current node * @return the previous node in the tree */ Object getPreviousNode(Object node) { - TreeModel mod = tree.getModel(); - Object parent = getParent(mod.getRoot(), node); + Object parent = getParent(treeModel.getRoot(), node); if (parent == null) return null; @@ -3384,13 +3434,13 @@ public class BasicTreeUI return parent; int size = 0; - if (!mod.isLeaf(sibling)) - size = mod.getChildCount(sibling); + if (!treeModel.isLeaf(sibling)) + size = treeModel.getChildCount(sibling); while (size > 0) { - sibling = mod.getChild(sibling, size - 1); - if (!mod.isLeaf(sibling)) - size = mod.getChildCount(sibling); + sibling = treeModel.getChild(sibling, size - 1); + if (!treeModel.isLeaf(sibling)) + size = treeModel.getChildCount(sibling); else size = 0; } @@ -3402,52 +3452,50 @@ public class BasicTreeUI * Returns the next sibling in the tree Package private for use in inner * classes. * - * @param the + * @param node - * current node * @return the next sibling in the tree */ Object getNextSibling(Object node) { - TreeModel mod = tree.getModel(); - Object parent = getParent(mod.getRoot(), node); + Object parent = getParent(treeModel.getRoot(), node); if (parent == null) return null; - int index = mod.getIndexOfChild(parent, node) + 1; + int index = treeModel.getIndexOfChild(parent, node) + 1; int size = 0; - if (!mod.isLeaf(parent)) - size = mod.getChildCount(parent); + if (!treeModel.isLeaf(parent)) + size = treeModel.getChildCount(parent); if (index == 0 || index >= size) return null; - return mod.getChild(parent, index); + return treeModel.getChild(parent, index); } - + /** * Returns the previous sibling in the tree Package private for use in inner * classes. * - * @param the + * @param node - * current node * @return the previous sibling in the tree */ Object getPreviousSibling(Object node) { - TreeModel mod = tree.getModel(); - Object parent = getParent(mod.getRoot(), node); + Object parent = getParent(treeModel.getRoot(), node); if (parent == null) return null; - int index = mod.getIndexOfChild(parent, node) - 1; + int index = treeModel.getIndexOfChild(parent, node) - 1; int size = 0; - if (!mod.isLeaf(parent)) - size = mod.getChildCount(parent); + if (!treeModel.isLeaf(parent)) + size = treeModel.getChildCount(parent); if (index < 0 || index >= size) return null; - return mod.getChild(parent, index); + return treeModel.getChild(parent, index); } /** @@ -3463,22 +3511,24 @@ public class BasicTreeUI { if (path != null) { - if (tree.getSelectionModel().getSelectionMode() == TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION) + 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) + else if (tree.getSelectionModel().getSelectionMode() == + TreeSelectionModel.CONTIGUOUS_TREE_SELECTION) { // TODO } else { - tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); - - tree.getSelectionModel().clearSelection(); tree.addSelectionPath(path); tree.setLeadSelectionPath(path); + tree.getSelectionModel().setSelectionMode + (TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); } } } @@ -3495,7 +3545,6 @@ public class BasicTreeUI */ Object[] getPathToRoot(Object node, int depth) { - TreeModel mod = tree.getModel(); if (node == null) { if (depth == 0) @@ -3504,7 +3553,7 @@ public class BasicTreeUI return new Object[depth]; } - Object[] path = getPathToRoot(getParent(mod.getRoot(), node), depth + 1); + Object[] path = getPathToRoot(getParent(treeModel.getRoot(), node), depth + 1); path[path.length - depth - 1] = node; return path; } @@ -3512,22 +3561,23 @@ public class BasicTreeUI /** * Returns the level of the node in the tree. * - * @param the + * @param node - * current node * @return the number of the level */ int getLevel(Object node) { int count = -1; + Object current = node; do { - current = getParent(tree.getModel().getRoot(), current); + current = getParent(treeModel.getRoot(), current); count++; } while (current != null); - + return count; } @@ -3586,10 +3636,271 @@ public class BasicTreeUI * is the center position in y-direction FIXME what to do if x < * (icon.width / 2). Same with y */ - protected void drawCentered(JComponent c, Graphics g, Icon icon, int x, int y) + protected void drawCentered(Component c, Graphics g, Icon icon, int x, int y) { int beginPositionX = x - icon.getIconWidth() / 2; int beginPositionY = y - icon.getIconHeight() / 2; icon.paintIcon(c, g, beginPositionX, beginPositionY); } + + /** + * Draws a dashed horizontal line. + * + * @param g - the graphics configuration. + * @param y - the y location to start drawing at + * @param x1 - the x location to start drawing at + * @param x2 - the x location to finish drawing at + */ + protected void drawDashedHorizontalLine(Graphics g, int y, int x1, int x2) + { + for (int i = x1; i < x2; i += 2) + g.drawLine(i, y, i + 1, y); + } + + /** + * Draws a dashed vertical line. + * + * @param g - the graphics configuration. + * @param x - the x location to start drawing at + * @param y1 - the y location to start drawing at + * @param y2 - the y location to finish drawing at + */ + protected void drawDashedVerticalLine(Graphics g, int x, int y1, int y2) + { + for (int i = y1; i < y2; i += 2) + g.drawLine(x, i, x, i + 1); + } + + /** + * Paints the expand (toggle) part of a row. The receiver should NOT modify + * clipBounds, or insets. + * + * @param g - the graphics configuration + * @param clipBounds - + * @param insets - + * @param bounds - bounds of expand control + * @param path - path to draw control for + * @param row - row to draw control for + * @param isExpanded - is the row expanded + * @param hasBeenExpanded - has the row already been expanded + * @param isLeaf - is the path a leaf + */ + protected void paintExpandControl(Graphics g, Rectangle clipBounds, + Insets insets, Rectangle bounds, + TreePath path, int row, + boolean isExpanded, boolean hasBeenExpanded, + boolean isLeaf) + { + if (treeModel != null && hasControlIcons()) + paintControlIcons(g, 0, 0, 0, tree, treeModel, path.getLastPathComponent()); + } + + /** + * Paints the horizontal part of the leg. The receiver should NOT modify + * clipBounds, or insets. + * NOTE: parentRow can be -1 if the root is not visible. + * + * @param g - the graphics configuration + * @param clipBounds - + * @param insets - + * @param bounds - bounds of expand control + * @param path - path to draw control for + * @param row - row to draw control for + * @param isExpanded - is the row expanded + * @param hasBeenExpanded - has the row already been expanded + * @param isLeaf - is the path a leaf + */ + protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds, + Insets insets, Rectangle bounds, + TreePath path, int row, + boolean isExpanded, boolean hasBeenExpanded, + boolean isLeaf) + { + // FIXME: not implemented + } + + /** + * Paints the vertical part of the leg. The receiver should NOT modify + * clipBounds, insets. + * + * @param g - the graphics configuration. + * @param clipBounds - + * @param insets - + * @param path - the path to draw the vertical part for. + */ + protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds, + Insets insets, TreePath path) + { + // FIXME: not implemented + } + + /** + * Paints the renderer part of a row. The receiver should NOT modify clipBounds, + * or insets. + * + * @param g - the graphics configuration + * @param clipBounds - + * @param insets - + * @param bounds - bounds of expand control + * @param path - path to draw control for + * @param row - row to draw control for + * @param isExpanded - is the row expanded + * @param hasBeenExpanded - has the row already been expanded + * @param isLeaf - is the path a leaf + */ + protected void paintRow(Graphics g, Rectangle clipBounds, + Insets insets, Rectangle bounds, + TreePath path, int row, + boolean isExpanded, boolean hasBeenExpanded, + boolean isLeaf) + { + boolean selected = tree.isPathSelected(path); + boolean hasIcons = false; + Object node = path.getLastPathComponent(); + + if (tree.isVisible(path)) + { + if (!validCachedPreferredSize) + updateCachedPreferredSize(); + bounds.x += gap; + bounds.width = preferredSize.width + bounds.x; + + if (editingComponent != null && editingPath != null && isEditing(tree) + && node.equals(editingPath.getLastPathComponent())) + { + rendererPane.paintComponent(g, editingComponent.getParent(), null, + bounds); + } + else + { + TreeCellRenderer dtcr = tree.getCellRenderer(); + if (dtcr == null) + dtcr = createDefaultCellRenderer(); + + Component c = dtcr.getTreeCellRendererComponent(tree, node, + selected, isExpanded, isLeaf, row, tree.hasFocus()); + rendererPane.paintComponent(g, c, c.getParent(), bounds); + } + } + } + + /** + * Prepares for the UI to uninstall. + */ + protected void prepareForUIUninstall() + { + // TODO: Implement this properly. + } + + /** + * Returns true if the expand (toggle) control should be drawn for the + * specified row. + * + * @param path - current path to check for. + * @param row - current row to check for. + * @param isExpanded - true if the path is expanded + * @param hasBeenExpanded - true if the path has been expanded already + * @param isLeaf - true if the row is a lead + */ + protected boolean shouldPaintExpandControl(TreePath path, int row, + boolean isExpanded, + boolean hasBeenExpanded, + boolean isLeaf) + { + Object node = path.getLastPathComponent(); + if (treeModel != null && (!isLeaf && !node.equals(treeModel.getRoot())) && + (tree.isRootVisible() || getLevel(node) != 1)) + return true; + return false; + } + + /** + * Updates the cached current TreePath of all visible + * nodes in the tree. + */ + void updateCurrentVisiblePath() + { + if (treeModel == null) + return; + + Object next = treeModel.getRoot(); + Rectangle bounds = getCellBounds(0, 0, next); + boolean rootVisible = isRootVisible(); + + // If root is not a valid size to be visible, or is + // not visible and the tree is expanded, then the next node acts + // as the root + if ((bounds.width == 0 && bounds.height == 0) || (!rootVisible + && tree.isExpanded(new TreePath(next)))) + next = getNextNode(next); + + Object root = next; + TreePath current = null; + while (next != null) + { + if (current == null) + current = new TreePath(next); + else + current = current.pathByAddingChild(next); + do + { + TreePath path = new TreePath(getPathToRoot(next, 0)); + if ((tree.isVisible(path) && tree.isExpanded(path)) + || treeModel.isLeaf(next)) + next = getNextNode(next); + else + { + Object pNext = next; + next = getNextSibling(pNext); + // if no next sibling, check parent's next sibling. + if (next == null) + { + Object parent = getParent(root, pNext); + while (next == null && parent != null) + { + next = getNextSibling(parent); + if (next == null) + parent = getParent(treeModel.getRoot(), next); + } + } + } + } + while (next != null && + !tree.isVisible(new TreePath(getPathToRoot(next, 0)))); + } + + currentVisiblePath = current; + if (currentVisiblePath != null) + tree.setVisibleRowCount(currentVisiblePath.getPathCount()); + else tree.setVisibleRowCount(0); + + if (tree.getSelectionModel() != null && tree.getSelectionCount() == 0 && + currentVisiblePath != null) + selectPath(tree, new TreePath(getPathToRoot(currentVisiblePath. + getPathComponent(0), 0))); + } + + /** + * Get next visible node in the currentVisiblePath. Package private for use in + * inner classes. + * + * @param node + * current node + * @return the next visible node in the JTree. Return null if there are no + * more. + */ + Object getNextVisibleNode(Object node) + { + if (currentVisiblePath != null) + { + Object[] nodes = currentVisiblePath.getPath(); + int i = 0; + while (i < nodes.length && !node.equals(nodes[i])) + i++; + // return the next node + if (i+1 < nodes.length) + return nodes[i+1]; + } + return null; + } } // BasicTreeUI diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java index 0d461332a70..51b902d6443 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java @@ -38,61 +38,22 @@ exception statement from your version. */ package javax.swing.plaf.basic; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Image; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.image.ImageObserver; - import javax.swing.JComponent; -import javax.swing.JViewport; -import javax.swing.ViewportLayout; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; +import javax.swing.LookAndFeel; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ViewportUI; public class BasicViewportUI extends ViewportUI { - - ChangeListener changeListener; - Image backingStoreImage; - int backingStoreWidth = -1; - int backingStoreHeight = -1; - - class ChangeHandler implements ChangeListener + protected void installDefaults(JComponent c) { - public void stateChanged(ChangeEvent event) - { - JViewport v = (JViewport) event.getSource(); - v.repaint(); - } - } - - void installDefaults(JComponent c) - { c.setOpaque(true); + LookAndFeel.installColorsAndFont(c, "Viewport.background", + "Viewport.foreground", "Viewport.font"); } - - void uninstallDefaults(JComponent c) - { - } - - void installListeners(JComponent c) + protected void uninstallDefaults(JComponent c) { - ((JViewport)c).addChangeListener(changeListener); - } - - void uninstallListeners(JComponent c) - { - ((JViewport)c).removeChangeListener(changeListener); - } - - public BasicViewportUI() - { - changeListener = new ChangeHandler(); + // TODO: Implement this properly. } public static ComponentUI createUI(JComponent c) @@ -103,132 +64,12 @@ public class BasicViewportUI extends ViewportUI public void installUI(JComponent c) { super.installUI(c); - installListeners(c); + installDefaults(c); } public void uninstallUI(JComponent c) { - uninstallListeners(c); - } - - - public Dimension getPreferredSize(JComponent c) - { - // let the ViewportLayout decide - return null; - } - - public void paint(Graphics g, JComponent c) - { - JViewport port = (JViewport)c; - Component view = port.getView(); - - if (view == null) - return; - - Point pos = port.getViewPosition(); - Rectangle viewBounds = view.getBounds(); - Rectangle portBounds = port.getBounds(); - - if (viewBounds.width == 0 - || viewBounds.height == 0 - || portBounds.width == 0 - || portBounds.height == 0) - return; - - switch (port.getScrollMode()) - { - - case JViewport.BACKINGSTORE_SCROLL_MODE: - paintBackingStore(g, port, view, pos, viewBounds, portBounds); - break; - - case JViewport.BLIT_SCROLL_MODE: - // FIXME: implement separate blit mode - - case JViewport.SIMPLE_SCROLL_MODE: - default: - paintSimple(g, port, view, pos, viewBounds, portBounds); - break; - } - } - - private void paintSimple(Graphics g, - JViewport v, - Component view, - Point pos, - Rectangle viewBounds, - Rectangle portBounds) - { - Rectangle oldClip = g.getClipBounds(); - g.setClip(new Rectangle(0, 0, portBounds.width, portBounds.height)); - g.translate (-pos.x, -pos.y); - try - { - view.paint(g); - } - finally - { - g.translate (pos.x, pos.y); - g.setClip (oldClip); - } - } - - private void paintBackingStore(Graphics g, - JViewport v, - Component view, - Point pos, - Rectangle viewBounds, - Rectangle portBounds) - { - if (backingStoreImage == null - || backingStoreWidth != viewBounds.width - || backingStoreHeight != viewBounds.height) - { - backingStoreImage = v.createImage(viewBounds.width, viewBounds.height); - backingStoreWidth = viewBounds.width; - backingStoreHeight = viewBounds.height; - } - - Graphics g2 = backingStoreImage.getGraphics(); - - if (v.getBackground() != null) - { - // fill the backing store background - java.awt.Color save = g2.getColor(); - g2.setColor(v.getBackground()); - g2.fillRect (0, 0, backingStoreWidth, backingStoreHeight); - g2.setColor(save); - - // fill the viewport background - save = g.getColor(); - g.setColor(v.getBackground()); - g.fillRect (0, 0, portBounds.width, portBounds.height); - g.setColor(save); - - } - else - { - // clear the backing store background - g2.clearRect(0, 0, backingStoreWidth, backingStoreHeight); - - // clear the viewport background - g.clearRect(0, 0, portBounds.width, portBounds.height); - } - - g2.setClip(g.getClipBounds()); - g2.translate(-pos.x, -pos.y); - try - { - view.paint(g2); - } - finally - { - g2.translate(pos.x, pos.y); - } - g2 = null; - g.drawImage(backingStoreImage, - 0, 0, - (ImageObserver)null); + super.uninstallUI(c); + uninstallDefaults(c); } } |