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