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