Esempio n. 1
0
 /** This draws the "Flush 3D Border" which is used throughout the Metal L&F */
 static void drawFlush3DBorder(Graphics g, int x, int y, int w, int h) {
   g.translate(x, y);
   g.setColor(MetalLookAndFeel.getControlDarkShadow());
   g.drawRect(0, 0, w - 2, h - 2);
   g.setColor(MetalLookAndFeel.getControlHighlight());
   g.drawRect(1, 1, w - 2, h - 2);
   g.setColor(MetalLookAndFeel.getControl());
   g.drawLine(0, h - 1, 1, h - 2);
   g.drawLine(w - 1, 0, w - 2, 1);
   g.translate(-x, -y);
 }
Esempio n. 2
0
 static void drawDefaultButtonPressedBorder(Graphics g, int x, int y, int w, int h) {
   drawPressed3DBorder(g, x + 1, y + 1, w - 1, h - 1);
   g.translate(x, y);
   g.setColor(MetalLookAndFeel.getControlDarkShadow());
   g.drawRect(0, 0, w - 3, h - 3);
   g.drawLine(w - 2, 0, w - 2, 0);
   g.drawLine(0, h - 2, 0, h - 2);
   g.setColor(MetalLookAndFeel.getControl());
   g.drawLine(w - 1, 0, w - 1, 0);
   g.drawLine(0, h - 1, 0, h - 1);
   g.translate(-x, -y);
 }
Esempio n. 3
0
  /**
   * This draws a variant "Flush 3D Border" It is used for things like active toggle buttons. This
   * is used rarely.
   */
  static void drawDark3DBorder(Graphics g, int x, int y, int w, int h) {
    g.translate(x, y);

    drawFlush3DBorder(g, 0, 0, w, h);

    g.setColor(MetalLookAndFeel.getControl());
    g.drawLine(1, 1, 1, h - 2);
    g.drawLine(1, 1, w - 2, 1);
    g.setColor(MetalLookAndFeel.getControlShadow());
    g.drawLine(1, h - 2, 1, h - 2);
    g.drawLine(w - 2, 1, w - 2, 1);
    g.translate(-x, -y);
  }
Esempio n. 4
0
    public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
      g.translate(x, y);

      if (MetalLookAndFeel.usingOcean()) {
        g.setColor(MetalLookAndFeel.getControlDarkShadow());
        g.drawRect(0, 0, w, h - 1);
        g.setColor(MetalLookAndFeel.getControlShadow());
        g.drawRect(1, 1, w - 2, h - 3);
      } else {
        g.setColor(MetalLookAndFeel.getControlDarkShadow());
        g.drawLine(0, 0, w - 1, 0);
        g.drawLine(0, 0, 0, h - 2);
        g.drawLine(0, h - 2, w - 1, h - 2);
        g.setColor(MetalLookAndFeel.getControlHighlight());
        g.drawLine(1, 1, w - 1, 1);
        g.drawLine(1, 1, 1, h - 1);
        g.drawLine(1, h - 1, w - 1, h - 1);
        g.setColor(MetalLookAndFeel.getControl());
        g.drawLine(1, h - 2, 1, h - 2);
      }

      g.translate(-x, -y);
    }
/**
 * Class that manages a JLF title bar
 *
 * @author Steve Wilson
 * @author Brian Beck
 * @since 1.3
 */
public class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane {

  protected boolean isPalette = false;
  protected Icon paletteCloseIcon;
  protected int paletteTitleHeight;

  private static final Border handyEmptyBorder = new EmptyBorder(0, 0, 0, 0);

  /**
   * Key used to lookup Color from UIManager. If this is null, <code>getWindowTitleBackground</code>
   * is used.
   */
  private String selectedBackgroundKey;
  /**
   * Key used to lookup Color from UIManager. If this is null, <code>getWindowTitleForeground</code>
   * is used.
   */
  private String selectedForegroundKey;
  /**
   * Key used to lookup shadow color from UIManager. If this is null, <code>
   * getPrimaryControlDarkShadow</code> is used.
   */
  private String selectedShadowKey;
  /**
   * Boolean indicating the state of the <code>JInternalFrame</code>s closable property at <code>
   * updateUI</code> time.
   */
  private boolean wasClosable;

