001 /* 002 * Copyright (c) 2001-2006 JGoodies Karsten Lentzsch. All Rights Reserved. 003 * 004 * Redistribution and use in source and binary forms, with or without 005 * modification, are permitted provided that the following conditions are met: 006 * 007 * o Redistributions of source code must retain the above copyright notice, 008 * this list of conditions and the following disclaimer. 009 * 010 * o Redistributions in binary form must reproduce the above copyright notice, 011 * this list of conditions and the following disclaimer in the documentation 012 * and/or other materials provided with the distribution. 013 * 014 * o Neither the name of JGoodies Karsten Lentzsch nor the names of 015 * its contributors may be used to endorse or promote products derived 016 * from this software without specific prior written permission. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 020 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 021 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 022 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 023 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 024 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 025 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 026 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 027 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030 031 package com.jgoodies.looks.windows; 032 033 import java.awt.Color; 034 import java.awt.Component; 035 import java.awt.Container; 036 import java.awt.Dimension; 037 import java.awt.Graphics; 038 import java.awt.LayoutManager; 039 040 import javax.swing.JButton; 041 import javax.swing.JSplitPane; 042 import javax.swing.UIManager; 043 import javax.swing.border.Border; 044 import javax.swing.plaf.basic.BasicSplitPaneUI; 045 046 import com.jgoodies.looks.plastic.PlasticSplitPaneUI; 047 048 /** 049 * Paints nicely rendered one touch triangles. 050 * 051 * @author Karsten Lentzsch 052 * @version $Revision: 1.2 $ 053 * 054 * @see PlasticSplitPaneUI 055 */ 056 final class WindowsSplitPaneDivider extends com.sun.java.swing.plaf.windows.WindowsSplitPaneDivider { 057 058 private static final int EXT_ONE_TOUCH_SIZE = 5; 059 private static final int EXT_ONE_TOUCH_OFFSET = 2; 060 private static final int EXT_BLOCKSIZE = 6; 061 062 /** 063 * Used to lay out a WindowsSplitPaneDivider. Layout for the divider 064 * involves appropriately moving the left/right buttons around. 065 * <p> 066 * This inner class is marked "public" due to a compiler bug. 067 * This class should be treated as a "protected" inner class. 068 * Instantiate it only within subclasses of MetalSplitPaneDivider. 069 */ 070 public final class ExtWindowsDividerLayout implements LayoutManager { 071 public void layoutContainer(Container c) { 072 JButton theLeftButton = getLeftButtonFromSuper(); 073 JButton theRightButton = getRightButtonFromSuper(); 074 JSplitPane theSplitPane = getSplitPaneFromSuper(); 075 int theOrientation = getOrientationFromSuper(); 076 int oneTouchSize = getOneTouchSize(); 077 int oneTouchOffset = getOneTouchOffset(); 078 int blockSize = 5; 079 //getBlockSize(); //Math.min(getDividerSize(), oneTouchSize); 080 081 // This layout differs from the one used in BasicSplitPaneDivider. 082 // It does not center justify the oneTouchExpadable buttons. 083 // This was necessary in order to meet the spec of the Metal 084 // splitpane divider. 085 if (theLeftButton != null 086 && theRightButton != null 087 && c == WindowsSplitPaneDivider.this) { 088 if (theSplitPane.isOneTouchExpandable()) { 089 if (theOrientation == JSplitPane.VERTICAL_SPLIT) { 090 theLeftButton.setBounds( 091 oneTouchOffset, 092 0, 093 blockSize * 2, 094 blockSize); 095 theRightButton.setBounds( 096 oneTouchOffset + oneTouchSize * 2, 097 0, 098 blockSize * 2, 099 blockSize); 100 } else { 101 theLeftButton.setBounds( 102 0, 103 oneTouchOffset, 104 blockSize, 105 blockSize * 2); 106 theRightButton.setBounds( 107 0, 108 oneTouchOffset + oneTouchSize * 2, 109 blockSize, 110 blockSize * 2); 111 } 112 } else { 113 theLeftButton.setBounds(-5, -5, 1, 1); 114 theRightButton.setBounds(-5, -5, 1, 1); 115 } 116 } 117 } 118 119 public Dimension minimumLayoutSize(Container c) { 120 return new Dimension(0, 0); 121 } 122 public Dimension preferredLayoutSize(Container c) { 123 return new Dimension(0, 0); 124 } 125 public void removeLayoutComponent(Component c) { 126 // Unused method; implements LayoutManager. 127 } 128 public void addLayoutComponent(String string, Component c) { 129 // Unused method; implements LayoutManager. 130 } 131 } 132 133 public WindowsSplitPaneDivider(BasicSplitPaneUI ui) { 134 super(ui); 135 setLayout(new ExtWindowsDividerLayout()); 136 } 137 138 /** 139 * Creates and return an instance of JButton that can be used to 140 * collapse the left component in the metal split pane. 141 */ 142 protected JButton createLeftOneTouchButton() { 143 JButton b = new JButton() { 144 // Sprite buffer for the arrow image of the left button Rate145 int[][] buffer = { { 0, 0, 0, 2, 2, 0, 0, 0, 0 }, { 146 0, 0, 2, 1, 1, 1, 0, 0, 0 }, { 147 0, 2, 1, 1, 1, 1, 1, 0, 0 }, { 148 2, 1, 1, 1, 1, 1, 1, 1, 0 }, { 149 0, 3, 3, 3, 3, 3, 3, 3, 3 } 150 }; 151 152 public void setBorder(Border border) { 153 // Ignore borders 154 } 155 156 public void paint(Graphics g) { 157 JSplitPane theSplitPane = getSplitPaneFromSuper(); 158 if (theSplitPane != null) { 159 int theOrientation = getOrientationFromSuper(); 160 int blockSize = buffer.length + 1; 161 //Math.min(getDividerSize(), oneTouchSize); 162 163 // Initialize the color array 164 Color[] colors = 165 { 166 this.getBackground(), 167 UIManager.getColor("controlDkShadow"), 168 Color.black, 169 //UIManager.getColor(), 170 UIManager.getColor("controlLtHighlight")}; 171 172 // Fill the background first ... 173 g.setColor(this.getBackground()); 174 g.fillRect(0, 0, this.getWidth(), this.getHeight()); 175 176 // ... then draw the arrow. 177 if (getModel().isPressed()) { 178 // Adjust color mapping for pressed button state 179 colors[1] = colors[2]; 180 } 181 if (theOrientation == JSplitPane.VERTICAL_SPLIT) { 182 // Draw the image for a vertical split 183 for (int i = 1; i <= buffer[0].length; i++) { 184 for (int j = 1; j < blockSize; j++) { 185 if (buffer[j - 1][i - 1] == 0) { 186 continue; 187 } else { 188 g.setColor(colors[buffer[j - 1][i - 1]]); 189 } 190 g.drawLine(i - 1, j, i - 1, j); 191 } 192 } 193 } else { 194 // Draw the image for a horizontal split 195 // by simply swaping the i and j axis. 196 // Except the drawLine() call this code is 197 // identical to the code block above. This was done 198 // in order to remove the additional orientation 199 // check for each pixel. 200 for (int i = 1; i <= buffer[0].length; i++) { 201 for (int j = 1; j < blockSize; j++) { 202 if (buffer[j - 1][i - 1] == 0) { 203 // Nothing needs 204 // to be drawn 205 continue; 206 } else { 207 // Set the color from the 208 // color map 209 g.setColor(colors[buffer[j - 1][i - 1]]); 210 } 211 // Draw a pixel 212 g.drawLine(j - 1, i, j - 1, i); 213 } 214 } 215 } 216 } 217 } 218 219 }; 220 b.setFocusPainted(false); 221 b.setBorderPainted(false); 222 b.setFocusable(false); 223 return b; 224 } 225 226 /** 227 * Creates and return an instance of JButton that can be used to 228 * collapse the right component in the metal split pane. 229 */ 230 protected JButton createRightOneTouchButton() { 231 JButton b = new JButton() { 232 // Sprite buffer for the arrow image of the right button Rate233 int[][] buffer = { { 2, 2, 2, 2, 2, 2, 2, 2 }, { 234 0, 1, 1, 1, 1, 1, 1, 3 }, { 235 0, 0, 1, 1, 1, 1, 3, 0 }, { 236 0, 0, 0, 1, 1, 3, 0, 0 }, { 237 0, 0, 0, 0, 3, 0, 0, 0 } 238 }; 239 240 public void setBorder(Border border) { 241 // Ignore borders 242 } 243 244 public void paint(Graphics g) { 245 JSplitPane theSplitPane = getSplitPaneFromSuper(); 246 if (theSplitPane != null) { 247 int theOrientation = getOrientationFromSuper(); 248 int blockSize = buffer.length + 1; 249 //Math.min(getDividerSize(), oneTouchSize); 250 251 // Initialize the color array 252 Color[] colors = 253 { 254 this.getBackground(), 255 UIManager.getColor("controlDkShadow"), 256 Color.black, 257 //UIManager.getColor("controlDkShadow"), 258 UIManager.getColor("controlLtHighlight")}; 259 260 // Fill the background first ... 261 g.setColor(this.getBackground()); 262 g.fillRect(0, 0, this.getWidth(), this.getHeight()); 263 264 // ... then draw the arrow. 265 if (getModel().isPressed()) { 266 // Adjust color mapping for pressed button state 267 colors[1] = colors[2]; 268 } 269 if (theOrientation == JSplitPane.VERTICAL_SPLIT) { 270 // Draw the image for a vertical split 271 for (int i = 1; i <= buffer[0].length; i++) { 272 for (int j = 1; j < blockSize; j++) { 273 if (buffer[j - 1][i - 1] == 0) { 274 continue; 275 } else { 276 g.setColor(colors[buffer[j - 1][i - 1]]); 277 } 278 g.drawLine(i, j, i, j); 279 } 280 } 281 } else { 282 // Draw the image for a horizontal split 283 // by simply swaping the i and j axis. 284 // Except the drawLine() call this code is 285 // identical to the code block above. This was done 286 // in order to remove the additional orientation 287 // check for each pixel. 288 for (int i = 1; i <= buffer[0].length; i++) { 289 for (int j = 1; j < blockSize; j++) { 290 if (buffer[j - 1][i - 1] == 0) { 291 // Nothing needs 292 // to be drawn 293 continue; 294 } else { 295 // Set the color from the 296 // color map 297 g.setColor(colors[buffer[j - 1][i - 1]]); 298 } 299 // Draw a pixel 300 g.drawLine(j - 1, i, j - 1, i); 301 } 302 } 303 } 304 } 305 } 306 }; 307 b.setFocusPainted(false); 308 b.setBorderPainted(false); 309 b.setFocusable(false); 310 return b; 311 } 312 313 int getBlockSize() { 314 return EXT_BLOCKSIZE; 315 } 316 317 int getOneTouchOffset() { 318 return EXT_ONE_TOUCH_OFFSET; 319 } 320 321 int getOneTouchSize() { 322 return EXT_ONE_TOUCH_SIZE; 323 } 324 325 int getOrientationFromSuper() { 326 return super.orientation; 327 } 328 329 JButton getLeftButtonFromSuper() { 330 return super.leftButton; 331 } 332 333 JButton getRightButtonFromSuper() { 334 return super.rightButton; 335 } 336 337 JSplitPane getSplitPaneFromSuper() { 338 return super.splitPane; 339 } 340 341 }