blob: fa25a9390b9744dbca0b6f2931c7c733f3beb5e9 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1997-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25package com.sun.java.swing.plaf.motif;
26
27import java.awt.*;
28import javax.swing.*;
29import javax.swing.plaf.*;
30import javax.swing.border.*;
31import javax.swing.plaf.basic.*;
32import java.io.Serializable;
33import java.awt.event.*;
34import 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 */
47public 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 &quot;public&quot; due to a compiler bug.
263 * This class should be treated as a &quot;protected&quot; 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 &quot;protected&quot; 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}