  int buttonsWidth = 0;

  MetalBumps activeBumps =
      new MetalBumps(
          0,
          0,
          MetalLookAndFeel.getPrimaryControlHighlight(),
          MetalLookAndFeel.getPrimaryControlDarkShadow(),
          (UIManager.get("InternalFrame.activeTitleGradient") != null)
              ? null
              : MetalLookAndFeel.getPrimaryControl());
  MetalBumps inactiveBumps =
      new MetalBumps(
          0,
          0,
          MetalLookAndFeel.getControlHighlight(),
          MetalLookAndFeel.getControlDarkShadow(),
          (UIManager.get("InternalFrame.inactiveTitleGradient") != null)
              ? null
              : MetalLookAndFeel.getControl());
  MetalBumps paletteBumps;

  private Color activeBumpsHighlight = MetalLookAndFeel.getPrimaryControlHighlight();
  private Color activeBumpsShadow = MetalLookAndFeel.getPrimaryControlDarkShadow();

  public MetalInternalFrameTitlePane(JInternalFrame f) {
    super(f);
  }

  public void addNotify() {
    super.addNotify();
    // This is done here instead of in installDefaults as I was worried
    // that the BasicInternalFrameUI might not be fully initialized, and
    // that if this resets the closable state the BasicInternalFrameUI
    // Listeners that get notified might be in an odd/uninitialized state.
    updateOptionPaneState();
  }

  protected void installDefaults() {
    super.installDefaults();
    setFont(UIManager.getFont("InternalFrame.titleFont"));
    paletteTitleHeight = UIManager.getInt("InternalFrame.paletteTitleHeight");
    paletteCloseIcon = UIManager.getIcon("InternalFrame.paletteCloseIcon");
    wasClosable = frame.isClosable();
    selectedForegroundKey = selectedBackgroundKey = null;
    if (MetalLookAndFeel.usingOcean()) {
      setOpaque(true);
    }
  }

  protected void uninstallDefaults() {
    super.uninstallDefaults();
    if (wasClosable != frame.isClosable()) {
      frame.setClosable(wasClosable);
    }
  }

  protected void createButtons() {
    super.createButtons();

    Boolean paintActive = frame.isSelected() ? Boolean.TRUE : Boolean.FALSE;
    iconButton.putClientProperty("paintActive", paintActive);
    iconButton.setBorder(handyEmptyBorder);

    maxButton.putClientProperty("paintActive", paintActive);
    maxButton.setBorder(handyEmptyBorder);

    closeButton.putClientProperty("paintActive", paintActive);
    closeButton.setBorder(handyEmptyBorder);

    // The palette close icon isn't opaque while the regular close icon is.
    // This makes sure palette close buttons have the right background.
    closeButton.setBackground(MetalLookAndFeel.getPrimaryControlShadow());

    if (MetalLookAndFeel.usingOcean()) {
      iconButton.setContentAreaFilled(false);
      maxButton.setContentAreaFilled(false);
      closeButton.setContentAreaFilled(false);
    }
  }

  /** Override the parent's method to do nothing. Metal frames do not have system menus. */
  protected void assembleSystemMenu() {}

  /** Override the parent's method to do nothing. Metal frames do not have system menus. */
  protected void addSystemMenuItems(JMenu systemMenu) {}

  /** Override the parent's method to do nothing. Metal frames do not have system menus. */
  protected void showSystemMenu() {}

  /**
   * Override the parent's method avoid creating a menu bar. Metal frames do not have system menus.
   */
  protected void addSubComponents() {
    add(iconButton);
    add(maxButton);
    add(closeButton);
  }

  protected PropertyChangeListener createPropertyChangeListener() {
    return new MetalPropertyChangeHandler();
  }

  protected LayoutManager createLayout() {
    return new MetalTitlePaneLayout();
  }

