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<Object> 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, 49 final JComboBox<Object> comboBox, 50 final CellRendererPane rendererPane, 51 final JList<?> list) { 52 super(""); 53 putClientProperty("JButton.buttonType", "comboboxInternal"); 54 55 this.ui = ui; 56 this.comboBox = comboBox; 57 this.rendererPane = rendererPane; 58 this.list = list; 59 60 setModel(new DefaultButtonModel() { 61 public void setArmed(final boolean armed) { 62 super.setArmed(isPressed() ? true : armed); 63 } 64 }); 65 66 setEnabled(comboBox.isEnabled()); 67 } 68 69 public boolean isEnabled() { 70 return comboBox == null ? true : comboBox.isEnabled(); 71 } 72 73 @SuppressWarnings("deprecation") 74 public boolean isFocusTraversable() { 75 return false; 76 } 77 78 protected void setIsPopDown(final boolean isPopDown) { 79 this.isPopDown = isPopDown; 80 repaint(); 81 } 82 83 protected void setIsSquare(final boolean isSquare) { 84 this.isSquare = isSquare; 85 repaint(); 86 } 87 88 protected State getState(final ButtonModel buttonModel) { 89 if (!comboBox.isEnabled()) return State.DISABLED; 90 if (!AquaFocusHandler.isActive(comboBox)) return State.INACTIVE; 91 if (buttonModel.isArmed()) return State.PRESSED; 92 return State.ACTIVE; 93 } 94 95 public void paintComponent(final Graphics g) { 96 // Don't Paint the button as usual 97 // super.paintComponent( g ); 98 final boolean editable = comboBox.isEditable(); 99 100 int top = 0; 101 int left = 0; 102 int width = getWidth(); 103 int height = getHeight(); 104 105 if (comboBox.isOpaque()) { 106 g.setColor(getBackground()); 107 g.fillRect(0, 0, width, height); 108 } 109 110 final Size size = AquaUtilControlSize.getUserSizeFrom(comboBox); 111 painter.state.set(size == null ? Size.REGULAR : size); 112 113 final ButtonModel buttonModel = getModel(); 114 painter.state.set(getState(buttonModel)); 115 116 painter.state.set(AlignmentVertical.CENTER); 117 118 if (AquaComboBoxUI.isTableCellEditor(comboBox)) { 119 painter.state.set(AlignmentHorizontal.RIGHT); 120 painter.state.set(Widget.BUTTON_POP_UP); 121 painter.state.set(ArrowsOnly.YES); 122 painter.paint(g, this, left, top, width, height); 123 doRendererPaint(g, buttonModel, editable, getInsets(), left, top, width, height); 124 return; 125 } 126 127 painter.state.set(AlignmentHorizontal.CENTER); 128 final Insets insets = getInsets(); 129 if (!editable) { 130 top += insets.top; 131 left += insets.left; 132 width -= insets.left + insets.right; 133 height -= insets.top + insets.bottom; 134 } 135 136 if (height <= 0 || width <= 0) { 137 return; 138 } 139 140 boolean hasFocus = comboBox.hasFocus(); 141 if (editable) { 142 painter.state.set(Widget.BUTTON_COMBO_BOX); 143 painter.state.set(IndicatorOnly.YES); 144 painter.state.set(AlignmentHorizontal.LEFT); 145 hasFocus |= comboBox.getEditor().getEditorComponent().hasFocus(); 146 } else { 147 painter.state.set(IndicatorOnly.NO); 148 painter.state.set(AlignmentHorizontal.CENTER); 149 if (isPopDown) { 150 painter.state.set(isSquare ? Widget.BUTTON_POP_DOWN_SQUARE : Widget.BUTTON_POP_DOWN); 151 } else { 152 painter.state.set(isSquare ? Widget.BUTTON_POP_UP_SQUARE : Widget.BUTTON_POP_UP); 153 } 154 } 155 painter.state.set(hasFocus ? Focused.YES : Focused.NO); 156 157 if (isSquare) { 158 painter.paint(g, comboBox, left + 2, top - 1, width - 4, height); 159 } else { 160 painter.paint(g, comboBox, left, top, width, height); 161 } 162 163 // Let the renderer paint 164 if (!editable && comboBox != null) { 165 doRendererPaint(g, buttonModel, editable, insets, left, top, width, height); 166 } 167 } 168 169 protected void doRendererPaint(final Graphics g, final ButtonModel buttonModel, final boolean editable, final Insets insets, int left, int top, int width, int height) { 170 final ListCellRenderer<Object> renderer = comboBox.getRenderer(); 171 172 // fake it out! not renderPressed 173 final Component c = renderer.getListCellRendererComponent(list, comboBox.getSelectedItem(), -1, false, false); 174 // System.err.println("Renderer: " + renderer); 175 176 if (!editable && !AquaComboBoxUI.isTableCellEditor(comboBox)) { 177 final int indentLeft = 10; 178 final int buttonWidth = 24; 179 180 // hardcoded for now. We should adjust as necessary. 181 top += 1; 182 height -= 4; 183 left += indentLeft; 184 width -= (indentLeft + buttonWidth); 185 } 186 187 c.setFont(rendererPane.getFont()); 188 189 if (buttonModel.isArmed() && buttonModel.isPressed()) { 190 if (isOpaque()) { 191 c.setBackground(UIManager.getColor("Button.select")); 192 } 193 c.setForeground(comboBox.getForeground()); 194 } else if (!comboBox.isEnabled()) { 195 if (isOpaque()) { 196 c.setBackground(UIManager.getColor("ComboBox.disabledBackground")); 197 } 198 c.setForeground(UIManager.getColor("ComboBox.disabledForeground")); 199 } else { 200 c.setForeground(comboBox.getForeground()); 201 c.setBackground(comboBox.getBackground()); 202 } 203 204 // Sun Fix for 4238829: should lay out the JPanel. 205 boolean shouldValidate = false; 206 if (c instanceof JPanel) { 207 shouldValidate = true; 208 } 209 210 final int iconWidth = 0; 211 final int cWidth = width - (insets.right + iconWidth); 212 213 // fix for 3156483 we need to crop images that are too big. 214 // if (height > 18) 215 // always crop. 216 { 217 top = height / 2 - 8; 218 height = 19; 219 } 220 221 // It doesn't need to draw its background, we handled it 222 final Color bg = c.getBackground(); 223 final boolean inhibitBackground = bg instanceof UIResource; 224 if (inhibitBackground) c.setBackground(new Color(0, 0, 0, 0)); 225 226 rendererPane.paintComponent(g, c, this, left, top, cWidth, height, shouldValidate); // h - (insets.top + insets.bottom) ); 227 228 if (inhibitBackground) c.setBackground(bg); 229 } 230 }