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