  class MetalPropertyChangeHandler extends BasicInternalFrameTitlePane.PropertyChangeHandler {
    public void propertyChange(PropertyChangeEvent evt) {
      String prop = (String) evt.getPropertyName();
      if (prop.equals(JInternalFrame.IS_SELECTED_PROPERTY)) {
        Boolean b = (Boolean) evt.getNewValue();
        iconButton.putClientProperty("paintActive", b);
        closeButton.putClientProperty("paintActive", b);
        maxButton.putClientProperty("paintActive", b);
      } else if ("JInternalFrame.messageType".equals(prop)) {
        updateOptionPaneState();
        frame.repaint();
      }
      super.propertyChange(evt);
    }
  }

  class MetalTitlePaneLayout extends TitlePaneLayout {
    public void addLayoutComponent(String name, Component c) {}

    public void removeLayoutComponent(Component c) {}

    public Dimension preferredLayoutSize(Container c) {
      return minimumLayoutSize(c);
    }

    public Dimension minimumLayoutSize(Container c) {
      // Compute width.
      int width = 30;
      if (frame.isClosable()) {
        width += 21;
      }
      if (frame.isMaximizable()) {
        width += 16 + (frame.isClosable() ? 10 : 4);
      }
      if (frame.isIconifiable()) {
        width += 16 + (frame.isMaximizable() ? 2 : (frame.isClosable() ? 10 : 4));
      }
      FontMetrics fm = frame.getFontMetrics(getFont());
      String frameTitle = frame.getTitle();
      int title_w = frameTitle != null ? SwingUtilities2.stringWidth(frame, fm, frameTitle) : 0;
      int title_length = frameTitle != null ? frameTitle.length() : 0;

      if (title_length > 2) {
        int subtitle_w =
            SwingUtilities2.stringWidth(frame, fm, frame.getTitle().substring(0, 2) + "...");
        width += (title_w < subtitle_w) ? title_w : subtitle_w;
      } else {
        width += title_w;
      }

      // Compute height.
      int height = 0;
      if (isPalette) {
        height = paletteTitleHeight;
      } else {
        int fontHeight = fm.getHeight();
        fontHeight += 7;
        Icon icon = frame.getFrameIcon();
        int iconHeight = 0;
        if (icon != null) {
          // SystemMenuBar forces the icon to be 16x16 or less.
          iconHeight = Math.min(icon.getIconHeight(), 16);
        }
        iconHeight += 5;
        height = Math.max(fontHeight, iconHeight);
      }

      return new Dimension(width, height);
    }

    public void layoutContainer(Container c) {
      boolean leftToRight = MetalUtils.isLeftToRight(frame);

      int w = getWidth();
      int x = leftToRight ? w : 0;
      int y = 2;
      int spacing;

      // assumes all buttons have the same dimensions
      // these dimensions include the borders
      int buttonHeight = closeButton.getIcon().getIconHeight();
      int buttonWidth = closeButton.getIcon().getIconWidth();

      if (frame.isClosable()) {
        if (isPalette) {
          spacing = 3;
          x += leftToRight ? -spacing - (buttonWidth + 2) : spacing;
          closeButton.setBounds(x, y, buttonWidth + 2, getHeight() - 4);
          if (!leftToRight) x += (buttonWidth + 2);
        } else {
          spacing = 4;
          x += leftToRight ? -spacing - buttonWidth : spacing;
          closeButton.setBounds(x, y, buttonWidth, buttonHeight);
          if (!leftToRight) x += buttonWidth;
        }
      }

      if (frame.isMaximizable() && !isPalette) {
        spacing = frame.isClosable() ? 10 : 4;
        x += leftToRight ? -spacing - buttonWidth : spacing;
        maxButton.setBounds(x, y, buttonWidth, buttonHeight);
        if (!leftToRight) x += buttonWidth;
      }

      if (frame.isIconifiable() && !isPalette) {
        spacing = frame.isMaximizable() ? 2 : (frame.isClosable() ? 10 : 4);
        x += leftToRight ? -spacing - buttonWidth : spacing;
        iconButton.setBounds(x, y, buttonWidth, buttonHeight);
        if (!leftToRight) x += buttonWidth;
      }

      buttonsWidth = leftToRight ? w - x : x;
    }
  }

