2004-10-22 Michael Koch <konqueror@gmx.de>
[official-gcc.git] / libjava / javax / swing / plaf / basic / BasicButtonUI.java
blob21c888bb3663d7a7d57b4461a6ca88248ff4918d
1 /* BasicButtonUI.java
2 Copyright (C) 2002, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package javax.swing.plaf.basic;
40 import java.awt.Color;
41 import java.awt.Dimension;
42 import java.awt.Font;
43 import java.awt.FontMetrics;
44 import java.awt.Graphics;
45 import java.awt.Rectangle;
47 import javax.swing.AbstractButton;
48 import javax.swing.ButtonModel;
49 import javax.swing.Icon;
50 import javax.swing.InputMap;
51 import javax.swing.JComponent;
52 import javax.swing.SwingUtilities;
53 import javax.swing.UIDefaults;
54 import javax.swing.UIManager;
55 import javax.swing.plaf.ButtonUI;
56 import javax.swing.plaf.ComponentUI;
58 public class BasicButtonUI extends ButtonUI
60 /**
61 * A constant used to pad out elements in the button's layout and
62 * preferred size calculations.
64 protected int defaultTextIconGap = 4;
66 /**
67 * A constant added to the defaultTextIconGap to adjust the text
68 * within this particular button.
70 protected int defaultTextShiftOffset = 0;
72 private int textShiftOffset;
74 private Color focusColor;
76 /**
77 * Factory method to create an instance of BasicButtonUI for a given
78 * {@link JComponent}, which should be an {@link AbstractButton}.
80 * @param c The component to create a UI got
82 * @return A new UI capable of drawing the component
84 public static ComponentUI createUI(final JComponent c)
86 return new BasicButtonUI();
89 public int getDefaultTextIconGap(AbstractButton b)
91 return defaultTextIconGap;
94 protected void clearTextShiftOffset()
96 textShiftOffset = 0;
99 protected int getTextShiftOffset()
101 return textShiftOffset;
104 protected void setTextShiftOffset()
106 textShiftOffset = defaultTextShiftOffset;
109 protected void installDefaults(AbstractButton b)
111 UIDefaults defaults = UIManager.getLookAndFeelDefaults();
112 focusColor = defaults.getColor("Button.focus");
113 b.setForeground(defaults.getColor("Button.foreground"));
114 b.setBackground(defaults.getColor("Button.background"));
115 b.setMargin(defaults.getInsets("Button.margin"));
116 b.setBorder(defaults.getBorder("Button.border"));
117 b.setIconTextGap(defaults.getInt("Button.textIconGap"));
118 b.setInputMap(JComponent.WHEN_FOCUSED,
119 (InputMap) defaults.get("Button.focusInputMap"));
120 b.setOpaque(true);
123 protected void uninstallDefaults(AbstractButton b)
125 b.setForeground(null);
126 b.setBackground(null);
127 b.setBorder(null);
128 b.setIconTextGap(defaultTextIconGap);
129 b.setMargin(null);
132 protected BasicButtonListener listener;
134 protected BasicButtonListener createButtonListener(AbstractButton b)
136 return new BasicButtonListener();
139 public void installListeners(AbstractButton b)
141 listener = createButtonListener(b);
142 b.addChangeListener(listener);
143 b.addPropertyChangeListener(listener);
144 b.addFocusListener(listener);
145 b.addMouseListener(listener);
146 b.addMouseMotionListener(listener);
149 public void uninstallListeners(AbstractButton b)
151 b.removeChangeListener(listener);
152 b.removePropertyChangeListener(listener);
153 b.removeFocusListener(listener);
154 b.removeMouseListener(listener);
155 b.removeMouseMotionListener(listener);
158 protected void installKeyboardActions(AbstractButton b)
160 listener.installKeyboardActions(b);
163 protected void uninstallKeyboardActions(AbstractButton b)
165 listener.uninstallKeyboardActions(b);
169 * Install the BasicButtonUI as the UI for a particular component.
170 * This means registering all the UI's listeners with the component,
171 * and setting any properties of the button which are particular to
172 * this look and feel.
174 * @param c The component to install the UI into
176 public void installUI(final JComponent c)
178 super.installUI(c);
179 if (c instanceof AbstractButton)
181 AbstractButton b = (AbstractButton) c;
182 installDefaults(b);
183 installListeners(b);
184 installKeyboardActions(b);
189 * Calculate the preferred size of this component, by delegating to
190 * {@link BasicGraphicsUtils.getPreferredButtonSize}.
192 * @param c The component to measure
194 * @return The preferred dimensions of the component
196 public Dimension getPreferredSize(JComponent c)
198 AbstractButton b = (AbstractButton)c;
199 Dimension d =
200 BasicGraphicsUtils.getPreferredButtonSize
201 (b, defaultTextIconGap + defaultTextShiftOffset);
202 return d;
205 static private Icon currentIcon(AbstractButton b)
207 Icon i = b.getIcon();
208 ButtonModel model = b.getModel();
210 if (model.isPressed() && b.getPressedIcon() != null)
211 i = b.getPressedIcon();
213 else if (model.isRollover())
215 if (b.isSelected() && b.getRolloverSelectedIcon() != null)
216 i = b.getRolloverSelectedIcon();
217 else if (b.getRolloverIcon() != null)
218 i = b.getRolloverIcon();
221 else if (b.isSelected())
223 if (b.isEnabled() && b.getSelectedIcon() != null)
224 i = b.getSelectedIcon();
225 else if (b.getDisabledSelectedIcon() != null)
226 i = b.getDisabledSelectedIcon();
229 else if (! b.isEnabled() && b.getDisabledIcon() != null)
230 i = b.getDisabledIcon();
232 return i;
236 * Paint the component, which is an {@link AbstractButton}, according to
237 * its current state.
239 * @param g The graphics context to paint with
240 * @param c The component to paint the state of
242 public void paint(Graphics g, JComponent c)
244 AbstractButton b = (AbstractButton) c;
246 Rectangle tr = new Rectangle();
247 Rectangle ir = new Rectangle();
248 Rectangle vr = new Rectangle();
249 Rectangle br = new Rectangle();
251 Font f = c.getFont();
253 g.setFont(f);
255 SwingUtilities.calculateInnerArea(b, br);
256 SwingUtilities.calculateInsetArea(br, b.getMargin(), vr);
257 String text = SwingUtilities.layoutCompoundLabel(c, g.getFontMetrics(f),
258 b.getText(),
259 currentIcon(b),
260 b.getVerticalAlignment(),
261 b.getHorizontalAlignment(),
262 b.getVerticalTextPosition(),
263 b.getHorizontalTextPosition(),
264 vr, ir, tr,
265 b.getIconTextGap()
266 + defaultTextShiftOffset);
268 if ((b.getModel().isArmed() && b.getModel().isPressed())
269 || b.isSelected())
270 paintButtonPressed(g, b);
271 else
272 paintButtonNormal(g, br, c);
274 paintIcon(g, c, ir);
275 if (text != null)
276 paintText(g, b, tr, text);
277 paintFocus(g, b, vr, tr, ir);
281 * Paint any focus decoration this {@link JComponent} might have. The
282 * component, which in this case will be an {@link AbstractButton},
283 * should only have focus decoration painted if it has the focus, and its
284 * "focusPainted" property is <code>true</code>.
286 * @param g Graphics context to paint with
287 * @param b Button to paint the focus of
288 * @param vr Visible rectangle, the area in which to paint
289 * @param tr Text rectangle, contained in visible rectangle
290 * @param ir Icon rectangle, contained in visible rectangle
292 * @see AbstractButton.isFocusPainted()
293 * @see JComponent.hasFocus()
295 protected void paintFocus(Graphics g, AbstractButton b, Rectangle vr,
296 Rectangle tr, Rectangle ir)
298 if (b.hasFocus() && b.isFocusPainted())
300 Color saved_color = g.getColor();
301 g.setColor(focusColor);
302 Rectangle focusRect = ir.union(tr);
303 g.drawRect(focusRect.x, focusRect.y,
304 focusRect.width, focusRect.height);
305 g.setColor(saved_color);
310 * Paint the icon for this component. Depending on the state of the
311 * component and the availability of the button's various icon
312 * properties, this might mean painting one of several different icons.
314 * @param g Graphics context to paint with
315 * @param c Component to paint the icon of
316 * @param iconRect Rectangle in which the icon should be painted
318 protected void paintIcon(Graphics g, JComponent c, Rectangle iconRect)
320 AbstractButton b = (AbstractButton) c;
321 Icon i = currentIcon(b);
323 if (i != null)
324 i.paintIcon(c, g, iconRect.x, iconRect.y);
328 * Paints the background area of an {@link AbstractButton} in the pressed
329 * state. This means filling the supplied area with the {@link
330 * pressedBackgroundColor}.
332 * @param g The graphics context to paint with
333 * @param b The button to paint the state of
335 protected void paintButtonPressed(Graphics g, AbstractButton b)
337 if (b.isContentAreaFilled())
339 Rectangle area = new Rectangle();
340 SwingUtilities.calculateInnerArea(b, area);
341 g.setColor(b.getBackground().darker());
342 g.fillRect(area.x, area.y, area.width, area.height);
347 * Paints the background area of an {@link AbstractButton} in the normal,
348 * non-pressed state. This means filling the supplied area with the
349 * {@link normalBackgroundColor}.
351 * @param g The graphics context to paint with
352 * @param area The area in which to paint
353 * @param b The component to paint the state of
355 private void paintButtonNormal(Graphics g, Rectangle area, JComponent b)
357 if (((AbstractButton)b).isContentAreaFilled() && b.isOpaque())
359 g.setColor(b.getBackground());
360 g.fillRect(area.x, area.y, area.width, area.height);
365 * Paints the "text" property of an {@link AbstractButton}, using the
366 * {@link textColor} color.
368 * @param g The graphics context to paint with
369 * @param c The component to paint the state of
370 * @param textRect The area in which to paint the text
371 * @param text The text to paint
373 protected void paintText(Graphics g, JComponent c, Rectangle textRect,
374 String text)
376 paintText(g, (AbstractButton) c, textRect, text);
380 * Paints the "text" property of an {@link AbstractButton}, using the
381 * {@link textColor} color.
383 * @param g The graphics context to paint with
384 * @param b The button to paint the state of
385 * @param textRect The area in which to paint the text
386 * @param text The text to paint
388 * @since 1.4
390 protected void paintText(Graphics g, AbstractButton b, Rectangle textRect,
391 String text)
393 Font f = b.getFont();
394 g.setFont(f);
395 FontMetrics fm = g.getFontMetrics(f);
397 if (b.isEnabled())
399 g.setColor(b.getForeground());
400 g.drawString(text, textRect.x, textRect.y + fm.getAscent());
402 else
404 g.setColor(b.getBackground().brighter());
405 g.drawString(text, textRect.x, textRect.y + fm.getAscent());
406 g.setColor(b.getBackground().darker());
407 g.drawString(text, textRect.x + 1, textRect.y + fm.getAscent() + 1);