1. /*
  2. * @(#)MetalComboBoxButton.java 1.38 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing.plaf.metal;
  8. import java.awt.*;
  9. import java.awt.event.*;
  10. import javax.swing.plaf.basic.*;
  11. import javax.swing.*;
  12. import javax.swing.plaf.*;
  13. import javax.swing.border.*;
  14. import java.io.Serializable;
  15. /**
  16. * JButton subclass to help out MetalComboBoxUI
  17. * <p>
  18. * <strong>Warning:</strong>
  19. * Serialized objects of this class will not be compatible with
  20. * future Swing releases. The current serialization support is
  21. * appropriate for short term storage or RMI between applications running
  22. * the same version of Swing. As of 1.4, support for long term storage
  23. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  24. * has been added to the <code>java.beans</code> package.
  25. * Please see {@link java.beans.XMLEncoder}.
  26. *
  27. * @see MetalComboBoxButton
  28. * @version 1.38 12/19/03
  29. * @author Tom Santos
  30. */
  31. public class MetalComboBoxButton extends JButton {
  32. protected JComboBox comboBox;
  33. protected JList listBox;
  34. protected CellRendererPane rendererPane;
  35. protected Icon comboIcon;
  36. protected boolean iconOnly = false;
  37. public final JComboBox getComboBox() { return comboBox;}
  38. public final void setComboBox( JComboBox cb ) { comboBox = cb;}
  39. public final Icon getComboIcon() { return comboIcon;}
  40. public final void setComboIcon( Icon i ) { comboIcon = i;}
  41. public final boolean isIconOnly() { return iconOnly;}
  42. public final void setIconOnly( boolean isIconOnly ) { iconOnly = isIconOnly;}
  43. MetalComboBoxButton() {
  44. super( "" );
  45. DefaultButtonModel model = new DefaultButtonModel() {
  46. public void setArmed( boolean armed ) {
  47. super.setArmed( isPressed() ? true : armed );
  48. }
  49. };
  50. setModel( model );
  51. }
  52. public MetalComboBoxButton( JComboBox cb, Icon i,
  53. CellRendererPane pane, JList list ) {
  54. this();
  55. comboBox = cb;
  56. comboIcon = i;
  57. rendererPane = pane;
  58. listBox = list;
  59. setEnabled( comboBox.isEnabled() );
  60. }
  61. public MetalComboBoxButton( JComboBox cb, Icon i, boolean onlyIcon,
  62. CellRendererPane pane, JList list ) {
  63. this( cb, i, pane, list );
  64. iconOnly = onlyIcon;
  65. }
  66. public boolean isFocusTraversable() {
  67. return false;
  68. }
  69. public void setEnabled(boolean enabled) {
  70. super.setEnabled(enabled);
  71. // Set the background and foreground to the combobox colors.
  72. if (enabled) {
  73. setBackground(comboBox.getBackground());
  74. setForeground(comboBox.getForeground());
  75. } else {
  76. setBackground(UIManager.getColor("ComboBox.disabledBackground"));
  77. setForeground(UIManager.getColor("ComboBox.disabledForeground"));
  78. }
  79. }
  80. public void paintComponent( Graphics g ) {
  81. boolean leftToRight = MetalUtils.isLeftToRight(comboBox);
  82. // Paint the button as usual
  83. super.paintComponent( g );
  84. Insets insets = getInsets();
  85. int width = getWidth() - (insets.left + insets.right);
  86. int height = getHeight() - (insets.top + insets.bottom);
  87. if ( height <= 0 || width <= 0 ) {
  88. return;
  89. }
  90. int left = insets.left;
  91. int top = insets.top;
  92. int right = left + (width - 1);
  93. int bottom = top + (height - 1);
  94. int iconWidth = 0;
  95. int iconLeft = (leftToRight) ? right : left;
  96. // Paint the icon
  97. if ( comboIcon != null ) {
  98. iconWidth = comboIcon.getIconWidth();
  99. int iconHeight = comboIcon.getIconHeight();
  100. int iconTop = 0;
  101. if ( iconOnly ) {
  102. iconLeft = (getWidth() / 2) - (iconWidth / 2);
  103. iconTop = (getHeight() / 2) - (iconHeight / 2);
  104. }
  105. else {
  106. if (leftToRight) {
  107. iconLeft = (left + (width - 1)) - iconWidth;
  108. }
  109. else {
  110. iconLeft = left;
  111. }
  112. iconTop = (top + ((bottom - top) / 2)) - (iconHeight / 2);
  113. }
  114. comboIcon.paintIcon( this, g, iconLeft, iconTop );
  115. // Paint the focus
  116. if ( comboBox.hasFocus() && (!MetalLookAndFeel.usingOcean() ||
  117. comboBox.isEditable())) {
  118. g.setColor( MetalLookAndFeel.getFocusColor() );
  119. g.drawRect( left - 1, top - 1, width + 3, height + 1 );
  120. }
  121. }
  122. if (MetalLookAndFeel.usingOcean()) {
  123. // With Ocean the button only paints the arrow, bail.
  124. return;
  125. }
  126. // Let the renderer paint
  127. if ( ! iconOnly && comboBox != null ) {
  128. ListCellRenderer renderer = comboBox.getRenderer();
  129. Component c;
  130. boolean renderPressed = getModel().isPressed();
  131. c = renderer.getListCellRendererComponent(listBox,
  132. comboBox.getSelectedItem(),
  133. -1,
  134. renderPressed,
  135. false);
  136. c.setFont(rendererPane.getFont());
  137. if ( model.isArmed() && model.isPressed() ) {
  138. if ( isOpaque() ) {
  139. c.setBackground(UIManager.getColor("Button.select"));
  140. }
  141. c.setForeground(comboBox.getForeground());
  142. }
  143. else if ( !comboBox.isEnabled() ) {
  144. if ( isOpaque() ) {
  145. c.setBackground(UIManager.getColor("ComboBox.disabledBackground"));
  146. }
  147. c.setForeground(UIManager.getColor("ComboBox.disabledForeground"));
  148. }
  149. else {
  150. c.setForeground(comboBox.getForeground());
  151. c.setBackground(comboBox.getBackground());
  152. }
  153. int cWidth = width - (insets.right + iconWidth);
  154. // Fix for 4238829: should lay out the JPanel.
  155. boolean shouldValidate = false;
  156. if (c instanceof JPanel) {
  157. shouldValidate = true;
  158. }
  159. if (leftToRight) {
  160. rendererPane.paintComponent( g, c, this,
  161. left, top, cWidth, height, shouldValidate );
  162. }
  163. else {
  164. rendererPane.paintComponent( g, c, this,
  165. left + iconWidth, top, cWidth, height, shouldValidate );
  166. }
  167. }
  168. }
  169. }