  public void paintPalette(Graphics g) {
    boolean leftToRight = MetalUtils.isLeftToRight(frame);

    int width = getWidth();
    int height = getHeight();

    if (paletteBumps == null) {
      paletteBumps =
          new MetalBumps(
              0,
              0,
              MetalLookAndFeel.getPrimaryControlHighlight(),
              MetalLookAndFeel.getPrimaryControlInfo(),
              MetalLookAndFeel.getPrimaryControlShadow());
    }

    Color background = MetalLookAndFeel.getPrimaryControlShadow();
    Color darkShadow = MetalLookAndFeel.getPrimaryControlDarkShadow();

    g.setColor(background);
    g.fillRect(0, 0, width, height);

    g.setColor(darkShadow);
    g.drawLine(0, height - 1, width, height - 1);

    int xOffset = leftToRight ? 4 : buttonsWidth + 4;
    int bumpLength = width - buttonsWidth - 2 * 4;
    int bumpHeight = getHeight() - 4;
    paletteBumps.setBumpArea(bumpLength, bumpHeight);
    paletteBumps.paintIcon(this, g, xOffset, 2);
  }

  public void paintComponent(Graphics g) {
    if (isPalette) {
      paintPalette(g);
      return;
    }

    boolean leftToRight = MetalUtils.isLeftToRight(frame);
    boolean isSelected = frame.isSelected();

    int width = getWidth();
    int height = getHeight();

    Color background = null;
    Color foreground = null;
    Color shadow = null;

    MetalBumps bumps;
    String gradientKey;

    if (isSelected) {
      if (!MetalLookAndFeel.usingOcean()) {
        closeButton.setContentAreaFilled(true);
        maxButton.setContentAreaFilled(true);
        iconButton.setContentAreaFilled(true);
      }
      if (selectedBackgroundKey != null) {
        background = UIManager.getColor(selectedBackgroundKey);
      }
      if (background == null) {
        background = MetalLookAndFeel.getWindowTitleBackground();
      }
      if (selectedForegroundKey != null) {
        foreground = UIManager.getColor(selectedForegroundKey);
      }
      if (selectedShadowKey != null) {
        shadow = UIManager.getColor(selectedShadowKey);
      }
      if (shadow == null) {
        shadow = MetalLookAndFeel.getPrimaryControlDarkShadow();
      }
      if (foreground == null) {
        foreground = MetalLookAndFeel.getWindowTitleForeground();
      }
      activeBumps.setBumpColors(
          activeBumpsHighlight,
          activeBumpsShadow,
          UIManager.get("InternalFrame.activeTitleGradient") != null ? null : background);
      bumps = activeBumps;
      gradientKey = "InternalFrame.activeTitleGradient";
    } else {
      if (!MetalLookAndFeel.usingOcean()) {
        closeButton.setContentAreaFilled(false);
        maxButton.setContentAreaFilled(false);
        iconButton.setContentAreaFilled(false);
      }
      background = MetalLookAndFeel.getWindowTitleInactiveBackground();
      foreground = MetalLookAndFeel.getWindowTitleInactiveForeground();
      shadow = MetalLookAndFeel.getControlDarkShadow();
      bumps = inactiveBumps;
      gradientKey = "InternalFrame.inactiveTitleGradient";
    }

    if (!MetalUtils.drawGradient(this, g, gradientKey, 0, 0, width, height, true)) {
      g.setColor(background);
      g.fillRect(0, 0, width, height);
    }

    g.setColor(shadow);
    g.drawLine(0, height - 1, width, height - 1);
    g.drawLine(0, 0, 0, 0);
    g.drawLine(width - 1, 0, width - 1, 0);

    int titleLength = 0;
    int xOffset = leftToRight ? 5 : width - 5;
    String frameTitle = frame.getTitle();

    Icon icon = frame.getFrameIcon();
    if (icon != null) {
      if (!leftToRight) xOffset -= icon.getIconWidth();
      int iconY = ((height / 2) - (icon.getIconHeight() / 2));
      icon.paintIcon(frame, g, xOffset, iconY);
      xOffset += leftToRight ? icon.getIconWidth() + 5 : -5;
    }

    if (frameTitle != null) {
      Font f = getFont();
      g.setFont(f);
      FontMetrics fm = SwingUtilities2.getFontMetrics(frame, g, f);
      int fHeight = fm.getHeight();

      g.setColor(foreground);

      int yOffset = ((height - fm.getHeight()) / 2) + fm.getAscent();

      Rectangle rect = new Rectangle(0, 0, 0, 0);
      if (frame.isIconifiable()) {
        rect = iconButton.getBounds();
      } else if (frame.isMaximizable()) {
        rect = maxButton.getBounds();
      } else if (frame.isClosable()) {
        rect = closeButton.getBounds();
      }
      int titleW;

      if (leftToRight) {
        if (rect.x == 0) {
          rect.x = frame.getWidth() - frame.getInsets().right - 2;
        }
        titleW = rect.x - xOffset - 4;
        frameTitle = getTitle(frameTitle, fm, titleW);
      } else {
        titleW = xOffset - rect.x - rect.width - 4;
        frameTitle = getTitle(frameTitle, fm, titleW);
        xOffset -= SwingUtilities2.stringWidth(frame, fm, frameTitle);
      }

      titleLength = SwingUtilities2.stringWidth(frame, fm, frameTitle);
      SwingUtilities2.drawString(frame, g, frameTitle, xOffset, yOffset);
      xOffset += leftToRight ? titleLength + 5 : -5;
    }

    int bumpXOffset;
    int bumpLength;
    if (leftToRight) {
      bumpLength = width - buttonsWidth - xOffset - 5;
      bumpXOffset = xOffset;
    } else {
      bumpLength = xOffset - buttonsWidth - 5;
      bumpXOffset = buttonsWidth + 5;
    }
    int bumpYOffset = 3;
    int bumpHeight = getHeight() - (2 * bumpYOffset);
    bumps.setBumpArea(bumpLength, bumpHeight);
    bumps.paintIcon(this, g, bumpXOffset, bumpYOffset);
  }

