1/* 2 * Copyright (c) 2011, 2015, 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 27package sun.lwawt; 28 29import java.awt.Checkbox; 30import java.awt.CheckboxGroup; 31import java.awt.Component; 32import java.awt.Dimension; 33import java.awt.event.ItemEvent; 34import java.awt.event.ItemListener; 35import java.awt.peer.CheckboxPeer; 36import java.beans.Transient; 37 38import javax.swing.JCheckBox; 39import javax.swing.JComponent; 40import javax.swing.JRadioButton; 41import javax.swing.JToggleButton; 42import 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 */ 49final 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().getCurrentButton().removeItemListener(this); 136 getDelegate().setSelected(state); 137 getDelegate().getCurrentButton().addItemListener(this); 138 } 139 repaintPeer(); 140 } 141 142 @Override 143 public boolean isFocusable() { 144 return true; 145 } 146 147 @SuppressWarnings("serial")// Safe: outer class is non-serializable. 148 final class CheckboxDelegate extends JComponent { 149 150 private final JCheckBox cb; 151 private final JRadioButton rb; 152 153 CheckboxDelegate() { 154 super(); 155 cb = new JCheckBox() { 156 @Override 157 public boolean hasFocus() { 158 return getTarget().hasFocus(); 159 } 160 }; 161 rb = new JRadioButton() { 162 @Override 163 public boolean hasFocus() { 164 return getTarget().hasFocus(); 165 } 166 }; 167 setLayout(null); 168 setRadioButton(false); 169 add(rb); 170 add(cb); 171 } 172 173 @Override 174 public void setEnabled(final boolean enabled) { 175 super.setEnabled(enabled); 176 rb.setEnabled(enabled); 177 cb.setEnabled(enabled); 178 } 179 180 @Override 181 public void setOpaque(final boolean isOpaque) { 182 super.setOpaque(isOpaque); 183 rb.setOpaque(isOpaque); 184 cb.setOpaque(isOpaque); 185 } 186 187 @Override 188 @Deprecated 189 public void reshape(final int x, final int y, final int w, 190 final int h) { 191 super.reshape(x, y, w, h); 192 cb.setBounds(0, 0, w, h); 193 rb.setBounds(0, 0, w, h); 194 } 195 196 @Override 197 public Dimension getPreferredSize() { 198 return getCurrentButton().getPreferredSize(); 199 } 200 201 @Override 202 @Transient 203 public Dimension getMinimumSize() { 204 return getCurrentButton().getMinimumSize(); 205 } 206 207 void setRadioButton(final boolean showRadioButton) { 208 rb.setVisible(showRadioButton); 209 cb.setVisible(!showRadioButton); 210 } 211 212 @Transient 213 JToggleButton getCurrentButton() { 214 return cb.isVisible() ? cb : rb; 215 } 216 217 void setText(final String label) { 218 cb.setText(label); 219 rb.setText(label); 220 } 221 222 void setSelected(final boolean state) { 223 cb.setSelected(state); 224 rb.setSelected(state); 225 } 226 } 227} 228