001: /*
002: * Copyright (c) 2005-2008 Substance Kirill Grouchnikov. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of Substance Kirill Grouchnikov nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030: package org.jvnet.substance;
031:
032: import java.awt.*;
033: import java.awt.event.FocusEvent;
034: import java.awt.event.FocusListener;
035: import java.beans.PropertyChangeEvent;
036:
037: import javax.swing.*;
038: import javax.swing.border.Border;
039: import javax.swing.border.EmptyBorder;
040: import javax.swing.plaf.*;
041: import javax.swing.plaf.basic.BasicComboBoxUI;
042: import javax.swing.plaf.basic.ComboPopup;
043:
044: import org.jvnet.lafwidget.animation.FadeStateListener;
045: import org.jvnet.lafwidget.layout.TransitionLayout;
046: import org.jvnet.substance.button.BaseButtonShaper;
047: import org.jvnet.substance.color.ColorScheme;
048: import org.jvnet.substance.combo.*;
049: import org.jvnet.substance.painter.highlight.SubstanceHighlightUtils;
050: import org.jvnet.substance.painter.text.SubstanceTextPainter;
051: import org.jvnet.substance.theme.SubstanceTheme;
052: import org.jvnet.substance.utils.*;
053: import org.jvnet.substance.utils.SubstanceConstants.Side;
054:
055: /**
056: * UI for combo boxes in <b>Substance </b> look and feel.
057: *
058: * @author Kirill Grouchnikov
059: * @author Thomas Bierhance http://www.orbital-computer.de/JComboBox/
060: * @author inostock
061: */
062: public class SubstanceComboBoxUI extends BasicComboBoxUI {
063: /**
064: * Property change handler on <code>enabled</code> property,
065: * <code>componentOrientation</code> property and on
066: * {@link SubstanceLookAndFeel#COMBO_BOX_POPUP_FLYOUT_ORIENTATION} property.
067: */
068: protected ComboBoxPropertyChangeHandler substanceChangeHandler;
069:
070: /**
071: * Listener for fade animations.
072: */
073: protected FadeStateListener substanceFadeStateListener;
074:
075: /**
076: * Focus listener on the combobox.
077: */
078: protected FocusListener substanceFocusListener;
079:
080: private static SubstanceFillBackgroundDelegate backgroundDelegate = new SubstanceFillBackgroundDelegate();
081:
082: /*
083: * (non-Javadoc)
084: *
085: * @see javax.swing.plaf.ComponentUI#createUI(javax.swing.JComponent)
086: */
087: public static ComponentUI createUI(JComponent b) {
088: SubstanceComboBoxUI ui = new SubstanceComboBoxUI();
089: ui.comboBox = (JComboBox) b;
090: ui.comboBox.setOpaque(false);
091: return ui;
092: }
093:
094: /*
095: * (non-Javadoc)
096: *
097: * @see javax.swing.plaf.basic.BasicComboBoxUI#createArrowButton()
098: */
099: @Override
100: protected JButton createArrowButton() {
101: SubstanceComboBoxButton result = new SubstanceComboBoxButton(
102: this .comboBox);
103: result.setIcon(this .comboBox, getCurrentIcon(result));
104: result.setFont(this .comboBox.getFont());
105: return result;
106: }
107:
108: /**
109: * Returns the icon for the specified arrow button.
110: *
111: * @param button
112: * Arrow button.
113: * @return Icon for the specified button.
114: */
115: private Icon getCurrentIcon(JButton button) {
116: Icon icon = SubstanceCoreUtilities.getArrowIcon(this .comboBox,
117: button, SubstanceCoreUtilities
118: .getPopupFlyoutOrientation(this .comboBox));
119: return icon;
120: }
121:
122: /*
123: * (non-Javadoc)
124: *
125: * @see javax.swing.plaf.basic.BasicComboBoxUI#createRenderer()
126: */
127: @Override
128: protected ListCellRenderer createRenderer() {
129: return new SubstanceDefaultComboBoxRenderer.SubstanceUIResource(
130: this .comboBox);
131: }
132:
133: /*
134: * (non-Javadoc)
135: *
136: * @see javax.swing.plaf.basic.BasicComboBoxUI#installListeners()
137: */
138: @Override
139: protected void installListeners() {
140: super .installListeners();
141: this .substanceChangeHandler = new ComboBoxPropertyChangeHandler();
142: this .comboBox
143: .addPropertyChangeListener(this .substanceChangeHandler);
144:
145: this .substanceFadeStateListener = new FadeStateListener(
146: this .comboBox, null, null);
147: this .substanceFadeStateListener.registerListeners();
148: }
149:
150: /*
151: * (non-Javadoc)
152: *
153: * @see javax.swing.plaf.basic.BasicComboBoxUI#uninstallListeners()
154: */
155: @Override
156: protected void uninstallListeners() {
157: this .substanceFadeStateListener.unregisterListeners();
158: this .substanceFadeStateListener = null;
159:
160: this .comboBox
161: .removePropertyChangeListener(this .substanceChangeHandler);
162: this .substanceChangeHandler = null;
163: super .uninstallListeners();
164: }
165:
166: /*
167: * (non-Javadoc)
168: *
169: * @see javax.swing.plaf.basic.BasicComboBoxUI#installDefaults()
170: */
171: @Override
172: protected void installDefaults() {
173: super .installDefaults();
174: Border b = this .comboBox.getBorder();
175: if (b == null || b instanceof UIResource) {
176: Border newB = new SubstanceBorder(SubstanceSizeUtils
177: .getComboBorderInsets(SubstanceSizeUtils
178: .getComponentFontSize(this .comboBox)));
179:
180: this .comboBox.setBorder(newB);
181: }
182: }
183:
184: /*
185: * (non-Javadoc)
186: *
187: * @see javax.swing.plaf.basic.BasicComboBoxUI#createLayoutManager()
188: */
189: @Override
190: protected LayoutManager createLayoutManager() {
191: return new SubstanceComboBoxLayoutManager();
192: }
193:
194: /**
195: * Layout manager for combo box.
196: *
197: * @author Kirill Grouchnikov
198: */
199: private class SubstanceComboBoxLayoutManager extends
200: BasicComboBoxUI.ComboBoxLayoutManager {
201:
202: /*
203: * (non-Javadoc)
204: *
205: * @see java.awt.LayoutManager#layoutContainer(java.awt.Container)
206: */
207: @Override
208: public void layoutContainer(Container parent) {
209: JComboBox cb = (JComboBox) parent;
210:
211: int width = cb.getWidth();
212: int height = cb.getHeight();
213:
214: Insets insets = SubstanceComboBoxUI.this .getInsets();
215: int buttonWidth = SubstanceSizeUtils
216: .getScrollBarWidth(SubstanceSizeUtils
217: .getComponentFontSize(comboBox));
218: buttonWidth = Math.max(buttonWidth, arrowButton
219: .getPreferredSize().width);
220:
221: if (SubstanceComboBoxUI.this .arrowButton != null) {
222: if (cb.getComponentOrientation().isLeftToRight()) {
223: SubstanceComboBoxUI.this .arrowButton.setBounds(
224: width - buttonWidth - insets.right, 0,
225: buttonWidth + insets.right, height);
226: } else {
227: SubstanceComboBoxUI.this .arrowButton.setBounds(0,
228: 0, buttonWidth + insets.left, height);
229: }
230: }
231: if (SubstanceComboBoxUI.this .editor != null) {
232: SubstanceComboBoxUI.this .editor
233: .setBounds(SubstanceComboBoxUI.this
234: .rectangleForCurrentValue());
235: }
236: }
237: }
238:
239: /*
240: * (non-Javadoc)
241: *
242: * @see javax.swing.plaf.basic.BasicComboBoxUI#getDefaultSize()
243: */
244: @Override
245: protected Dimension getDefaultSize() {
246: Component rend = new SubstanceDefaultComboBoxRenderer(
247: this .comboBox).getListCellRendererComponent(listBox,
248: " ", -1, false, false);
249: rend.setFont(this .comboBox.getFont());
250:
251: return rend.getPreferredSize();
252: }
253:
254: /*
255: * (non-Javadoc)
256: *
257: * @see javax.swing.plaf.basic.BasicComboBoxUI#getMinimumSize(javax.swing.JComponent)
258: */
259: @Override
260: public Dimension getMinimumSize(JComponent c) {
261: if (!this .isMinimumSizeDirty) {
262: return new Dimension(this .cachedMinimumSize);
263: }
264:
265: Dimension size = null;
266:
267: if (!this .comboBox.isEditable() && this .arrowButton != null
268: && this .arrowButton instanceof SubstanceComboBoxButton) {
269:
270: SubstanceComboBoxButton button = (SubstanceComboBoxButton) this .arrowButton;
271: Insets buttonInsets = button.getInsets();
272: Insets insets = this .comboBox.getInsets();
273:
274: size = this .getDisplaySize();
275:
276: size.width += insets.left + insets.right;
277: size.width += buttonInsets.left + buttonInsets.right;
278: size.width += button.getMinimumSize().getWidth();
279: size.height += insets.top + insets.bottom;
280: } else if (this .comboBox.isEditable()
281: && this .arrowButton != null && this .editor != null) {
282: size = super .getMinimumSize(c);
283: } else {
284: size = super .getMinimumSize(c);
285: }
286:
287: this .cachedMinimumSize.setSize(size.width, size.height);
288: this .isMinimumSizeDirty = false;
289:
290: return new Dimension(this .cachedMinimumSize);
291: }
292:
293: /**
294: * This property change handler changes combo box arrow icon based on the
295: * enabled status of the combo box.
296: *
297: * @author Kirill Grouchnikov
298: */
299: public class ComboBoxPropertyChangeHandler extends
300: PropertyChangeHandler {
301: /*
302: * (non-Javadoc)
303: *
304: * @see javax.swing.plaf.basic.BasicComboBoxUI$PropertyChangeHandler#propertyChange(java.beans.PropertyChangeEvent)
305: */
306: @Override
307: public void propertyChange(final PropertyChangeEvent e) {
308: String propertyName = e.getPropertyName();
309:
310: if (propertyName.equals("componentOrientation")) {
311: SwingUtilities.invokeLater(new Runnable() {
312: public void run() {
313: if (SubstanceComboBoxUI.this .comboBox == null)
314: return;
315: final ComponentOrientation newOrientation = (ComponentOrientation) e
316: .getNewValue();
317: final ListCellRenderer cellRenderer = SubstanceComboBoxUI.this .comboBox
318: .getRenderer();
319: final ComboBoxEditor editor = SubstanceComboBoxUI.this .comboBox
320: .getEditor();
321: if (SubstanceComboBoxUI.this .popup instanceof Component) {
322: final Component cPopup = (Component) SubstanceComboBoxUI.this .popup;
323: cPopup
324: .applyComponentOrientation(newOrientation);
325: cPopup.doLayout();
326: }
327: if (cellRenderer instanceof Component) {
328: ((Component) cellRenderer)
329: .applyComponentOrientation(newOrientation);
330: }
331: if ((editor != null)
332: && (editor.getEditorComponent() instanceof Component)) {
333: (editor.getEditorComponent())
334: .applyComponentOrientation(newOrientation);
335: }
336: if (SubstanceComboBoxUI.this .comboBox != null)
337: SubstanceComboBoxUI.this .comboBox.repaint();
338:
339: configureArrowButtonStraightSide();
340: }
341: });
342: }
343:
344: if (SubstanceLookAndFeel.COMBO_BOX_POPUP_FLYOUT_ORIENTATION
345: .equals(propertyName)) {
346: ((SubstanceComboBoxButton) arrowButton)
347: .setIcon(
348: comboBox,
349: SubstanceCoreUtilities
350: .getArrowIcon(
351: comboBox,
352: arrowButton,
353: // theme,
354: SubstanceCoreUtilities
355: .getPopupFlyoutOrientation(SubstanceComboBoxUI.this .comboBox)));
356:
357: }
358:
359: if ("font".equals(propertyName)) {
360: SwingUtilities.invokeLater(new Runnable() {
361: public void run() {
362: comboBox.updateUI();
363: }
364: });
365: }
366:
367: if ("background".equals(propertyName)) {
368: if (comboBox.isEditable()) {
369: comboBox.getEditor().getEditorComponent()
370: .setBackground(comboBox.getBackground());
371: popup.getList().setBackground(
372: comboBox.getBackground());
373: }
374: }
375: // Do not call super - fix for bug 63
376: }
377: }
378:
379: /*
380: * (non-Javadoc)
381: *
382: * @see javax.swing.plaf.basic.BasicComboBoxUI#createPopup()
383: */
384: @Override
385: protected ComboPopup createPopup() {
386: final ComboPopup sPopup = new SubstanceComboPopup(this .comboBox);
387:
388: final ComponentOrientation currOrientation = this .comboBox
389: .getComponentOrientation();
390:
391: SwingUtilities.invokeLater(new Runnable() {
392: public void run() {
393: if (SubstanceComboBoxUI.this .comboBox == null)
394: return;
395:
396: if (sPopup instanceof Component) {
397: final Component cPopup = (Component) sPopup;
398: cPopup.applyComponentOrientation(currOrientation);
399: cPopup.doLayout();
400: }
401: ListCellRenderer cellRenderer = SubstanceComboBoxUI.this .comboBox
402: .getRenderer();
403: if (cellRenderer instanceof Component) {
404: ((Component) cellRenderer)
405: .applyComponentOrientation(currOrientation);
406: }
407: ComboBoxEditor editor = SubstanceComboBoxUI.this .comboBox
408: .getEditor();
409: if ((editor != null)
410: && (editor.getEditorComponent() instanceof Component)) {
411: (editor.getEditorComponent())
412: .applyComponentOrientation(currOrientation);
413: }
414: SubstanceComboBoxUI.this .comboBox.repaint();
415: }
416: });
417: return sPopup;
418: }
419:
420: /*
421: * (non-Javadoc)
422: *
423: * @see javax.swing.plaf.basic.BasicComboBoxUI#paintCurrentValueBackground(java.awt.Graphics,
424: * java.awt.Rectangle, boolean)
425: */
426: @Override
427: public void paintCurrentValueBackground(Graphics g,
428: Rectangle bounds, boolean hasFocus) {
429: ListUI listUI = this .popup.getList().getUI();
430: SubstanceListUI ui = (SubstanceListUI) listUI;
431: ComponentState state = ui.getCellState(-1);
432: // ComponentState prevState = ui.getPrevCellState(-1);
433: boolean isEnabled = this .comboBox.isEnabled();
434: boolean isSelected = hasFocus
435: || SubstanceCoreUtilities
436: .isControlAlwaysPaintedActive(this .comboBox);
437: if (isSelected && isEnabled) {
438: state = ComponentState.SELECTED;
439: }
440: if (!isEnabled) {
441: state = ComponentState.DISABLED_UNSELECTED;
442: }
443:
444: Graphics2D graphics = (Graphics2D) g.create();
445: SubstanceTheme theme = SubstanceThemeUtilities.getTheme(
446: this .comboBox, state);
447: final ColorScheme colorScheme = theme.getColorScheme();
448: float alpha = theme.getThemeAlpha(this .comboBox, state);
449: if (!SubstanceCoreUtilities
450: .isControlAlwaysPaintedActive(this .comboBox)) {
451: alpha = 0.8f * alpha;
452: }
453:
454: ListCellRenderer renderer = this .comboBox.getRenderer();
455: boolean toRegardAsFocused = hasFocus
456: || SubstanceCoreUtilities
457: .isControlAlwaysPaintedActive(this .comboBox);
458: Component c = renderer.getListCellRendererComponent(
459: this .listBox, this .comboBox.getSelectedItem(), -1,
460: toRegardAsFocused, hasFocus);
461:
462: Color background = c.getBackground();
463: if (!(background instanceof UIResource)) {
464: // support for enhancement 256 - colorizing components
465: double colorization = SubstanceCoreUtilities
466: .getColorizationFactor(this .comboBox);
467: if (!this .comboBox.isEnabled())
468: colorization /= 2.0;
469: if (colorization > 0.0) {
470: // the larger the colorization is, the lighter should the
471: // overlay be
472: alpha *= (1.0 - colorization);
473: }
474: }
475:
476: final float finalAlpha = alpha;
477:
478: // final SubstanceTheme theme =
479: // SubstanceCoreUtilities.getTheme(this.popup
480: // .getList(), state, true, true, true);
481:
482: final Rectangle newBounds = new Rectangle(1, 1, this .comboBox
483: .getWidth() - 2, this .comboBox.getHeight() - 2);
484:
485: SubstanceTextPainter textPainter = SubstanceLookAndFeel
486: .getCurrentTextPainter();
487: textPainter.init(this .comboBox, null, true);
488: if (textPainter.needsBackgroundImage()) {
489: textPainter.setBackgroundFill(this .comboBox, this .comboBox
490: .getBackground(), false, 0, 0);
491: // final ComponentState finalState = state;
492: textPainter
493: .attachCallback(new SubstanceTextPainter.BackgroundPaintingCallback() {
494: public void paintBackground(Graphics g) {
495: Graphics2D g2d = (Graphics2D) g.create();
496: g2d.setComposite(TransitionLayout
497: .getAlphaComposite(comboBox,
498: finalAlpha, g));
499: SubstanceHighlightUtils.paintHighlight(g2d,
500: comboBox, new Rectangle(0, 0,
501: comboBox.getWidth(),
502: comboBox.getHeight()),
503: 0.0f, null, colorScheme,
504: colorScheme, 0.0f);
505: g2d.dispose();
506: }
507: });
508: // The text GC will be clipped to the renderer bound. To
509: // have the background painted across the entire area, enforce
510: // this by painting space string now that the clip is not set
511: textPainter.attachText(this .comboBox, newBounds, " ", -1,
512: graphics.getFont(), graphics.getColor(), graphics
513: .getClipBounds());
514: textPainter.renderSurface(graphics);
515: } else {
516: backgroundDelegate.fillAndWatermark(graphics,
517: this .comboBox, background, newBounds);
518: graphics.setComposite(TransitionLayout.getAlphaComposite(
519: this .comboBox, finalAlpha, g));
520:
521: SubstanceHighlightUtils.paintHighlight(graphics,
522: this .comboBox, newBounds, 0.0f, null, colorScheme,
523: colorScheme, 0.0f);
524: }
525: graphics.dispose();
526: }
527:
528: /*
529: * (non-Javadoc)
530: *
531: * @see javax.swing.plaf.basic.BasicComboBoxUI#paintCurrentValue(java.awt.Graphics,
532: * java.awt.Rectangle, boolean)
533: */
534: @Override
535: public void paintCurrentValue(Graphics g, Rectangle bounds,
536: boolean hasFocus) {
537: Graphics2D graphics = (Graphics2D) g.create();
538: ComponentState state = this .comboBox.isEnabled() ? ComponentState.DEFAULT
539: : ComponentState.DISABLED_UNSELECTED;
540: float alpha = SubstanceThemeUtilities.getTheme(this .comboBox)
541: .getThemeAlpha(this .comboBox, state);
542: graphics.setComposite(TransitionLayout.getAlphaComposite(
543: this .comboBox, alpha, g));
544:
545: ListCellRenderer renderer = this .comboBox.getRenderer();
546: // if (renderer instanceof SubstanceDefaultListCellRenderer) {
547: Component c;
548: if (hasFocus
549: || SubstanceCoreUtilities
550: .isControlAlwaysPaintedActive(this .comboBox)) {
551: c = renderer
552: .getListCellRendererComponent(this .listBox,
553: this .comboBox.getSelectedItem(), -1, true,
554: hasFocus);
555: } else {
556: c = renderer.getListCellRendererComponent(this .listBox,
557: this .comboBox.getSelectedItem(), -1, false,
558: hasFocus);
559: }
560: c.setFont(this .comboBox.getFont());
561:
562: // Fix for 4238829: should lay out the JPanel.
563: boolean shouldValidate = false;
564: if (c instanceof JPanel) {
565: shouldValidate = true;
566: }
567:
568: // SubstanceCoreUtilities.workaroundBug6576507(graphics);
569:
570: if (c instanceof JComponent) {
571: ((JComponent) comboBox).putClientProperty(
572: SubstanceCoreUtilities.DO_NOT_FILL_BACKGROUND,
573: Boolean.TRUE);
574: }
575: // Insets ins = this.comboBox.getInsets();
576:
577: if (this .comboBox.getComponentOrientation().isLeftToRight()) {
578: this .currentValuePane.paintComponent(graphics, c,
579: this .comboBox, 1, 1, this .arrowButton.getX() - 1,
580: this .comboBox.getHeight() - 2, shouldValidate);
581: } else {
582: int startX = this .arrowButton.getX()
583: + this .arrowButton.getWidth();
584: this .currentValuePane.paintComponent(graphics, c,
585: this .comboBox, startX, 1, this .comboBox.getWidth()
586: - startX - 1,
587: this .comboBox.getHeight() - 2, shouldValidate);
588: }
589: if (c instanceof JComponent) {
590: ((JComponent) comboBox)
591: .putClientProperty(
592: SubstanceCoreUtilities.DO_NOT_FILL_BACKGROUND,
593: null);
594: }
595: // } else {
596: // super.paintCurrentValue(g, bounds, hasFocus);
597: // }
598:
599: graphics.dispose();
600: }
601:
602: /*
603: * (non-Javadoc)
604: *
605: * @see javax.swing.plaf.basic.BasicComboBoxUI#paint(java.awt.Graphics,
606: * javax.swing.JComponent)
607: */
608: @Override
609: public void paint(Graphics g, JComponent c) {
610: super .paint(g, c);
611: this .hasFocus = this .comboBox.hasFocus();
612: if (!this .comboBox.isEditable() && this .hasFocus) {
613: Rectangle r = this .rectangleForCurrentValue();
614: r.y += 1;
615: r.height -= 2;
616: r.width -= (this .arrowButton.getWidth() + 10);
617: this .paintFocus(g, r);
618: }
619: }
620:
621: /**
622: * Paints the focus indication.
623: *
624: * @param g
625: * Graphics.
626: * @param bounds
627: * Bounds for text.
628: */
629: protected void paintFocus(Graphics g, Rectangle bounds) {
630: int extraPadding = 2 + SubstanceSizeUtils
631: .getExtraPadding(SubstanceSizeUtils
632: .getComponentFontSize(this .comboBox));
633: SubstanceCoreUtilities.paintFocus(g, this .comboBox,
634: this .comboBox, BaseButtonShaper.getBaseOutline(
635: this .arrowButton.getX() - 1 - extraPadding,
636: this .comboBox.getHeight() - 2 * extraPadding,
637: 2, null), bounds, 0.4f, extraPadding);
638: }
639:
640: /**
641: * Returns the popup of the associated combobox.
642: *
643: * @return The popup of the associated combobox.
644: */
645: public ComboPopup getPopup() {
646: return this .popup;
647: }
648:
649: /*
650: * (non-Javadoc)
651: *
652: * @see javax.swing.plaf.ComponentUI#update(java.awt.Graphics,
653: * javax.swing.JComponent)
654: */
655: @Override
656: public void update(Graphics g, JComponent c) {
657: SubstanceCoreUtilities.paintTextCompBackground(g, c);
658: this .paint(g, c);
659: }
660:
661: /*
662: * (non-Javadoc)
663: *
664: * @see javax.swing.plaf.basic.BasicComboBoxUI#configureArrowButton()
665: */
666: @Override
667: public void configureArrowButton() {
668: super .configureArrowButton();
669: // Mustang decided to make the arrow button focusable on
670: // focusable comboboxes
671: this .arrowButton.setFocusable(false);
672:
673: this .substanceFocusListener = new FocusListener() {
674: public void focusGained(FocusEvent e) {
675: arrowButton.setSelected(true);
676: }
677:
678: public void focusLost(FocusEvent e) {
679: arrowButton.setSelected(false);
680: }
681: };
682: this .arrowButton.setSelected(this .comboBox.hasFocus());
683: this .comboBox.addFocusListener(this .substanceFocusListener);
684:
685: this .configureArrowButtonStraightSide();
686: }
687:
688: /**
689: * Configures the straight side of the arrow button.
690: */
691: protected void configureArrowButtonStraightSide() {
692: this .arrowButton
693: .putClientProperty(
694: SubstanceLookAndFeel.BUTTON_SIDE_PROPERTY,
695: this .comboBox.getComponentOrientation()
696: .isLeftToRight() ? Side.LEFT
697: : Side.RIGHT);
698: }
699:
700: /*
701: * (non-Javadoc)
702: *
703: * @see javax.swing.plaf.basic.BasicComboBoxUI#unconfigureArrowButton()
704: */
705: @Override
706: public void unconfigureArrowButton() {
707: this .comboBox.removeFocusListener(this .substanceFocusListener);
708: this .substanceFocusListener = null;
709: super .unconfigureArrowButton();
710: }
711:
712: /*
713: * (non-Javadoc)
714: *
715: * @see javax.swing.plaf.basic.BasicComboBoxUI#configureEditor()
716: */
717: @Override
718: protected void configureEditor() {
719: super .configureEditor();
720: // This for Mustang - setting Substance once again adds a border on
721: // the text field in the combo editor.
722: if (this .editor instanceof JComponent) {
723: Insets ins = SubstanceSizeUtils
724: .getComboTextBorderInsets(SubstanceSizeUtils
725: .getComponentFontSize(this .editor));
726: ((JComponent) this .editor).setBorder(new EmptyBorder(
727: ins.top, ins.left, ins.bottom, ins.right));
728: this .editor.setBackground(this .comboBox.getBackground());
729: // ((JComponent) this.editor).setBorder(new LineBorder(Color.red));
730: }
731: }
732:
733: /*
734: * (non-Javadoc)
735: *
736: * @see javax.swing.plaf.basic.BasicComboBoxUI#createEditor()
737: */
738: @Override
739: protected ComboBoxEditor createEditor() {
740: return new SubstanceComboBoxEditor.UIResource();
741: }
742: }
|