  public void setPalette(boolean b) {
    isPalette = b;

    if (isPalette) {
      closeButton.setIcon(paletteCloseIcon);
      if (frame.isMaximizable()) remove(maxButton);
      if (frame.isIconifiable()) remove(iconButton);
    } else {
      closeButton.setIcon(closeIcon);
      if (frame.isMaximizable()) add(maxButton);
      if (frame.isIconifiable()) add(iconButton);
    }
    revalidate();
    repaint();
  }

  /**
   * Updates any state dependant upon the JInternalFrame being shown in a <code>JOptionPane</code>.
   */
  private void updateOptionPaneState() {
    int type = -2;
    boolean closable = wasClosable;
    Object obj = frame.getClientProperty("JInternalFrame.messageType");

    if (obj == null) {
      // Don't change the closable state unless in an JOptionPane.
      return;
    }
    if (obj instanceof Integer) {
      type = ((Integer) obj).intValue();
    }
    switch (type) {
      case JOptionPane.ERROR_MESSAGE:
        selectedBackgroundKey = "OptionPane.errorDialog.titlePane.background";
        selectedForegroundKey = "OptionPane.errorDialog.titlePane.foreground";
        selectedShadowKey = "OptionPane.errorDialog.titlePane.shadow";
        closable = false;
        break;
      case JOptionPane.QUESTION_MESSAGE:
        selectedBackgroundKey = "OptionPane.questionDialog.titlePane.background";
        selectedForegroundKey = "OptionPane.questionDialog.titlePane.foreground";
        selectedShadowKey = "OptionPane.questionDialog.titlePane.shadow";
        closable = false;
        break;
      case JOptionPane.WARNING_MESSAGE:
        selectedBackgroundKey = "OptionPane.warningDialog.titlePane.background";
        selectedForegroundKey = "OptionPane.warningDialog.titlePane.foreground";
        selectedShadowKey = "OptionPane.warningDialog.titlePane.shadow";
        closable = false;
        break;
      case JOptionPane.INFORMATION_MESSAGE:
      case JOptionPane.PLAIN_MESSAGE:
        selectedBackgroundKey = selectedForegroundKey = selectedShadowKey = null;
        closable = false;
        break;
      default:
        selectedBackgroundKey = selectedForegroundKey = selectedShadowKey = null;
        break;
    }
    if (closable != frame.isClosable()) {
      frame.setClosable(closable);
    }
  }
}
/**
 * Metal's split pane divider
 *
 * <p><strong>Warning:</strong> 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. As of 1.4, support for long term storage
 * of all JavaBeans<sup><font size="-2">TM</font></sup> has been added to the <code>java.beans
 * </code> package. Please see {@link java.beans.XMLEncoder}.
 *
 * @author Steve Wilson
 * @author Ralph kar
 */
