/* * @(#)MotifBorders.java 1.36 03/12/19 * * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package com.sun.java.swing.plaf.motif; import com.sun.java.swing.SwingUtilities2; import javax.swing.*; import javax.swing.border.*; import javax.swing.plaf.*; import java.awt.Color; import java.awt.Component; 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.io.Serializable; /** * Factory object that can vend Icons appropriate for the basic L & F. *
* Warning: * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is appropriate * for short term storage or RMI between applications running the same * version of Swing. A future release of Swing will provide support for * long term persistence. * * @version 1.36 12/19/03 * @author Amy Fowler */ public class MotifBorders { public static class BevelBorder extends AbstractBorder implements UIResource { private Color darkShadow = UIManager.getColor("controlShadow"); private Color lightShadow = UIManager.getColor("controlLtHighlight"); private boolean isRaised; public BevelBorder(boolean isRaised, Color darkShadow, Color lightShadow) { this.isRaised = isRaised; this.darkShadow = darkShadow; this.lightShadow = lightShadow; } public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { g.setColor((isRaised) ? lightShadow : darkShadow); g.drawLine(x, y, x+w-1, y); // top g.drawLine(x, y+h-1, x, y+1); // left g.setColor((isRaised) ? darkShadow : lightShadow); g.drawLine(x+1, y+h-1, x+w-1, y+h-1); // bottom g.drawLine(x+w-1, y+h-1, x+w-1, y+1); // right } public Insets getBorderInsets(Component c) { return getBorderInsets(c, new Insets(0,0,0,0)); } public Insets getBorderInsets(Component c, Insets insets) { insets.top = insets.left = insets.bottom = insets.right = 1; return insets; } public boolean isOpaque(Component c) { return true; } } public static class FocusBorder extends AbstractBorder implements UIResource { private Color focus; private Color control; public FocusBorder(Color control, Color focus) { this.control = control; this.focus = focus; } public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { if (((JComponent)c).hasFocus()) { g.setColor(focus); g.drawRect(x, y, w-1, h-1); } else { g.setColor(control); g.drawRect(x, y, w-1, h-1); } } public Insets getBorderInsets(Component c) { return getBorderInsets(c, new Insets(0,0,0,0)); } public Insets getBorderInsets(Component c, Insets insets) { insets.top = insets.left = insets.bottom = insets.right = 1; return insets; } } public static class ButtonBorder extends AbstractBorder implements UIResource { protected Color focus = UIManager.getColor("activeCaptionBorder"); protected Color shadow = UIManager.getColor("Button.shadow"); protected Color highlight = UIManager.getColor("Button.light"); protected Color darkShadow; public ButtonBorder(Color shadow, Color highlight, Color darkShadow, Color focus) { this.shadow = shadow; this.highlight = highlight; this.darkShadow = darkShadow; this.focus = focus; } public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { boolean isPressed = false; boolean hasFocus = false; boolean canBeDefault = false; boolean isDefault = false; if (c instanceof AbstractButton) { AbstractButton b = (AbstractButton)c; ButtonModel model = b.getModel(); isPressed = (model.isArmed() && model.isPressed()); hasFocus = (model.isArmed() && isPressed) || (b.isFocusPainted() && b.hasFocus()); if (b instanceof JButton) { canBeDefault = ((JButton)b).isDefaultCapable(); isDefault = ((JButton)b).isDefaultButton(); } } int bx1 = x+1; int by1 = y+1; int bx2 = x+w-2; int by2 = y+h-2; if (canBeDefault) { if (isDefault) { g.setColor(shadow); g.drawLine(x+3, y+3, x+3, y+h-4); g.drawLine(x+3, y+3, x+w-4, y+3); g.setColor(highlight); g.drawLine(x+4, y+h-4, x+w-4, y+h-4); g.drawLine(x+w-4, y+3, x+w-4, y+h-4); } bx1 +=6; by1 += 6; bx2 -= 6; by2 -= 6; } if (hasFocus) { g.setColor(focus); if (isDefault) { g.drawRect(x, y, w-1, h-1); } else { g.drawRect(bx1-1, by1-1, bx2-bx1+2, by2-by1+2); } } g.setColor(isPressed? shadow : highlight); g.drawLine(bx1, by1, bx2, by1); g.drawLine(bx1, by1, bx1, by2); g.setColor(isPressed? highlight : shadow); g.drawLine(bx2, by1+1, bx2, by2); g.drawLine(bx1+1, by2, bx2, by2); } public Insets getBorderInsets(Component c) { return getBorderInsets(c, new Insets(0,0,0,0)); } public Insets getBorderInsets(Component c, Insets insets) { int thickness = (c instanceof JButton && ((JButton)c).isDefaultCapable())? 8 : 2; insets.top = insets.left = insets.bottom = insets.right = thickness; return insets; } } public static class ToggleButtonBorder extends ButtonBorder { public ToggleButtonBorder(Color shadow, Color highlight, Color darkShadow, Color focus) { super(shadow, highlight, darkShadow, focus); } public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { if (c instanceof AbstractButton) { AbstractButton b = (AbstractButton)c; ButtonModel model = b.getModel(); if (model.isArmed() && model.isPressed() || model.isSelected()) { drawBezel(g, x, y, width, height, (model.isPressed() || model.isSelected()), b.isFocusPainted() && b.hasFocus(), shadow, highlight, darkShadow, focus); } else { drawBezel(g, x, y, width, height, false, b.isFocusPainted() && b.hasFocus(), shadow, highlight, darkShadow, focus); } } else { drawBezel(g, x, y, width, height, false, false, shadow, highlight, darkShadow, focus); } } public Insets getBorderInsets(Component c) { return new Insets(2, 2, 3, 3); } public Insets getBorderInsets(Component c, Insets insets) { insets.top = insets.left = 2; insets.bottom = insets.right = 3; return insets; } } public static class MenuBarBorder extends ButtonBorder { public MenuBarBorder(Color shadow, Color highlight, Color darkShadow, Color focus) { super(shadow, highlight, darkShadow, focus); } public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { JMenuBar menuBar = (JMenuBar)c; if (menuBar.isBorderPainted() == true) { // this draws the MenuBar border Dimension size = menuBar.getSize(); drawBezel(g,x,y,size.width,size.height,false,false, shadow, highlight, darkShadow, focus); } } public Insets getBorderInsets(Component c) { return getBorderInsets(c, new Insets(0,0,0,0)); } public Insets getBorderInsets(Component c, Insets insets) { insets.top = insets.left = insets.bottom = insets.right = 6; return insets; } } public static class FrameBorder extends AbstractBorder implements UIResource { JComponent jcomp; Color frameHighlight; Color frameColor; Color frameShadow; // The width of the border public final static int BORDER_SIZE = 5; /** Constructs an FrameBorder for the JComponent comp. */ public FrameBorder(JComponent comp) { jcomp = comp; } /** Sets the FrameBorder's JComponent. */ public void setComponent(JComponent comp) { jcomp = comp; } /** Returns the FrameBorder's JComponent. * @see #setComponent */ public JComponent component() { return jcomp; } protected Color getFrameHighlight() { return frameHighlight; } protected Color getFrameColor() { return frameColor; } protected Color getFrameShadow() { return frameShadow; } static Insets insets = new Insets(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE); public Insets getBorderInsets(Component c) { return insets; } public Insets getBorderInsets(Component c, Insets newInsets) { newInsets.top = insets.top; newInsets.left = insets.left; newInsets.bottom = insets.bottom; newInsets.right = insets.right; return newInsets; } /** Draws the FrameBorder's top border. */ protected boolean drawTopBorder(Component c, Graphics g, int x, int y, int width, int height) { Rectangle titleBarRect = new Rectangle(x, y, width, BORDER_SIZE); if (!g.getClipBounds().intersects(titleBarRect)) { return false; } int maxX = width - 1; int maxY = BORDER_SIZE - 1; // Draw frame g.setColor(frameColor); g.drawLine(x, y + 2, maxX - 2, y + 2); g.drawLine(x, y + 3, maxX - 2, y + 3); g.drawLine(x, y + 4, maxX - 2, y + 4); // Draw highlights g.setColor(frameHighlight); g.drawLine(x, y, maxX, y); g.drawLine(x, y + 1, maxX, y + 1); g.drawLine(x, y + 2, x, y + 4); g.drawLine(x + 1, y + 2, x + 1, y + 4); // Draw shadows g.setColor(frameShadow); g.drawLine(x + 4, y + 4, maxX - 4, y + 4); g.drawLine(maxX, y + 1, maxX, maxY); g.drawLine(maxX - 1, y + 2, maxX - 1, maxY); return true; } /** Draws the FrameBorder's left border. */ protected boolean drawLeftBorder(Component c, Graphics g, int x, int y, int width, int height) { Rectangle borderRect = new Rectangle(0, 0, getBorderInsets(c).left, height); if (!g.getClipBounds().intersects(borderRect)) { return false; } int startY = BORDER_SIZE; g.setColor(frameHighlight); g.drawLine(x, startY, x, height - 1); g.drawLine(x + 1, startY, x + 1, height - 2); g.setColor(frameColor); g.fillRect(x + 2, startY, x + 2, height - 3); g.setColor(frameShadow); g.drawLine(x + 4, startY, x + 4, height - 5); return true; } /** Draws the FrameBorder's right border. */ protected boolean drawRightBorder(Component c, Graphics g, int x, int y, int width, int height) { Rectangle borderRect = new Rectangle( width - getBorderInsets(c).right, 0, getBorderInsets(c).right, height); if (!g.getClipBounds().intersects(borderRect)) { return false; } int startX = width - getBorderInsets(c).right; int startY = BORDER_SIZE; g.setColor(frameColor); g.fillRect(startX + 1, startY, 2, height - 1); g.setColor(frameShadow); g.fillRect(startX + 3, startY, 2, height - 1); g.setColor(frameHighlight); g.drawLine(startX, startY, startX, height - 1); return true; } /** Draws the FrameBorder's bottom border. */ protected boolean drawBottomBorder(Component c, Graphics g, int x, int y, int width, int height) { Rectangle borderRect; int marginHeight, startY; borderRect = new Rectangle(0, height - getBorderInsets(c).bottom, width, getBorderInsets(c).bottom); if (!g.getClipBounds().intersects(borderRect)) { return false; } startY = height - getBorderInsets(c).bottom; g.setColor(frameShadow); g.drawLine(x + 1, height - 1, width - 1, height - 1); g.drawLine(x + 2, height - 2, width - 2, height - 2); g.setColor(frameColor); g.fillRect(x + 2, startY + 1, width - 4, 2); g.setColor(frameHighlight); g.drawLine(x + 5, startY, width - 5, startY); return true; } // Returns true if the associated component has focus. protected boolean isActiveFrame() { return jcomp.hasFocus(); } /** Draws the FrameBorder in the given Rect. Calls * drawTitleBar, drawLeftBorder, drawRightBorder and * drawBottomBorder. */ public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { if (isActiveFrame()) { frameColor = UIManager.getColor("activeCaptionBorder"); } else { frameColor = UIManager.getColor("inactiveCaptionBorder"); } frameHighlight = frameColor.brighter(); frameShadow = frameColor.darker().darker(); drawTopBorder(c, g, x, y, width, height); drawLeftBorder(c, g, x, y, width, height); drawRightBorder(c, g, x, y, width, height); drawBottomBorder(c, g, x, y, width, height); } } public static class InternalFrameBorder extends FrameBorder { JInternalFrame frame; // The size of the bounding box for Motif frame corners. public final static int CORNER_SIZE = 24; /** Constructs an InternalFrameBorder for the InternalFrame * aFrame. */ public InternalFrameBorder(JInternalFrame aFrame) { super(aFrame); frame = aFrame; } /** Sets the InternalFrameBorder's InternalFrame. */ public void setFrame(JInternalFrame aFrame) { frame = aFrame; } /** Returns the InternalFrameBorder's InternalFrame. * @see #setFrame */ public JInternalFrame frame() { return frame; } /** Returns the width of the InternalFrameBorder's resize controls, * appearing along the InternalFrameBorder's bottom border. Clicking * and dragging within these controls lets the user change both the * InternalFrame's width and height, while dragging between the controls * constrains resizing to just the vertical dimension. Override this * method if you implement your own bottom border painting and use a * resize control with a different size. */ public int resizePartWidth() { if (!frame.isResizable()) { return 0; } return FrameBorder.BORDER_SIZE; } /** Draws the InternalFrameBorder's top border. */ protected boolean drawTopBorder(Component c, Graphics g, int x, int y, int width, int height) { if (super.drawTopBorder(c, g, x, y, width, height) && frame.isResizable()) { g.setColor(getFrameShadow()); g.drawLine(CORNER_SIZE - 1, y + 1, CORNER_SIZE - 1, y + 4); g.drawLine(width - CORNER_SIZE - 1, y + 1, width - CORNER_SIZE - 1, y + 4); g.setColor(getFrameHighlight()); g.drawLine(CORNER_SIZE, y, CORNER_SIZE, y + 4); g.drawLine(width - CORNER_SIZE, y, width - CORNER_SIZE, y + 4); return true; } return false; } /** Draws the InternalFrameBorder's left border. */ protected boolean drawLeftBorder(Component c, Graphics g, int x, int y, int width, int height) { if (super.drawLeftBorder(c, g, x, y, width, height) && frame.isResizable()) { g.setColor(getFrameHighlight()); int topY = y + CORNER_SIZE; g.drawLine(x, topY, x + 4, topY); int bottomY = height - CORNER_SIZE; g.drawLine(x + 1, bottomY, x + 5, bottomY); g.setColor(getFrameShadow()); g.drawLine(x + 1, topY - 1, x + 5, topY - 1); g.drawLine(x + 1, bottomY - 1, x + 5, bottomY - 1); return true; } return false; } /** Draws the InternalFrameBorder's right border. */ protected boolean drawRightBorder(Component c, Graphics g, int x, int y, int width, int height) { if (super.drawRightBorder(c, g, x, y, width, height) && frame.isResizable()) { int startX = width - getBorderInsets(c).right; g.setColor(getFrameHighlight()); int topY = y + CORNER_SIZE; g.drawLine(startX, topY, width - 2, topY); int bottomY = height - CORNER_SIZE; g.drawLine(startX + 1, bottomY, startX + 3, bottomY); g.setColor(getFrameShadow()); g.drawLine(startX + 1, topY - 1, width - 2, topY - 1); g.drawLine(startX + 1, bottomY - 1, startX + 3, bottomY - 1); return true; } return false; } /** Draws the InternalFrameBorder's bottom border. */ protected boolean drawBottomBorder(Component c, Graphics g, int x, int y, int width, int height) { if (super.drawBottomBorder(c, g, x, y, width, height) && frame.isResizable()) { int startY = height - getBorderInsets(c).bottom; g.setColor(getFrameShadow()); g.drawLine(CORNER_SIZE - 1, startY + 1, CORNER_SIZE - 1, height - 1); g.drawLine(width - CORNER_SIZE, startY + 1, width - CORNER_SIZE, height - 1); g.setColor(getFrameHighlight()); g.drawLine(CORNER_SIZE, startY, CORNER_SIZE, height - 2); g.drawLine(width - CORNER_SIZE + 1, startY, width - CORNER_SIZE + 1, height - 2); return true; } return false; } // Returns true if the associated internal frame has focus. protected boolean isActiveFrame() { return frame.isSelected(); } } public static void drawBezel(Graphics g, int x, int y, int w, int h, boolean isPressed, boolean hasFocus, Color shadow, Color highlight, Color darkShadow, Color focus) { Color oldColor = g.getColor(); g.translate(x, y); if (isPressed) { if (hasFocus){ g.setColor(focus); g.drawRect(0, 0, w-1, h-1); } g.setColor(shadow); // inner border g.drawRect(1, 1, w-3, h-3); g.setColor(highlight); // inner 3D border g.drawLine(2, h-3, w-3, h-3); g.drawLine(w-3, 2, w-3, h-4); } else { if (hasFocus) { g.setColor(focus); g.drawRect(0, 0, w-1, h-1); g.setColor(highlight); // inner 3D border g.drawLine(1, 1, 1, h-3); g.drawLine(2, 1, w-4, 1); g.setColor(shadow); g.drawLine(2, h-3, w-3, h-3); g.drawLine(w-3, 1, w-3, h-4); g.setColor(darkShadow); // black drop shadow __| g.drawLine(1, h-2, w-2, h-2); g.drawLine(w-2, h-2, w-2, 1); } else { g.setColor(highlight); // inner 3D border g.drawLine(1,1,1,h-3); g.drawLine(2,1,w-4,1); g.setColor(shadow); g.drawLine(2,h-3,w-3,h-3); g.drawLine(w-3,1,w-3,h-4); g.setColor(darkShadow); // black drop shadow __| g.drawLine(1,h-2,w-2,h-2); g.drawLine(w-2,h-2,w-2,0); } g.translate(-x, -y); } g.setColor(oldColor); } public static class MotifPopupMenuBorder extends AbstractBorder implements UIResource { protected Font font; protected Color background; protected Color foreground; protected Color shadowColor; protected Color highlightColor; // Space between the border and text static protected final int TEXT_SPACING = 2; // Space for the separator under the title static protected final int GROOVE_HEIGHT = 2; /** * Creates a MotifPopupMenuBorder instance * */ public MotifPopupMenuBorder( Font titleFont, Color bgColor, Color fgColor, Color shadow, Color highlight) { this.font = titleFont; this.background = bgColor; this.foreground = fgColor; this.shadowColor = shadow; this.highlightColor = highlight; } /** * Paints the border for the specified component with the * specified position and size. * @param c the component for which this border is being painted * @param g the paint graphics * @param x the x position of the painted border * @param y the y position of the painted border * @param width the width of the painted border * @param height the height of the painted border */ public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { Font origFont = g.getFont(); Color origColor = g.getColor(); JPopupMenu popup = (JPopupMenu)c; String title = popup.getLabel(); if (title == null) { return; } g.setFont(font); FontMetrics fm = SwingUtilities2.getFontMetrics(popup, g, font); int fontHeight = fm.getHeight(); int descent = fm.getDescent(); int ascent = fm.getAscent(); Point textLoc = new Point(); int stringWidth = SwingUtilities2.stringWidth(popup, fm, title); textLoc.y = y + ascent + TEXT_SPACING; textLoc.x = x + ((width - stringWidth) / 2); g.setColor(background); g.fillRect(textLoc.x - TEXT_SPACING, textLoc.y - (fontHeight-descent), stringWidth + (2 * TEXT_SPACING), fontHeight - descent); g.setColor(foreground); SwingUtilities2.drawString(popup, g, title, textLoc.x, textLoc.y); MotifGraphicsUtils.drawGroove(g, x, textLoc.y + TEXT_SPACING, width, GROOVE_HEIGHT, shadowColor, highlightColor); g.setFont(origFont); g.setColor(origColor); } /** * Returns the insets of the border. * @param c the component for which this border insets value applies */ public Insets getBorderInsets(Component c) { return getBorderInsets(c, new Insets(0, 0, 0, 0)); } /** * Reinitialize the insets parameter with this Border's current Insets. * @param c the component for which this border insets value applies * @param insets the object to be reinitialized */ public Insets getBorderInsets(Component c, Insets insets) { FontMetrics fm; int descent = 0; int ascent = 16; String title = ((JPopupMenu)c).getLabel(); if (title == null) { insets.left = insets.top = insets.right = insets.bottom = 0; return insets; } fm = c.getFontMetrics(font); if(fm != null) { descent = fm.getDescent(); ascent = fm.getAscent(); } insets.top += ascent + descent + TEXT_SPACING + GROOVE_HEIGHT; return insets; } } }