1. /*
  2. * @(#)MotifComboBoxUI.java 1.28 01/11/29
  3. *
  4. * Copyright 2002 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.25 10/30/98
  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. * This inner class is marked "public" due to a compiler bug.
  66. * This class should be treated as a "protected" inner class.
  67. * Instantiate it only within subclasses of <FooUI>.
  68. */
  69. public class MotifComboPopup extends BasicComboPopup {
  70. JComboBox cBox;
  71. public MotifComboPopup( JComboBox comboBox ) {
  72. super( comboBox );
  73. cBox = comboBox;
  74. }
  75. public MouseMotionListener createListMouseMotionListener() {
  76. return new MouseMotionAdapter() {};
  77. }
  78. public KeyListener createKeyListener() {
  79. return new InvocationKeyHandler();
  80. }
  81. /**
  82. * This inner class is marked "public" due to a compiler bug.
  83. * This class should be treated as a "protected" inner class.
  84. * Instantiate it only within subclasses of <FooUI>.
  85. */
  86. public class InvocationKeyHandler extends BasicComboPopup.InvocationKeyHandler {
  87. public void keyReleased( KeyEvent e ) {
  88. if ( !cBox.isEditable() ) {
  89. if ( e.getKeyCode() == KeyEvent.VK_DOWN ) {
  90. if ( !isVisible() ) {
  91. show();
  92. }
  93. }
  94. else {
  95. super.keyReleased( e );
  96. }
  97. }
  98. else {
  99. if ( e.getKeyCode() == KeyEvent.VK_UP ||
  100. e.getKeyCode() == KeyEvent.VK_DOWN ) {
  101. if ( !isVisible() ) {
  102. show();
  103. }
  104. }
  105. }
  106. }
  107. }
  108. }
  109. protected void installComponents() {
  110. if ( comboBox.isEditable() ) {
  111. addEditor();
  112. }
  113. comboBox.add( currentValuePane );
  114. }
  115. protected void uninstallComponents() {
  116. removeEditor();
  117. comboBox.removeAll();
  118. }
  119. public void paint(Graphics g, JComponent c) {
  120. boolean hasFocus = comboBox.hasFocus();
  121. Rectangle r;
  122. g.setColor(comboBox.getBackground()/*UIManager.getColor("ComboBox.control")*/);
  123. g.fillRect(0,0,c.getWidth(),c.getHeight());
  124. if ( !comboBox.isEditable() ) {
  125. r = rectangleForCurrentValue();
  126. paintCurrentValue(g,r,hasFocus);
  127. }
  128. r = rectangleForArrowIcon();
  129. arrowIcon.paintIcon(c,g,r.x,r.y);
  130. if ( !comboBox.isEditable() ) {
  131. Border border = comboBox.getBorder();
  132. Insets in;
  133. if ( border != null ) {
  134. in = border.getBorderInsets(comboBox);
  135. }
  136. else {
  137. in = new Insets( 0, 0, 0, 0 );
  138. }
  139. // Draw the separation
  140. r.x -= (HORIZ_MARGIN + 2);
  141. r.y = in.top;
  142. r.width = 1;
  143. r.height = comboBox.getBounds().height - in.bottom - in.top;
  144. g.setColor(UIManager.getColor("controlShadow"));
  145. g.fillRect(r.x,r.y,r.width,r.height);
  146. r.x++;
  147. g.setColor(UIManager.getColor("controlHighlight"));
  148. g.fillRect(r.x,r.y,r.width,r.height);
  149. }
  150. }
  151. public void paintCurrentValue(Graphics g,Rectangle bounds,boolean hasFocus) {
  152. ListCellRenderer renderer = comboBox.getRenderer();
  153. Component c;
  154. Dimension d;
  155. c = renderer.getListCellRendererComponent(listBox, comboBox.getSelectedItem(), -1, false, false);
  156. c.setFont(comboBox.getFont());
  157. if ( comboBox.isEnabled() ) {
  158. c.setForeground(comboBox.getForeground());
  159. c.setBackground(comboBox.getBackground());
  160. }
  161. else {
  162. c.setForeground(UIManager.getColor("ComboBox.disabledForeground"));
  163. c.setBackground(UIManager.getColor("ComboBox.disabledBackground"));
  164. }
  165. d = c.getPreferredSize();
  166. currentValuePane.paintComponent(g,c,comboBox,bounds.x,bounds.y,
  167. bounds.width,d.height);
  168. }
  169. protected Rectangle rectangleForArrowIcon() {
  170. Rectangle b = comboBox.getBounds();
  171. Border border = comboBox.getBorder();
  172. Insets in;
  173. if ( border != null ) {
  174. in = border.getBorderInsets(comboBox);
  175. }
  176. else {
  177. in = new Insets( 0, 0, 0, 0 );
  178. }
  179. b.x = in.left;
  180. b.y = in.top;
  181. b.width -= (in.left + in.right);
  182. b.height -= (in.top + in.bottom);
  183. b.x = b.x + b.width - HORIZ_MARGIN - arrowIcon.getIconWidth();
  184. b.y = b.y + (b.height - arrowIcon.getIconHeight()) / 2;
  185. b.width = arrowIcon.getIconWidth();
  186. b.height = arrowIcon.getIconHeight();
  187. return b;
  188. }
  189. protected Rectangle rectangleForCurrentValue() {
  190. int width = comboBox.getWidth();
  191. int height = comboBox.getHeight();
  192. Insets insets = getInsets();
  193. return new Rectangle(insets.left, insets.top,
  194. (width - (insets.left + insets.right)) - iconAreaWidth(),
  195. height - (insets.top + insets.bottom));
  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. 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 void layoutContainer(Container parent) {
  220. if ( motifGetEditor() != null ) {
  221. Rectangle cvb = rectangleForCurrentValue();
  222. cvb.x += 1;
  223. cvb.y += 1;
  224. cvb.width -= 1;
  225. cvb.height -= 2;
  226. motifGetEditor().setBounds(cvb);
  227. }
  228. }
  229. }
  230. static class MotifComboBoxArrowIcon implements Icon, Serializable {
  231. private Color lightShadow;
  232. private Color darkShadow;
  233. private Color fill;
  234. public MotifComboBoxArrowIcon(Color lightShadow, Color darkShadow, Color fill) {
  235. this.lightShadow = lightShadow;
  236. this.darkShadow = darkShadow;
  237. this.fill = fill;
  238. }
  239. public void paintIcon(Component c, Graphics g, int xo, int yo) {
  240. int w = getIconWidth();
  241. int h = getIconHeight();
  242. g.setColor(lightShadow);
  243. g.drawLine(xo, yo, xo+w-1, yo);
  244. g.drawLine(xo, yo+1, xo+w-3, yo+1);
  245. g.setColor(darkShadow);
  246. g.drawLine(xo+w-2, yo+1, xo+w-1, yo+1);
  247. for ( int x = xo+1, y = yo+2, dx = w-6; y+1 < yo+h; y += 2 ) {
  248. g.setColor(lightShadow);
  249. g.drawLine(x, y, x+1, y);
  250. g.drawLine(x, y+1, x+1, y+1);
  251. if ( dx > 0 ) {
  252. g.setColor(fill);
  253. g.drawLine(x+2, y, x+1+dx, y);
  254. g.drawLine(x+2, y+1, x+1+dx, y+1);
  255. }
  256. g.setColor(darkShadow);
  257. g.drawLine(x+dx+2, y, x+dx+3, y);
  258. g.drawLine(x+dx+2, y+1, x+dx+3, y+1);
  259. x += 1;
  260. dx -= 2;
  261. }
  262. g.setColor(darkShadow);
  263. g.drawLine(xo+(w2), yo+h-1, xo+(w2), yo+h-1);
  264. }
  265. public int getIconWidth() {
  266. return 11;
  267. }
  268. public int getIconHeight() {
  269. return 11;
  270. }
  271. }
  272. protected void selectNextPossibleValue() {
  273. super.selectNextPossibleValue();
  274. }
  275. protected void selectPreviousPossibleValue() {
  276. super.selectPreviousPossibleValue();
  277. }
  278. /**
  279. * This method is here as a workaround for a bug in the javac compiler.
  280. */
  281. JComboBox motifGetComboBox() {
  282. return comboBox;
  283. }
  284. /**
  285. * This method is here as a workaround for a bug in the javac compiler.
  286. */
  287. MotifComboBoxUI motifGetUI() {
  288. return this;
  289. }
  290. protected void installKeyboardActions() {
  291. super.installKeyboardActions();
  292. ActionListener downAction = new ActionListener() {
  293. public void actionPerformed( ActionEvent e ) {
  294. if ( motifGetComboBox().isEnabled() && isPopupVisible(motifGetComboBox()) ) {
  295. motifGetUI().selectNextPossibleValue();
  296. }
  297. }
  298. };
  299. motifGetComboBox().registerKeyboardAction( downAction,
  300. KeyStroke.getKeyStroke( KeyEvent.VK_DOWN, 0 ),
  301. JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
  302. ActionListener upAction = new ActionListener() {
  303. public void actionPerformed( ActionEvent e ) {
  304. if ( motifGetComboBox().isEnabled() && isPopupVisible(motifGetComboBox()) ) {
  305. motifGetUI().selectPreviousPossibleValue();
  306. }
  307. }
  308. };
  309. motifGetComboBox().registerKeyboardAction( upAction,
  310. KeyStroke.getKeyStroke( KeyEvent.VK_UP, 0 )
  311. ,JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
  312. }
  313. protected void uninstallKeyboardActions() {
  314. super.uninstallKeyboardActions();
  315. comboBox.unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN,0));
  316. comboBox.unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_UP,0));
  317. }
  318. }