class MetalSplitPaneDivider extends BasicSplitPaneDivider {
  private MetalBumps bumps =
      new MetalBumps(
          10,
          10,
          MetalLookAndFeel.getControlHighlight(),
          MetalLookAndFeel.getControlDarkShadow(),
          MetalLookAndFeel.getControl());

  private MetalBumps focusBumps =
      new MetalBumps(
          10,
          10,
          MetalLookAndFeel.getPrimaryControlHighlight(),
          MetalLookAndFeel.getPrimaryControlDarkShadow(),
          UIManager.getColor("SplitPane.dividerFocusColor"));

  private int inset = 2;

  private Color controlColor = MetalLookAndFeel.getControl();
  private Color primaryControlColor = UIManager.getColor("SplitPane.dividerFocusColor");

  public MetalSplitPaneDivider(BasicSplitPaneUI ui) {
    super(ui);
  }

  public void paint(Graphics g) {
    MetalBumps usedBumps;
    if (splitPane.hasFocus()) {
      usedBumps = focusBumps;
      g.setColor(primaryControlColor);
    } else {
      usedBumps = bumps;
      g.setColor(controlColor);
    }
    Rectangle clip = g.getClipBounds();
    Insets insets = getInsets();
    g.fillRect(clip.x, clip.y, clip.width, clip.height);
    Dimension size = getSize();
    size.width -= inset * 2;
    size.height -= inset * 2;
    int drawX = inset;
    int drawY = inset;
    if (insets != null) {
      size.width -= (insets.left + insets.right);
      size.height -= (insets.top + insets.bottom);
      drawX += insets.left;
      drawY += insets.top;
    }
    usedBumps.setBumpArea(size);
    usedBumps.paintIcon(this, g, drawX, drawY);
    super.paint(g);
  }

  /**
   * Creates and return an instance of JButton that can be used to collapse the left component in
   * the metal split pane.
   */
  protected JButton createLeftOneTouchButton() {
    JButton b =
        new JButton() {
          // Sprite buffer for the arrow image of the left button
          int[][] buffer = {
            {0, 0, 0, 2, 2, 0, 0, 0, 0},
            {0, 0, 2, 1, 1, 1, 0, 0, 0},
            {0, 2, 1, 1, 1, 1, 1, 0, 0},
            {2, 1, 1, 1, 1, 1, 1, 1, 0},
            {0, 3, 3, 3, 3, 3, 3, 3, 3}
          };

          public void setBorder(Border b) {}

          public void paint(Graphics g) {
            JSplitPane splitPane = getSplitPaneFromSuper();
            if (splitPane != null) {
              int oneTouchSize = getOneTouchSizeFromSuper();
              int orientation = getOrientationFromSuper();
              int blockSize = Math.min(getDividerSize(), oneTouchSize);

              // Initialize the color array
              Color[] colors = {
                this.getBackground(),
                MetalLookAndFeel.getPrimaryControlDarkShadow(),
                MetalLookAndFeel.getPrimaryControlInfo(),
                MetalLookAndFeel.getPrimaryControlHighlight()
              };

              // Fill the background first ...
              g.setColor(this.getBackground());
              if (isOpaque()) {
                g.fillRect(0, 0, this.getWidth(), this.getHeight());
              }

              // ... then draw the arrow.
              if (getModel().isPressed()) {
                // Adjust color mapping for pressed button state
                colors[1] = colors[2];
              }
              if (orientation == JSplitPane.VERTICAL_SPLIT) {
                // Draw the image for a vertical split
                for (int i = 1; i <= buffer[0].length; i++) {
                  for (int j = 1; j < blockSize; j++) {
                    if (buffer[j - 1][i - 1] == 0) {
                      continue;
                    } else {
                      g.setColor(colors[buffer[j - 1][i - 1]]);
                    }
                    g.drawLine(i, j, i, j);
                  }
                }
              } else {
                // Draw the image for a horizontal split
                // by simply swaping the i and j axis.
                // Except the drawLine() call this code is
                // identical to the code block above. This was done
                // in order to remove the additional orientation
                // check for each pixel.
                for (int i = 1; i <= buffer[0].length; i++) {
                  for (int j = 1; j < blockSize; j++) {
                    if (buffer[j - 1][i - 1] == 0) {
                      // Nothing needs
                      // to be drawn
                      continue;
                    } else {
                      // Set the color from the
                      // color map
                      g.setColor(colors[buffer[j - 1][i - 1]]);
                    }
                    // Draw a pixel
                    g.drawLine(j, i, j, i);
                  }
                }
              }
            }
          }

          // Don't want the button to participate in focus traversable.
          public boolean isFocusTraversable() {
            return false;
          }
        };
    b.setRequestFocusEnabled(false);
    b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
    b.setFocusPainted(false);
    b.setBorderPainted(false);
    maybeMakeButtonOpaque(b);
    return b;
  }

