1 /* 2 * Copyright (c) 1997, 2006, 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 package com.sun.java.swing.plaf.motif; 26 27 import java.awt.*; 28 import javax.swing.*; 29 import javax.swing.plaf.*; 30 import javax.swing.border.*; 31 import javax.swing.plaf.basic.*; 32 import java.io.Serializable; 33 import java.awt.event.*; 34 import java.beans.*; 35 36 /** 37 * ComboBox motif look and feel 38 * <p> * <strong>Warning:</strong> 39 * Serialized objects of this class will not be compatible with 40 * future Swing releases. The current serialization support is appropriate 41 * for short term storage or RMI between applications running the same 42 * version of Swing. A future release of Swing will provide support for 43 * long term persistence. 44 * 45 * @author Arnaud Weber 46 */ 47 public class MotifComboBoxUI extends BasicComboBoxUI implements Serializable { 48 Icon arrowIcon; 49 static final int HORIZ_MARGIN = 3; 50 51 public static ComponentUI createUI(JComponent c) { 52 return new MotifComboBoxUI(); 53 } 54 55 public void installUI(JComponent c) { 56 super.installUI(c); 57 arrowIcon = new MotifComboBoxArrowIcon(UIManager.getColor("controlHighlight"), 58 UIManager.getColor("controlShadow"), 59 UIManager.getColor("control")); 60 61 Runnable initCode = new Runnable() { 62 public void run(){ 63 if ( motifGetEditor() != null ) { 64 motifGetEditor().setBackground( UIManager.getColor( "text" ) ); 65 } 66 } 67 }; 68 69 SwingUtilities.invokeLater( initCode ); 70 } 71 72 public Dimension getMinimumSize( JComponent c ) { 73 if ( !isMinimumSizeDirty ) { 74 return new Dimension( cachedMinimumSize ); 75 } 76 Dimension size; 77 Insets insets = getInsets(); 78 size = getDisplaySize(); 79 size.height += insets.top + insets.bottom; 80 int buttonSize = iconAreaWidth(); 81 size.width += insets.left + insets.right + buttonSize; 82 83 cachedMinimumSize.setSize( size.width, size.height ); 84 isMinimumSizeDirty = false; 85 86 return size; 87 } 88 89 protected ComboPopup createPopup() { 90 return new MotifComboPopup( comboBox ); 91 } 92 93 /** 94 * Overriden to empty the MouseMotionListener. 95 */ 96 protected class MotifComboPopup extends BasicComboPopup { 97 98 public MotifComboPopup( JComboBox comboBox ) { 99 super( comboBox ); 100 } 101 102 /** 103 * Motif combo popup should not track the mouse in the list. 104 */ 105 public MouseMotionListener createListMouseMotionListener() { 106 return new MouseMotionAdapter() {}; 107 } 108 109 public KeyListener createKeyListener() { 110 return super.createKeyListener(); 111 } 112 113 protected class InvocationKeyHandler extends BasicComboPopup.InvocationKeyHandler { 114 protected InvocationKeyHandler() { 115 MotifComboPopup.this.super(); 116 } 117 } 118 } 119 120 protected void installComponents() { 121 if ( comboBox.isEditable() ) { 122 addEditor(); 123 } 124 125 comboBox.add( currentValuePane ); 126 } 127 128 protected void uninstallComponents() { 129 removeEditor(); 130 comboBox.removeAll(); 131 } 132 133 public void paint(Graphics g, JComponent c) { 134 boolean hasFocus = comboBox.hasFocus(); 135 Rectangle r; 136 137 if (comboBox.isEnabled()) { 138 g.setColor(comboBox.getBackground()); 139 } else { 140 g.setColor(UIManager.getColor("ComboBox.disabledBackground")); 141 } 142 g.fillRect(0,0,c.getWidth(),c.getHeight()); 143 144 if ( !comboBox.isEditable() ) { 145 r = rectangleForCurrentValue(); 146 paintCurrentValue(g,r,hasFocus); 147 } 148 r = rectangleForArrowIcon(); 149 arrowIcon.paintIcon(c,g,r.x,r.y); 150 if ( !comboBox.isEditable() ) { 151 Border border = comboBox.getBorder(); 152 Insets in; 153 if ( border != null ) { 154 in = border.getBorderInsets(comboBox); 155 } 156 else { 157 in = new Insets( 0, 0, 0, 0 ); 158 } 159 // Draw the separation 160 if(MotifGraphicsUtils.isLeftToRight(comboBox)) { 161 r.x -= (HORIZ_MARGIN + 2); 162 } 163 else { 164 r.x += r.width + HORIZ_MARGIN + 1; 165 } 166 r.y = in.top; 167 r.width = 1; 168 r.height = comboBox.getBounds().height - in.bottom - in.top; 169 g.setColor(UIManager.getColor("controlShadow")); 170 g.fillRect(r.x,r.y,r.width,r.height); 171 r.x++; 172 g.setColor(UIManager.getColor("controlHighlight")); 173 g.fillRect(r.x,r.y,r.width,r.height); 174 } 175 } 176 177 public void paintCurrentValue(Graphics g,Rectangle bounds,boolean hasFocus) { 178 ListCellRenderer renderer = comboBox.getRenderer(); 179 Component c; 180 Dimension d; 181 c = renderer.getListCellRendererComponent(listBox, comboBox.getSelectedItem(), -1, false, false); 182 c.setFont(comboBox.getFont()); 183 if ( comboBox.isEnabled() ) { 184 c.setForeground(comboBox.getForeground()); 185 c.setBackground(comboBox.getBackground()); 186 } 187 else { 188 c.setForeground(UIManager.getColor("ComboBox.disabledForeground")); 189 c.setBackground(UIManager.getColor("ComboBox.disabledBackground")); 190 } 191 d = c.getPreferredSize(); 192 currentValuePane.paintComponent(g,c,comboBox,bounds.x,bounds.y, 193 bounds.width,d.height); 194 } 195 196 protected Rectangle rectangleForArrowIcon() { 197 Rectangle b = comboBox.getBounds(); 198 Border border = comboBox.getBorder(); 199 Insets in; 200 if ( border != null ) { 201 in = border.getBorderInsets(comboBox); 202 } 203 else { 204 in = new Insets( 0, 0, 0, 0 ); 205 } 206 b.x = in.left; 207 b.y = in.top; 208 b.width -= (in.left + in.right); 209 b.height -= (in.top + in.bottom); 210 211 if(MotifGraphicsUtils.isLeftToRight(comboBox)) { 212 b.x = b.x + b.width - HORIZ_MARGIN - arrowIcon.getIconWidth(); 213 } 214 else { 215 b.x += HORIZ_MARGIN; 216 } 217 b.y = b.y + (b.height - arrowIcon.getIconHeight()) / 2; 218 b.width = arrowIcon.getIconWidth(); 219 b.height = arrowIcon.getIconHeight(); 220 return b; 221 } 222 223 protected Rectangle rectangleForCurrentValue() { 224 int width = comboBox.getWidth(); 225 int height = comboBox.getHeight(); 226 Insets insets = getInsets(); 227 if(MotifGraphicsUtils.isLeftToRight(comboBox)) { 228 return new Rectangle(insets.left, insets.top, 229 (width - (insets.left + insets.right)) - 230 iconAreaWidth(), 231 height - (insets.top + insets.bottom)); 232 } 233 else { 234 return new Rectangle(insets.left + iconAreaWidth(), insets.top, 235 (width - (insets.left + insets.right)) - 236 iconAreaWidth(), 237 height - (insets.top + insets.bottom)); 238 } 239 } 240 241 public int iconAreaWidth() { 242 if ( comboBox.isEditable() ) 243 return arrowIcon.getIconWidth() + (2 * HORIZ_MARGIN); 244 else 245 return arrowIcon.getIconWidth() + (3 * HORIZ_MARGIN) + 2; 246 } 247 248 public void configureEditor() { 249 super.configureEditor(); 250 editor.setBackground( UIManager.getColor( "text" ) ); 251 } 252 253 protected LayoutManager createLayoutManager() { 254 return new ComboBoxLayoutManager(); 255 } 256 257 private Component motifGetEditor() { 258 return editor; 259 } 260 261 /** 262 * This inner class is marked "public" due to a compiler bug. 263 * This class should be treated as a "protected" inner class. 264 * Instantiate it only within subclasses of <FooUI>. 265 */ 266 public class ComboBoxLayoutManager extends BasicComboBoxUI.ComboBoxLayoutManager { 267 public ComboBoxLayoutManager() { 268 MotifComboBoxUI.this.super(); 269 } 270 public void layoutContainer(Container parent) { 271 if ( motifGetEditor() != null ) { 272 Rectangle cvb = rectangleForCurrentValue(); 273 cvb.x += 1; 274 cvb.y += 1; 275 cvb.width -= 1; 276 cvb.height -= 2; 277 motifGetEditor().setBounds(cvb); 278 } 279 } 280 } 281 282 static class MotifComboBoxArrowIcon implements Icon, Serializable { 283 private Color lightShadow; 284 private Color darkShadow; 285 private Color fill; 286 287 public MotifComboBoxArrowIcon(Color lightShadow, Color darkShadow, Color fill) { 288 this.lightShadow = lightShadow; 289 this.darkShadow = darkShadow; 290 this.fill = fill; 291 } 292 293 294 public void paintIcon(Component c, Graphics g, int xo, int yo) { 295 int w = getIconWidth(); 296 int h = getIconHeight(); 297 298 g.setColor(lightShadow); 299 g.drawLine(xo, yo, xo+w-1, yo); 300 g.drawLine(xo, yo+1, xo+w-3, yo+1); 301 g.setColor(darkShadow); 302 g.drawLine(xo+w-2, yo+1, xo+w-1, yo+1); 303 304 for ( int x = xo+1, y = yo+2, dx = w-6; y+1 < yo+h; y += 2 ) { 305 g.setColor(lightShadow); 306 g.drawLine(x, y, x+1, y); 307 g.drawLine(x, y+1, x+1, y+1); 308 if ( dx > 0 ) { 309 g.setColor(fill); 310 g.drawLine(x+2, y, x+1+dx, y); 311 g.drawLine(x+2, y+1, x+1+dx, y+1); 312 } 313 g.setColor(darkShadow); 314 g.drawLine(x+dx+2, y, x+dx+3, y); 315 g.drawLine(x+dx+2, y+1, x+dx+3, y+1); 316 x += 1; 317 dx -= 2; 318 } 319 320 g.setColor(darkShadow); 321 g.drawLine(xo+(w/2), yo+h-1, xo+(w/2), yo+h-1); 322 323 } 324 325 public int getIconWidth() { 326 return 11; 327 } 328 329 public int getIconHeight() { 330 return 11; 331 } 332 } 333 334 /** 335 *{@inheritDoc} 336 * 337 * @since 1.6 338 */ 339 protected PropertyChangeListener createPropertyChangeListener() { 340 return new MotifPropertyChangeListener(); 341 } 342 343 /** 344 * This class should be made "protected" in future releases. 345 */ 346 private class MotifPropertyChangeListener 347 extends BasicComboBoxUI.PropertyChangeHandler { 348 public void propertyChange(PropertyChangeEvent e) { 349 super.propertyChange(e); 350 String propertyName = e.getPropertyName(); 351 if (propertyName == "enabled") { 352 if (comboBox.isEnabled()) { 353 Component editor = motifGetEditor(); 354 if (editor != null) { 355 editor.setBackground(UIManager.getColor("text")); 356 } 357 } 358 } 359 } 360 } 361 }