1. /*
  2. * @(#)MotifComboBoxUI.java 1.38 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.java.swing.plaf.motif;
  8. import java.awt.*;
  9. import javax.swing.*;
  10. import javax.swing.plaf.*;
  11. import javax.swing.border.*;
  12. import javax.swing.plaf.basic.*;
  13. import java.io.Serializable;
  14. import java.awt.event.*;
  15. /**
  16. * ComboBox motif look and feel
  17. * <p> * <strong>Warning:</strong>
  18. * Serialized objects of this class will not be compatible with
  19. * future Swing releases. The current serialization support is appropriate
  20. * for short term storage or RMI between applications running the same
  21. * version of Swing. A future release of Swing will provide support for
  22. * long term persistence.
  23. *
  24. * @version 1.38, 01/23/03
  25. * @author Arnaud Weber
  26. */
  27. public class MotifComboBoxUI extends BasicComboBoxUI implements Serializable {
  28. Icon arrowIcon;
  29. static final int HORIZ_MARGIN = 3;
  30. public static ComponentUI createUI(JComponent c) {
  31. return new MotifComboBoxUI();
  32. }
  33. public void installUI(JComponent c) {
  34. super.installUI(c);
  35. arrowIcon = new MotifComboBoxArrowIcon(UIManager.getColor("controlHighlight"),
  36. UIManager.getColor("controlShadow"),
  37. UIManager.getColor("control"));
  38. Runnable initCode = new Runnable() {
  39. public void run(){
  40. if ( motifGetEditor() != null ) {
  41. motifGetEditor().setBackground( UIManager.getColor( "text" ) );
  42. }
  43. }
  44. };
  45. SwingUtilities.invokeLater( initCode );
  46. }
  47. public Dimension getMinimumSize( JComponent c ) {
  48. if ( !isMinimumSizeDirty ) {
  49. return new Dimension( cachedMinimumSize );
  50. }
  51. Dimension size;
  52. Insets insets = getInsets();
  53. size = getDisplaySize();
  54. size.height += insets.top + insets.bottom;
  55. int buttonSize = iconAreaWidth();
  56. size.width += insets.left + insets.right + buttonSize;
  57. cachedMinimumSize.setSize( size.width, size.height );
  58. isMinimumSizeDirty = false;
  59. return size;
  60. }
  61. protected ComboPopup createPopup() {
  62. return new MotifComboPopup( comboBox );
  63. }
  64. /**
  65. * Overriden to empty the MouseMotionListener.
  66. */
  67. protected class MotifComboPopup extends BasicComboPopup {
  68. public MotifComboPopup( JComboBox comboBox ) {
  69. super( comboBox );
  70. }
  71. /**
  72. * Motif combo popup should not track the mouse in the list.
  73. */
  74. public MouseMotionListener createListMouseMotionListener() {
  75. return new MouseMotionAdapter() {};
  76. }
  77. public KeyListener createKeyListener() {
  78. return super.createKeyListener();
  79. }
  80. protected class InvocationKeyHandler extends BasicComboPopup.InvocationKeyHandler {
  81. protected InvocationKeyHandler() {
  82. MotifComboPopup.this.super();
  83. }
  84. }
  85. }
  86. protected void installComponents() {
  87. if ( comboBox.isEditable() ) {
  88. addEditor();
  89. }
  90. comboBox.add( currentValuePane );
  91. }
  92. protected void uninstallComponents() {
  93. removeEditor();
  94. comboBox.removeAll();
  95. }
  96. public void paint(Graphics g, JComponent c) {
  97. boolean hasFocus = comboBox.hasFocus();
  98. Rectangle r;
  99. if (comboBox.isEnabled()) {
  100. g.setColor(comboBox.getBackground());
  101. } else {
  102. g.setColor(UIManager.getColor("ComboBox.disabledBackground"));
  103. }
  104. g.fillRect(0,0,c.getWidth(),c.getHeight());
  105. if ( !comboBox.isEditable() ) {
  106. r = rectangleForCurrentValue();
  107. paintCurrentValue(g,r,hasFocus);
  108. }
  109. r = rectangleForArrowIcon();
  110. arrowIcon.paintIcon(c,g,r.x,r.y);
  111. if ( !comboBox.isEditable() ) {
  112. Border border = comboBox.getBorder();
  113. Insets in;
  114. if ( border != null ) {
  115. in = border.getBorderInsets(comboBox);
  116. }
  117. else {
  118. in = new Insets( 0, 0, 0, 0 );
  119. }
  120. // Draw the separation
  121. if(MotifGraphicsUtils.isLeftToRight(comboBox)) {
  122. r.x -= (HORIZ_MARGIN + 2);
  123. }
  124. else {
  125. r.x += r.width + HORIZ_MARGIN + 1;
  126. }
  127. r.y = in.top;
  128. r.width = 1;
  129. r.height = comboBox.getBounds().height - in.bottom - in.top;
  130. g.setColor(UIManager.getColor("controlShadow"));
  131. g.fillRect(r.x,r.y,r.width,r.height);
  132. r.x++;
  133. g.setColor(UIManager.getColor("controlHighlight"));
  134. g.fillRect(r.x,r.y,r.width,r.height);
  135. }
  136. }
  137. public void paintCurrentValue(Graphics g,Rectangle bounds,boolean hasFocus) {
  138. ListCellRenderer renderer = comboBox.getRenderer();
  139. Component c;
  140. Dimension d;
  141. c = renderer.getListCellRendererComponent(listBox, comboBox.getSelectedItem(), -1, false, false);
  142. c.setFont(comboBox.getFont());
  143. if ( comboBox.isEnabled() ) {
  144. c.setForeground(comboBox.getForeground());
  145. c.setBackground(comboBox.getBackground());
  146. }
  147. else {
  148. c.setForeground(UIManager.getColor("ComboBox.disabledForeground"));
  149. c.setBackground(UIManager.getColor("ComboBox.disabledBackground"));
  150. }
  151. d = c.getPreferredSize();
  152. currentValuePane.paintComponent(g,c,comboBox,bounds.x,bounds.y,
  153. bounds.width,d.height);
  154. }
  155. protected Rectangle rectangleForArrowIcon() {
  156. Rectangle b = comboBox.getBounds();
  157. Border border = comboBox.getBorder();
  158. Insets in;
  159. if ( border != null ) {
  160. in = border.getBorderInsets(comboBox);
  161. }
  162. else {
  163. in = new Insets( 0, 0, 0, 0 );
  164. }
  165. b.x = in.left;
  166. b.y = in.top;
  167. b.width -= (in.left + in.right);
  168. b.height -= (in.top + in.bottom);
  169. if(MotifGraphicsUtils.isLeftToRight(comboBox)) {
  170. b.x = b.x + b.width - HORIZ_MARGIN - arrowIcon.getIconWidth();
  171. }
  172. else {
  173. b.x += HORIZ_MARGIN;
  174. }
  175. b.y = b.y + (b.height - arrowIcon.getIconHeight()) / 2;
  176. b.width = arrowIcon.getIconWidth();
  177. b.height = arrowIcon.getIconHeight();
  178. return b;
  179. }
  180. protected Rectangle rectangleForCurrentValue() {
  181. int width = comboBox.getWidth();
  182. int height = comboBox.getHeight();
  183. Insets insets = getInsets();
  184. if(MotifGraphicsUtils.isLeftToRight(comboBox)) {
  185. return new Rectangle(insets.left, insets.top,
  186. (width - (insets.left + insets.right)) -
  187. iconAreaWidth(),
  188. height - (insets.top + insets.bottom));
  189. }
  190. else {
  191. return new Rectangle(insets.left + iconAreaWidth(), insets.top,
  192. (width - (insets.left + insets.right)) -
  193. iconAreaWidth(),
  194. height - (insets.top + insets.bottom));
  195. }
  196. }
  197. public int iconAreaWidth() {
  198. if ( comboBox.isEditable() )
  199. return arrowIcon.getIconWidth() + (2 * HORIZ_MARGIN);
  200. else
  201. return arrowIcon.getIconWidth() + (3 * HORIZ_MARGIN) + 2;
  202. }
  203. public void configureEditor() {
  204. super.configureEditor();
  205. editor.setBackground( UIManager.getColor( "text" ) );
  206. }
  207. protected LayoutManager createLayoutManager() {
  208. return new ComboBoxLayoutManager();
  209. }
  210. private Component motifGetEditor() {
  211. return editor;
  212. }
  213. /**
  214. * This inner class is marked "public" due to a compiler bug.
  215. * This class should be treated as a "protected" inner class.
  216. * Instantiate it only within subclasses of <FooUI>.
  217. */
  218. public class ComboBoxLayoutManager extends BasicComboBoxUI.ComboBoxLayoutManager {
  219. public ComboBoxLayoutManager() {
  220. MotifComboBoxUI.this.super();
  221. }
  222. public void layoutContainer(Container parent) {
  223. if ( motifGetEditor() != null ) {
  224. Rectangle cvb = rectangleForCurrentValue();
  225. cvb.x += 1;
  226. cvb.y += 1;
  227. cvb.width -= 1;
  228. cvb.height -= 2;
  229. motifGetEditor().setBounds(cvb);
  230. }
  231. }
  232. }
  233. static class MotifComboBoxArrowIcon implements Icon, Serializable {
  234. private Color lightShadow;
  235. private Color darkShadow;
  236. private Color fill;
  237. public MotifComboBoxArrowIcon(Color lightShadow, Color darkShadow, Color fill) {
  238. this.lightShadow = lightShadow;
  239. this.darkShadow = darkShadow;
  240. this.fill = fill;
  241. }
  242. public void paintIcon(Component c, Graphics g, int xo, int yo) {
  243. int w = getIconWidth();
  244. int h = getIconHeight();
  245. g.setColor(lightShadow);
  246. g.drawLine(xo, yo, xo+w-1, yo);
  247. g.drawLine(xo, yo+1, xo+w-3, yo+1);
  248. g.setColor(darkShadow);
  249. g.drawLine(xo+w-2, yo+1, xo+w-1, yo+1);
  250. for ( int x = xo+1, y = yo+2, dx = w-6; y+1 < yo+h; y += 2 ) {
  251. g.setColor(lightShadow);
  252. g.drawLine(x, y, x+1, y);
  253. g.drawLine(x, y+1, x+1, y+1);
  254. if ( dx > 0 ) {
  255. g.setColor(fill);
  256. g.drawLine(x+2, y, x+1+dx, y);
  257. g.drawLine(x+2, y+1, x+1+dx, y+1);
  258. }
  259. g.setColor(darkShadow);
  260. g.drawLine(x+dx+2, y, x+dx+3, y);
  261. g.drawLine(x+dx+2, y+1, x+dx+3, y+1);
  262. x += 1;
  263. dx -= 2;
  264. }
  265. g.setColor(darkShadow);
  266. g.drawLine(xo+(w2), yo+h-1, xo+(w2), yo+h-1);
  267. }
  268. public int getIconWidth() {
  269. return 11;
  270. }
  271. public int getIconHeight() {
  272. return 11;
  273. }
  274. }
  275. }