  /** If necessary <code>c</code> is made opaque. */
  private void maybeMakeButtonOpaque(JComponent c) {
    Object opaque = UIManager.get("SplitPane.oneTouchButtonsOpaque");
    if (opaque != null) {
      c.setOpaque(((Boolean) opaque).booleanValue());
    }
  }

  /**
   * Creates and return an instance of JButton that can be used to collapse the right component in
   * the metal split pane.
   */
  protected JButton createRightOneTouchButton() {
    JButton b =
        new JButton() {
          // Sprite buffer for the arrow image of the right button
          int[][] buffer = {
            {2, 2, 2, 2, 2, 2, 2, 2},
            {0, 1, 1, 1, 1, 1, 1, 3},
            {0, 0, 1, 1, 1, 1, 3, 0},
            {0, 0, 0, 1, 1, 3, 0, 0},
            {0, 0, 0, 0, 3, 0, 0, 0}
          };

          public void setBorder(Border border) {}

          public void paint(Graphics g) {
            JSplitPane splitPane = getSplitPaneFromSuper();
            if (splitPane != null) {
              int oneTouchSize = getOneTouchSizeFromSuper();
              int orientation = getOrientationFromSuper();
              int blockSize = Math.min(getDividerSize(), oneTouchSize);

              // Initialize the color array
              Color[] colors = {
                this.getBackground(),
                MetalLookAndFeel.getPrimaryControlDarkShadow(),
                MetalLookAndFeel.getPrimaryControlInfo(),
                MetalLookAndFeel.getPrimaryControlHighlight()
              };

              // Fill the background first ...
              g.setColor(this.getBackground());
              if (isOpaque()) {
                g.fillRect(0, 0, this.getWidth(), this.getHeight());
              }

              // ... then draw the arrow.
              if (getModel().isPressed()) {
                // Adjust color mapping for pressed button state
                colors[1] = colors[2];
              }
              if (orientation == JSplitPane.VERTICAL_SPLIT) {
                // Draw the image for a vertical split
                for (int i = 1; i <= buffer[0].length; i++) {
                  for (int j = 1; j < blockSize; j++) {
                    if (buffer[j - 1][i - 1] == 0) {
                      continue;
                    } else {
                      g.setColor(colors[buffer[j - 1][i - 1]]);
                    }
                    g.drawLine(i, j, i, j);
                  }
                }
              } else {
                // Draw the image for a horizontal split
                // by simply swaping the i and j axis.
                // Except the drawLine() call this code is
                // identical to the code block above. This was done
                // in order to remove the additional orientation
                // check for each pixel.
                for (int i = 1; i <= buffer[0].length; i++) {
                  for (int j = 1; j < blockSize; j++) {
                    if (buffer[j - 1][i - 1] == 0) {
                      // Nothing needs
                      // to be drawn
                      continue;
                    } else {
                      // Set the color from the
                      // color map
                      g.setColor(colors[buffer[j - 1][i - 1]]);
                    }
                    // Draw a pixel
                    g.drawLine(j, i, j, i);
                  }
                }
              }
            }
          }

          // Don't want the button to participate in focus traversable.
          public boolean isFocusTraversable() {
            return false;
          }
        };
    b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
    b.setFocusPainted(false);
    b.setBorderPainted(false);
    b.setRequestFocusEnabled(false);
    maybeMakeButtonOpaque(b);
    return b;
  }

