1 /* 2 * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.apple.laf; 27 28 import java.awt.*; 29 30 import javax.swing.*; 31 import javax.swing.plaf.UIResource; 32 33 import apple.laf.JRSUIState; 34 import apple.laf.JRSUIConstants.*; 35 36 @SuppressWarnings("serial") // Superclass is not serializable across versions 37 class AquaComboBoxButton extends JButton { 38 final protected JComboBox comboBox; 39 final protected JList list; 40 final protected CellRendererPane rendererPane; 41 final protected AquaComboBoxUI ui; 42 43 protected final AquaPainter<JRSUIState> painter = AquaPainter.create(JRSUIState.getInstance()); 44 boolean isPopDown; 45 boolean isSquare; 46 47 @SuppressWarnings("serial") // anonymous class 48 protected AquaComboBoxButton(final AquaComboBoxUI ui, final JComboBox comboBox, final CellRendererPane rendererPane, final JList list) { 49 super(""); 50 putClientProperty("JButton.buttonType", "comboboxInternal"); 51 52 this.ui = ui; 53 this.comboBox = comboBox; 54 this.rendererPane = rendererPane; 55 this.list = list; 56 57 setModel(new DefaultButtonModel() { 58 public void setArmed(final boolean armed) { 59 super.setArmed(isPressed() ? true : armed); 60 } 61 }); 62 63 setEnabled(comboBox.isEnabled()); 64 } 65 66 public boolean isEnabled() { 67 return comboBox == null ? true : comboBox.isEnabled(); 68 } 69 70 public boolean isFocusTraversable() { 71 return false; 72 } 73 74 protected void setIsPopDown(final boolean isPopDown) { 75 this.isPopDown = isPopDown; 76 repaint(); 77 } 78 79 protected void setIsSquare(final boolean isSquare) { 80 this.isSquare = isSquare; 81 repaint(); 82 } 83 84 protected State getState(final ButtonModel buttonModel) { 85 if (!comboBox.isEnabled()) return State.DISABLED; 86 if (!AquaFocusHandler.isActive(comboBox)) return State.INACTIVE; 87 if (buttonModel.isArmed()) return State.PRESSED; 88 return State.ACTIVE; 89 } 90 91 public void paintComponent(final Graphics g) { 92 // Don't Paint the button as usual 93 // super.paintComponent( g ); 94 final boolean editable = comboBox.isEditable(); 95 96 int top = 0; 97 int left = 0; 98 int width = getWidth(); 99 int height = getHeight(); 100 101 if (comboBox.isOpaque()) { 102 g.setColor(getBackground()); 103 g.fillRect(0, 0, width, height); 104 } 105 106 final Size size = AquaUtilControlSize.getUserSizeFrom(comboBox); 107 painter.state.set(size == null ? Size.REGULAR : size); 108 109 final ButtonModel buttonModel = getModel(); 110 painter.state.set(getState(buttonModel)); 111 112 painter.state.set(AlignmentVertical.CENTER); 113 114 if (AquaComboBoxUI.isTableCellEditor(comboBox)) { 115 painter.state.set(AlignmentHorizontal.RIGHT); 116 painter.state.set(Widget.BUTTON_POP_UP); 117 painter.state.set(ArrowsOnly.YES); 118 painter.paint(g, this, left, top, width, height); 119 doRendererPaint(g, buttonModel, editable, getInsets(), left, top, width, height); 120 return; 121 } 122 123 painter.state.set(AlignmentHorizontal.CENTER); 124 final Insets insets = getInsets(); 125 if (!editable) { 126 top += insets.top; 127 left += insets.left; 128 width -= insets.left + insets.right; 129 height -= insets.top + insets.bottom; 130 } 131 132 if (height <= 0 || width <= 0) { 133 return; 134 } 135 136 boolean hasFocus = comboBox.hasFocus(); 137 if (editable) { 138 painter.state.set(Widget.BUTTON_COMBO_BOX); 139 painter.state.set(IndicatorOnly.YES); 140 painter.state.set(AlignmentHorizontal.LEFT); 141 hasFocus |= comboBox.getEditor().getEditorComponent().hasFocus(); 142 } else { 143 painter.state.set(IndicatorOnly.NO); 144 painter.state.set(AlignmentHorizontal.CENTER); 145 if (isPopDown) { 146 painter.state.set(isSquare ? Widget.BUTTON_POP_DOWN_SQUARE : Widget.BUTTON_POP_DOWN); 147 } else { 148 painter.state.set(isSquare ? Widget.BUTTON_POP_UP_SQUARE : Widget.BUTTON_POP_UP); 149 } 150 } 151 painter.state.set(hasFocus ? Focused.YES : Focused.NO); 152 153 if (isSquare) { 154 painter.paint(g, comboBox, left + 2, top - 1, width - 4, height); 155 } else { 156 painter.paint(g, comboBox, left, top, width, height); 157 } 158 159 // Let the renderer paint 160 if (!editable && comboBox != null) { 161 doRendererPaint(g, buttonModel, editable, insets, left, top, width, height); 162 } 163 } 164 165 protected void doRendererPaint(final Graphics g, final ButtonModel buttonModel, final boolean editable, final Insets insets, int left, int top, int width, int height) { 166 final ListCellRenderer renderer = comboBox.getRenderer(); 167 168 // fake it out! not renderPressed 169 final Component c = renderer.getListCellRendererComponent(list, comboBox.getSelectedItem(), -1, false, false); 170 // System.err.println("Renderer: " + renderer); 171 172 if (!editable && !AquaComboBoxUI.isTableCellEditor(comboBox)) { 173 final int indentLeft = 10; 174 final int buttonWidth = 24; 175 176 // hardcoded for now. We should adjust as necessary. 177 top += 1; 178 height -= 4; 179 left += indentLeft; 180 width -= (indentLeft + buttonWidth); 181 } 182 183 c.setFont(rendererPane.getFont()); 184 185 if (buttonModel.isArmed() && buttonModel.isPressed()) { 186 if (isOpaque()) { 187 c.setBackground(UIManager.getColor("Button.select")); 188 } 189 c.setForeground(comboBox.getForeground()); 190 } else if (!comboBox.isEnabled()) { 191 if (isOpaque()) { 192 c.setBackground(UIManager.getColor("ComboBox.disabledBackground")); 193 } 194 c.setForeground(UIManager.getColor("ComboBox.disabledForeground")); 195 } else { 196 c.setForeground(comboBox.getForeground()); 197 c.setBackground(comboBox.getBackground()); 198 } 199 200 // Sun Fix for 4238829: should lay out the JPanel. 201 boolean shouldValidate = false; 202 if (c instanceof JPanel) { 203 shouldValidate = true; 204 } 205 206 final int iconWidth = 0; 207 final int cWidth = width - (insets.right + iconWidth); 208 209 // fix for 3156483 we need to crop images that are too big. 210 // if (height > 18) 211 // always crop. 212 { 213 top = height / 2 - 8; 214 height = 19; 215 } 216 217 // It doesn't need to draw its background, we handled it 218 final Color bg = c.getBackground(); 219 final boolean inhibitBackground = bg instanceof UIResource; 220 if (inhibitBackground) c.setBackground(new Color(0, 0, 0, 0)); 221 222 rendererPane.paintComponent(g, c, this, left, top, cWidth, height, shouldValidate); // h - (insets.top + insets.bottom) ); 223 224 if (inhibitBackground) c.setBackground(bg); 225 } 226 }