1 /* 2 * Copyright (c) 2011, 2013, 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 27 package sun.lwawt; 28 29 import java.awt.Checkbox; 30 import java.awt.CheckboxGroup; 31 import java.awt.Component; 32 import java.awt.Dimension; 33 import java.awt.event.ItemEvent; 34 import java.awt.event.ItemListener; 35 import java.awt.peer.CheckboxPeer; 36 import java.beans.Transient; 37 38 import javax.swing.JCheckBox; 39 import javax.swing.JComponent; 40 import javax.swing.JRadioButton; 41 import javax.swing.JToggleButton; 42 import javax.swing.SwingUtilities; 43 44 /** 45 * Lightweight implementation of {@link CheckboxPeer}. Delegates most of the 46 * work to the {@link JCheckBox} and {@link JRadioButton}, which are placed 47 * inside an empty {@link JComponent}. 48 */ 49 final class LWCheckboxPeer 50 extends LWComponentPeer<Checkbox, LWCheckboxPeer.CheckboxDelegate> 51 implements CheckboxPeer, ItemListener { 52 53 LWCheckboxPeer(final Checkbox target, 54 final PlatformComponent platformComponent) { 55 super(target, platformComponent); 56 } 57 58 @Override 59 CheckboxDelegate createDelegate() { 60 return new CheckboxDelegate(); 61 } 62 63 @Override 64 Component getDelegateFocusOwner() { 65 return getDelegate().getCurrentButton(); 66 } 67 68 @Override 69 void initializeImpl() { 70 super.initializeImpl(); 71 setLabel(getTarget().getLabel()); 72 setState(getTarget().getState()); 73 setCheckboxGroup(getTarget().getCheckboxGroup()); 74 } 75 76 @Override 77 public void itemStateChanged(final ItemEvent e) { 78 // group.setSelectedCheckbox() will repaint the component 79 // to let LWCheckboxPeer correctly handle it we should call it 80 // after the current event is processed 81 SwingUtilities.invokeLater(new Runnable() { 82 @Override 83 public void run() { 84 boolean postEvent = true; 85 final CheckboxGroup group = getTarget().getCheckboxGroup(); 86 if (group != null) { 87 if (e.getStateChange() == ItemEvent.SELECTED) { 88 if (group.getSelectedCheckbox() != getTarget()) { 89 group.setSelectedCheckbox(getTarget()); 90 } else { 91 postEvent = false; 92 } 93 } else { 94 postEvent = false; 95 if (group.getSelectedCheckbox() == getTarget()) { 96 // Don't want to leave the group with no selected 97 // checkbox. 98 getTarget().setState(true); 99 } 100 } 101 } else { 102 getTarget().setState(e.getStateChange() 103 == ItemEvent.SELECTED); 104 } 105 if (postEvent) { 106 postEvent(new ItemEvent(getTarget(), 107 ItemEvent.ITEM_STATE_CHANGED, 108 getTarget().getLabel(), 109 e.getStateChange())); 110 } 111 } 112 }); 113 } 114 115 @Override 116 public void setCheckboxGroup(final CheckboxGroup g) { 117 synchronized (getDelegateLock()) { 118 getDelegate().getCurrentButton().removeItemListener(this); 119 getDelegate().setRadioButton(g != null); 120 getDelegate().getCurrentButton().addItemListener(this); 121 } 122 repaintPeer(); 123 } 124 125 @Override 126 public void setLabel(final String label) { 127 synchronized (getDelegateLock()) { 128 getDelegate().setText(label); 129 } 130 } 131 132 @Override 133 public void setState(final boolean state) { 134 synchronized (getDelegateLock()) { 135 getDelegate().setSelected(state); 136 } 137 repaintPeer(); 138 } 139 140 @Override 141 public boolean isFocusable() { 142 return true; 143 } 144 145 @SuppressWarnings("serial")// Safe: outer class is non-serializable. 146 final class CheckboxDelegate extends JComponent { 147 148 private final JCheckBox cb; 149 private final JRadioButton rb; 150 151 CheckboxDelegate() { 152 super(); 153 cb = new JCheckBox() { 154 @Override 155 public boolean hasFocus() { 156 return getTarget().hasFocus(); 157 } 158 }; 159 rb = new JRadioButton() { 160 @Override 161 public boolean hasFocus() { 162 return getTarget().hasFocus(); 163 } 164 }; 165 setLayout(null); 166 setRadioButton(false); 167 add(rb); 168 add(cb); 169 } 170 171 @Override 172 public void setEnabled(final boolean enabled) { 173 super.setEnabled(enabled); 174 rb.setEnabled(enabled); 175 cb.setEnabled(enabled); 176 } 177 178 @Override 179 public void setOpaque(final boolean isOpaque) { 180 super.setOpaque(isOpaque); 181 rb.setOpaque(isOpaque); 182 cb.setOpaque(isOpaque); 183 } 184 185 @Override 186 @Deprecated 187 public void reshape(final int x, final int y, final int w, 188 final int h) { 189 super.reshape(x, y, w, h); 190 cb.setBounds(0, 0, w, h); 191 rb.setBounds(0, 0, w, h); 192 } 193 194 @Override 195 public Dimension getPreferredSize() { 196 return getCurrentButton().getPreferredSize(); 197 } 198 199 @Override 200 @Transient 201 public Dimension getMinimumSize() { 202 return getCurrentButton().getMinimumSize(); 203 } 204 205 void setRadioButton(final boolean showRadioButton) { 206 rb.setVisible(showRadioButton); 207 cb.setVisible(!showRadioButton); 208 } 209 210 @Transient 211 JToggleButton getCurrentButton() { 212 return cb.isVisible() ? cb : rb; 213 } 214 215 void setText(final String label) { 216 cb.setText(label); 217 rb.setText(label); 218 } 219 220 void setSelected(final boolean state) { 221 cb.setSelected(state); 222 rb.setSelected(state); 223 } 224 } 225 }