  /**
   * Used to layout a MetalSplitPaneDivider. Layout for the divider involves appropriately moving
   * the left/right buttons around.
   *
   * <p>This class should be treated as a &quot;protected&quot; inner class. Instantiate it only
   * within subclasses of MetalSplitPaneDivider.
   */
  public class MetalDividerLayout implements LayoutManager {

    // NOTE NOTE NOTE NOTE NOTE
    // This class is no longer used, the functionality has
    // been rolled into BasicSplitPaneDivider.DividerLayout as a
    // defaults property

    public void layoutContainer(Container c) {
      JButton leftButton = getLeftButtonFromSuper();
      JButton rightButton = getRightButtonFromSuper();
      JSplitPane splitPane = getSplitPaneFromSuper();
      int orientation = getOrientationFromSuper();
      int oneTouchSize = getOneTouchSizeFromSuper();
      int oneTouchOffset = getOneTouchOffsetFromSuper();
      Insets insets = getInsets();

      // This layout differs from the one used in BasicSplitPaneDivider.
      // It does not center justify the oneTouchExpadable buttons.
      // This was necessary in order to meet the spec of the Metal
      // splitpane divider.
      if (leftButton != null && rightButton != null && c == MetalSplitPaneDivider.this) {
        if (splitPane.isOneTouchExpandable()) {
          if (orientation == JSplitPane.VERTICAL_SPLIT) {
            int extraY = (insets != null) ? insets.top : 0;
            int blockSize = getDividerSize();

            if (insets != null) {
              blockSize -= (insets.top + insets.bottom);
            }
            blockSize = Math.min(blockSize, oneTouchSize);
            leftButton.setBounds(oneTouchOffset, extraY, blockSize * 2, blockSize);
            rightButton.setBounds(
                oneTouchOffset + oneTouchSize * 2, extraY, blockSize * 2, blockSize);
          } else {
            int blockSize = getDividerSize();
            int extraX = (insets != null) ? insets.left : 0;

            if (insets != null) {
              blockSize -= (insets.left + insets.right);
            }
            blockSize = Math.min(blockSize, oneTouchSize);
            leftButton.setBounds(extraX, oneTouchOffset, blockSize, blockSize * 2);
            rightButton.setBounds(
                extraX, oneTouchOffset + oneTouchSize * 2, blockSize, blockSize * 2);
          }
        } else {
          leftButton.setBounds(-5, -5, 1, 1);
          rightButton.setBounds(-5, -5, 1, 1);
        }
      }
    }

    public Dimension minimumLayoutSize(Container c) {
      return new Dimension(0, 0);
    }

    public Dimension preferredLayoutSize(Container c) {
      return new Dimension(0, 0);
    }

    public void removeLayoutComponent(Component c) {}

    public void addLayoutComponent(String string, Component c) {}
  }

  /*
   * The following methods only exist in order to be able to access protected
   * members in the superclass, because these are otherwise not available
   * in any inner class.
   */

  int getOneTouchSizeFromSuper() {
    return super.ONE_TOUCH_SIZE;
  }

  int getOneTouchOffsetFromSuper() {
    return super.ONE_TOUCH_OFFSET;
  }

  int getOrientationFromSuper() {
    return super.orientation;
  }

  JSplitPane getSplitPaneFromSuper() {
    return super.splitPane;
  }

  JButton getLeftButtonFromSuper() {
    return super.leftButton;
  }

  JButton getRightButtonFromSuper() {
    return super.rightButton;
  }
}