/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Liquid Look and Feel * * * * Author, Miroslav Lazarevic * * * * For licensing information and credits, please refer to the * * comment in file com.birosoft.liquid.LiquidLookAndFeel * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ package com.birosoft.liquid; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Insets; import java.awt.LayoutManager; import java.awt.Rectangle; import javax.swing.JButton; import javax.swing.JSplitPane; import javax.swing.border.Border; import javax.swing.plaf.basic.BasicSplitPaneDivider; import javax.swing.plaf.basic.BasicSplitPaneUI; import com.birosoft.liquid.skin.Skin; /** * Liquid'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}. * * @version 1.17 12/03/01 * @author Steve Wilson * @author Ralph kar */ class LiquidSplitPaneDivider extends BasicSplitPaneDivider { /** * */ private static final long serialVersionUID = 4058298927908826880L; Skin skinVertSplitter = null; Skin skinHorzSplitter = null; public LiquidSplitPaneDivider(BasicSplitPaneUI ui) { super(ui); setLayout(new LiquidDividerLayout()); } Skin getHorizontalSplitter() { if (skinHorzSplitter==null) skinHorzSplitter = new Skin("horizsplitter.png", 1, 5, 5, 5, 5); return skinHorzSplitter; } Skin getVerticalSplitter() { if (skinVertSplitter==null) skinVertSplitter = new Skin("vertsplitter.png", 1, 5, 5, 5, 5); return skinVertSplitter; } public void paint(Graphics g) { Dimension size = getSize(); Rectangle clip = new Rectangle(size.width, size.height); if (orientation == JSplitPane.HORIZONTAL_SPLIT) { int xOffset = (clip.width - 5) / 2; getHorizontalSplitter().draw(g, 0, clip.x+xOffset, clip.y+1, 5, clip.height-1); } else { int yOffset = (clip.height - 5) / 2; getVerticalSplitter().draw(g, 0, clip.x+1, clip.y+yOffset, clip.width-1, 5); } /* 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; } */ super.paint(g); } /** * I don't know does Liquid or KDE supports one touch buttons. * For now this is disabled. * 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() { /** * */ private static final long serialVersionUID = -2808135928573217861L; // 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(), (Color)LiquidLookAndFeel.uiDefaults.get("controlDkShadow"), (Color)LiquidLookAndFeel.uiDefaults.get("info"), (Color)LiquidLookAndFeel.uiDefaults.get("controlHighlight")}; // Fill the background first ... g.setColor(this.getBackground()); //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); return b; //return null; } /** * 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() { /** * */ private static final long serialVersionUID = -4522647393919107295L; // 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(), (Color)LiquidLookAndFeel.uiDefaults.get("controlDkShadow"), (Color)LiquidLookAndFeel.uiDefaults.get("info"), (Color)LiquidLookAndFeel.uiDefaults.get("controlHighlight")}; // Fill the background first ... g.setColor(this.getBackground()); //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); return b; //return null; } /** * Used to layout a XPSplitPaneDivider. Layout for the divider * involves appropriately moving the left/right buttons around. * <p> * This inner class is marked "public" due to a compiler bug. * This class should be treated as a "protected" inner class. * Instantiate it only within subclasses of XPSplitPaneDivider. */ public class LiquidDividerLayout implements LayoutManager { 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 Liquid // splitpane divider. if (leftButton != null && rightButton != null && c == LiquidSplitPaneDivider.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 ONE_TOUCH_SIZE; } int getOneTouchOffsetFromSuper() { return ONE_TOUCH_OFFSET; } int getOrientationFromSuper() { return super.orientation; } JSplitPane getSplitPaneFromSuper() { return super.splitPane; } JButton getLeftButtonFromSuper() { return super.leftButton; } JButton getRightButtonFromSuper() { return super.rightButton; } }