/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.java.sip.communicator.impl.gui.lookandfeel; import java.awt.*; import java.awt.image.*; import javax.swing.*; import javax.swing.border.*; import javax.swing.plaf.basic.*; import javax.swing.plaf.metal.*; import net.java.sip.communicator.impl.gui.utils.*; import net.java.sip.communicator.util.skin.*; /** * Divider used by SIPCommSplitPaneUI. * * @author Yana Stamcheva * @author Adam Netocny */ class SIPCommSplitPaneDivider extends BasicSplitPaneDivider implements Skinnable { /** * The horizontal divider. */ private BufferedImage horizontalDivider = ImageLoader.getImage(ImageLoader.SPLITPANE_HORIZONTAL); /** * The vertical divider. */ private BufferedImage verticalDivider = ImageLoader.getImage(ImageLoader.SPLITPANE_VERTICAL); /** * Creates an instance of <tt>SIPCommSplitPaneDivider</tt> by specifying the * <tt>BasicSplitPaneUI</tt> to use. * * @param ui the <tt>BasicSplitPaneUI</tt> */ public SIPCommSplitPaneDivider(BasicSplitPaneUI ui) { super(ui); setLayout(new DividerLayout()); } /** * Paints this split pane divider. * * @param g the <tt>Graphics</tt> object used for painting */ @Override public void paint(Graphics g) { Rectangle clip = g.getClipBounds(); if(getOrientationFromSuper() == JSplitPane.VERTICAL_SPLIT) g.drawImage(horizontalDivider, (getWidth() - horizontalDivider.getWidth(null))/2 , clip.y + (getHeight() - horizontalDivider.getHeight(null))/2, horizontalDivider.getWidth(null), horizontalDivider.getHeight(null), null); else g.drawImage(verticalDivider, clip.x + (getWidth() - verticalDivider.getWidth(null))/2 , (getHeight() - verticalDivider.getHeight(null))/2, verticalDivider.getWidth(null), verticalDivider.getHeight(null), null); super.paint(g); } /** * Creates and returns an instance of JButton that can be used to * collapse the left component in the metal split pane. * * @return the created button */ @Override 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}}; @Override public void setBorder(Border b) {} @Override 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()); 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); } } } } } }; b.setRequestFocusEnabled(false); b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); b.setFocusPainted(false); b.setBorderPainted(false); return b; } /** * Creates and return an instance of JButton that can be used to * collapse the right component in the metal split pane. */ @Override 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}}; @Override public void setBorder(Border border) {} @Override 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()); 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); } } } } } }; b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); b.setFocusPainted(false); b.setBorderPainted(false); b.setRequestFocusEnabled(false); return b; } /** * Used to layout a SIPCommSplitPaneDivider. 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 MetalSplitPaneDivider. */ public class DividerLayout implements LayoutManager { public void layoutContainer(Container c) { if (leftButton != null && rightButton != null && c == SIPCommSplitPaneDivider.this) { Dimension leftSize = leftButton.getPreferredSize(); Dimension rightSize = rightButton.getPreferredSize(); if (splitPane.isOneTouchExpandable()) { Insets insets = getInsets(); if (insets == null) insets = new Insets(0 , 0, 0, 0); if (orientation == JSplitPane.VERTICAL_SPLIT) { int blockSize = getDividerSize() - (insets.left + insets.right); int y = (c.getHeight() - blockSize) / 2; leftButton.setBounds(insets.left + leftSize.width, y, leftSize.width, leftSize.height); rightButton.setBounds((insets.left * 2) + leftSize.width + rightSize.width, y, rightSize.width, rightSize.height); } else { int blockSize = getDividerSize() - (insets.top + insets.bottom); int x = (c.getWidth() - blockSize) / 2; leftButton.setBounds(x, insets.top + leftSize.height, leftSize.width, leftSize.height); rightButton.setBounds(x, (insets.top * 2) + leftSize.height + rightSize.height, rightSize.width, rightSize.height); } } else { leftButton.setBounds(-5, -5, 1, 1); rightButton.setBounds(-5, -5, 1, 1); } } } /** * Returns the minimum layout size. * * @param c the container for which to return a minimum size * @return the preferred layout size */ public Dimension minimumLayoutSize(Container c) { return new Dimension(0,0); } /** * Returns the preferred layout size. * * @param c the container for which to return a preferred size * @return the preferred layout size */ 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. */ /** * Returns the one touch size. * * @return the one touch size */ int getOneTouchSizeFromSuper() { return BasicSplitPaneDivider.ONE_TOUCH_SIZE; } /** * Returns the one touch offset. * * @return the one touch offset */ int getOneTouchOffsetFromSuper() { return BasicSplitPaneDivider.ONE_TOUCH_OFFSET; } /** * Returns the orientation. * * @return the orientation */ int getOrientationFromSuper() { return super.orientation; } /** * Returns the split pane. * * @return the split pane */ JSplitPane getSplitPaneFromSuper() { return super.splitPane; } /** * Returns the left button. * * @return the left button */ JButton getLeftButtonFromSuper() { return super.leftButton; } /** * Returns the right button. * * @return the right button */ JButton getRightButtonFromSuper() { return super.rightButton; } /** * Reloads buffered images. */ public void loadSkin() { horizontalDivider = ImageLoader.getImage(ImageLoader.SPLITPANE_HORIZONTAL); verticalDivider = ImageLoader.getImage(ImageLoader.SPLITPANE_VERTICAL); } }