1 /* 2 * Copyright (c) 1997, 1999, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.java.swing.plaf.motif; 27 28 import java.awt.*; 29 import java.awt.event.*; 30 import javax.swing.JSplitPane; 31 import javax.swing.UIManager; 32 import javax.swing.plaf.basic.BasicSplitPaneUI; 33 import javax.swing.plaf.basic.BasicSplitPaneDivider; 34 35 36 /** 37 * Divider used for Motif split pane. 38 * <p> 39 * <strong>Warning:</strong> 40 * Serialized objects of this class will not be compatible with 41 * future Swing releases. The current serialization support is appropriate 42 * for short term storage or RMI between applications running the same 43 * version of Swing. A future release of Swing will provide support for 44 * long term persistence. 45 * 46 * @author Jeff Dinkins 47 */ 48 public class MotifSplitPaneDivider extends BasicSplitPaneDivider 49 { 50 /** 51 * Default cursor, supers is package private, so we have to have one 52 * too. 53 */ 54 private static final Cursor defaultCursor = 55 Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); 56 57 58 public static final int minimumThumbSize = 6; 59 public static final int defaultDividerSize = 18; 60 61 protected static final int pad = 6; 62 63 private int hThumbOffset = 30; 64 private int vThumbOffset = 40; 65 protected int hThumbWidth = 12; 66 protected int hThumbHeight = 18; 67 protected int vThumbWidth = 18; 68 protected int vThumbHeight = 12; 69 70 protected Color highlightColor; 71 protected Color shadowColor; 72 protected Color focusedColor; 73 74 /** 75 * Creates a new Motif SplitPaneDivider 76 */ 77 public MotifSplitPaneDivider(BasicSplitPaneUI ui) { 78 super(ui); 79 highlightColor = UIManager.getColor("SplitPane.highlight"); 80 shadowColor = UIManager.getColor("SplitPane.shadow"); 81 focusedColor = UIManager.getColor("SplitPane.activeThumb"); 82 setDividerSize(hThumbWidth + pad); 83 } 84 85 /** 86 * overrides to hardcode the size of the divider 87 * PENDING(jeff) - rewrite JSplitPane so that this ins't needed 88 */ 89 public void setDividerSize(int newSize) { 90 Insets insets = getInsets(); 91 int borderSize = 0; 92 if (getBasicSplitPaneUI().getOrientation() == 93 JSplitPane.HORIZONTAL_SPLIT) { 94 if (insets != null) { 95 borderSize = insets.left + insets.right; 96 } 97 } 98 else if (insets != null) { 99 borderSize = insets.top + insets.bottom; 100 } 101 if (newSize < pad + minimumThumbSize + borderSize) { 102 setDividerSize(pad + minimumThumbSize + borderSize); 103 } else { 104 vThumbHeight = hThumbWidth = newSize - pad - borderSize; 105 super.setDividerSize(newSize); 106 } 107 } 108 109 /** 110 * Paints the divider. 111 */ 112 // PENDING(jeff) - the thumb's location and size is currently hard coded. 113 // It should be dynamic. 114 public void paint(Graphics g) { 115 Color bgColor = getBackground(); 116 Dimension size = getSize(); 117 118 // fill 119 g.setColor(getBackground()); 120 g.fillRect(0, 0, size.width, size.height); 121 122 if(getBasicSplitPaneUI().getOrientation() == 123 JSplitPane.HORIZONTAL_SPLIT) { 124 int center = size.width/2; 125 int x = center - hThumbWidth/2; 126 int y = hThumbOffset; 127 128 // split line 129 g.setColor(shadowColor); 130 g.drawLine(center-1, 0, center-1, size.height); 131 132 g.setColor(highlightColor); 133 g.drawLine(center, 0, center, size.height); 134 135 // draw thumb 136 g.setColor((splitPane.hasFocus()) ? focusedColor : 137 getBackground()); 138 g.fillRect(x+1, y+1, hThumbWidth-2, hThumbHeight-1); 139 140 g.setColor(highlightColor); 141 g.drawLine(x, y, x+hThumbWidth-1, y); // top 142 g.drawLine(x, y+1, x, y+hThumbHeight-1); // left 143 144 g.setColor(shadowColor); 145 g.drawLine(x+1, y+hThumbHeight-1, 146 x+hThumbWidth-1, y+hThumbHeight-1); // bottom 147 g.drawLine(x+hThumbWidth-1, y+1, 148 x+hThumbWidth-1, y+hThumbHeight-2); // right 149 150 } else { 151 int center = size.height/2; 152 int x = size.width - vThumbOffset; 153 int y = size.height/2 - vThumbHeight/2; 154 155 // split line 156 g.setColor(shadowColor); 157 g.drawLine(0, center-1, size.width, center-1); 158 159 g.setColor(highlightColor); 160 g.drawLine(0, center, size.width, center); 161 162 // draw thumb 163 g.setColor((splitPane.hasFocus()) ? focusedColor : 164 getBackground()); 165 g.fillRect(x+1, y+1, vThumbWidth-1, vThumbHeight-1); 166 167 g.setColor(highlightColor); 168 g.drawLine(x, y, x+vThumbWidth, y); // top 169 g.drawLine(x, y+1, x, y+vThumbHeight); // left 170 171 g.setColor(shadowColor); 172 g.drawLine(x+1, y+vThumbHeight, 173 x+vThumbWidth, y+vThumbHeight); // bottom 174 g.drawLine(x+vThumbWidth, y+1, 175 x+vThumbWidth, y+vThumbHeight-1); // right 176 } 177 super.paint(g); 178 179 } 180 181 /** 182 * The minimums size is the same as the preferredSize 183 */ 184 public Dimension getMinimumSize() { 185 return getPreferredSize(); 186 } 187 188 /** 189 * Sets the SplitPaneUI that is using the receiver. This is completely 190 * overriden from super to create a different MouseHandler. 191 */ 192 public void setBasicSplitPaneUI(BasicSplitPaneUI newUI) { 193 if (splitPane != null) { 194 splitPane.removePropertyChangeListener(this); 195 if (mouseHandler != null) { 196 splitPane.removeMouseListener(mouseHandler); 197 splitPane.removeMouseMotionListener(mouseHandler); 198 removeMouseListener(mouseHandler); 199 removeMouseMotionListener(mouseHandler); 200 mouseHandler = null; 201 } 202 } 203 splitPaneUI = newUI; 204 if (newUI != null) { 205 splitPane = newUI.getSplitPane(); 206 if (splitPane != null) { 207 if (mouseHandler == null) mouseHandler=new MotifMouseHandler(); 208 splitPane.addMouseListener(mouseHandler); 209 splitPane.addMouseMotionListener(mouseHandler); 210 addMouseListener(mouseHandler); 211 addMouseMotionListener(mouseHandler); 212 splitPane.addPropertyChangeListener(this); 213 if (splitPane.isOneTouchExpandable()) { 214 oneTouchExpandableChanged(); 215 } 216 } 217 } 218 else { 219 splitPane = null; 220 } 221 } 222 223 /** 224 * Returns true if the point at <code>x</code>, <code>y</code> 225 * is inside the thumb. 226 */ 227 private boolean isInThumb(int x, int y) { 228 Dimension size = getSize(); 229 int thumbX; 230 int thumbY; 231 int thumbWidth; 232 int thumbHeight; 233 234 if (getBasicSplitPaneUI().getOrientation() == 235 JSplitPane.HORIZONTAL_SPLIT) { 236 int center = size.width/2; 237 thumbX = center - hThumbWidth/2; 238 thumbY = hThumbOffset; 239 thumbWidth = hThumbWidth; 240 thumbHeight = hThumbHeight; 241 } 242 else { 243 int center = size.height/2; 244 thumbX = size.width - vThumbOffset; 245 thumbY = size.height/2 - vThumbHeight/2; 246 thumbWidth = vThumbWidth; 247 thumbHeight = vThumbHeight; 248 } 249 return (x >= thumbX && x < (thumbX + thumbWidth) && 250 y >= thumbY && y < (thumbY + thumbHeight)); 251 } 252 253 // 254 // Two methods are exposed so that MotifMouseHandler can see the 255 // superclass protected ivars 256 // 257 258 private DragController getDragger() { 259 return dragger; 260 } 261 262 private JSplitPane getSplitPane() { 263 return splitPane; 264 } 265 266 267 /** 268 * MouseHandler is subclassed to only pass off to super if the mouse 269 * is in the thumb. Motif only allows dragging when the thumb is clicked 270 * in. 271 */ 272 private class MotifMouseHandler extends MouseHandler { 273 public void mousePressed(MouseEvent e) { 274 // Constrain the mouse pressed to the thumb. 275 if (e.getSource() == MotifSplitPaneDivider.this && 276 getDragger() == null && getSplitPane().isEnabled() && 277 isInThumb(e.getX(), e.getY())) { 278 super.mousePressed(e); 279 } 280 } 281 282 public void mouseMoved(MouseEvent e) { 283 if (getDragger() != null) { 284 return; 285 } 286 if (!isInThumb(e.getX(), e.getY())) { 287 if (getCursor() != defaultCursor) { 288 setCursor(defaultCursor); 289 } 290 return; 291 } 292 super.mouseMoved(e); 293 } 294 } 295 }