Frames | No Frames |
1: /* GtkCheckboxPeer.java -- Implements CheckboxPeer with GTK 2: Copyright (C) 1998, 1999, 2002, 2003, 2006 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package gnu.java.awt.peer.gtk; 40: 41: import java.awt.Checkbox; 42: import java.awt.CheckboxGroup; 43: import java.awt.event.ItemEvent; 44: import java.awt.peer.CheckboxPeer; 45: import java.util.WeakHashMap; 46: 47: /** 48: * This class wraps either a GtkCheckButton or a GtkOptionButton 49: * depending on if this peer's owner belongs to a CheckboxGroup. 50: */ 51: public class GtkCheckboxPeer extends GtkComponentPeer 52: implements CheckboxPeer 53: { 54: // The CheckboxGroup to which this GtkCheckboxPeer's owner belongs. 55: public CheckboxGroup current_group; 56: // The current state of the GTK checkbox. 57: private boolean currentState; 58: 59: // A map from CheckboxGroup to GSList* GTK option group pointer. 60: private static WeakHashMap groupMap = new WeakHashMap(); 61: 62: public native void createCheckButton (); 63: public native void createRadioButton (long groupPointer); 64: 65: public native void addToGroup (long groupPointer); 66: public native void removeFromGroup (); 67: public native void switchToGroup (long groupPointer); 68: 69: public native void connectSignals (); 70: 71: /** 72: * Overridden to set Font of label inside button. 73: */ 74: protected native void gtkWidgetModifyFont(String name, int style, int size); 75: native void gtkButtonSetLabel (String label); 76: native void gtkToggleButtonSetActive (boolean is_active); 77: 78: public GtkCheckboxPeer (Checkbox c) 79: { 80: super (c); 81: } 82: 83: public void create () 84: { 85: Checkbox checkbox = (Checkbox) awtComponent; 86: current_group = checkbox.getCheckboxGroup (); 87: if (current_group == null) 88: { 89: // Initially we're not part of a group so we're backed by a 90: // GtkCheckButton. 91: createCheckButton(); 92: } 93: else 94: { 95: // Initially we're part of a group. 96: 97: // See if this group is already stored in our map. 98: Long groupPointer = null; 99: synchronized (groupMap) 100: { 101: groupPointer = (Long) groupMap.get(current_group); 102: } 103: 104: if (groupPointer == null) 105: { 106: // We don't know about this group. Create a new native 107: // group pointer for this group and store it in our map. 108: createRadioButton(0); 109: } 110: else 111: { 112: // We already know about this group. Pass the 113: // corresponding native group pointer value to the native 114: // create method. 115: createRadioButton(groupPointer.longValue()); 116: } 117: } 118: currentState = checkbox.getState(); 119: gtkToggleButtonSetActive(currentState); 120: 121: String label = checkbox.getLabel(); 122: if (label != null) 123: gtkButtonSetLabel(label); 124: } 125: 126: /** 127: * Sets native GtkCheckButton is state is different from current 128: * state. Will set currentState to state to prevent posting an 129: * event since events should only be posted for user initiated 130: * clicks on the GtkCheckButton. 131: */ 132: public synchronized void setState (boolean state) 133: { 134: if (currentState != state) 135: { 136: currentState = state; 137: gtkToggleButtonSetActive(state); 138: } 139: } 140: 141: public void setLabel (String label) 142: { 143: gtkButtonSetLabel (label); 144: } 145: 146: public void setCheckboxGroup (CheckboxGroup group) 147: { 148: if (current_group == null && group != null) 149: { 150: // This peer's owner is currently not in a group, and now 151: // we're adding it to a group. This means that the backing 152: // GtkWidget will change from a GtkCheckButton to a 153: // GtkRadioButton. 154: 155: current_group = group; 156: 157: // See if the new group is already stored in our map. 158: Long groupPointer = null; 159: synchronized (groupMap) 160: { 161: groupPointer = (Long) groupMap.get(current_group); 162: } 163: 164: if (groupPointer == null) 165: { 166: // We don't know about this group. Create a new native 167: // group pointer for this group and store it in our map. 168: addToGroup(0); 169: } 170: else 171: { 172: // We already know about this group. Pass the 173: // corresponding native group pointer value to the native 174: // create method. 175: addToGroup(groupPointer.longValue()); 176: } 177: } 178: else if (current_group != null && group == null) 179: { 180: // This peer's owner is currently in a group, and now we're 181: // removing it from a group. This means that the backing 182: // GtkWidget will change from a GtkRadioButton to a 183: // GtkCheckButton. 184: removeFromGroup(); 185: current_group = null; 186: } 187: else if (current_group == null && group == null) 188: { 189: // This peer's owner is currently not in a group, and we're 190: // not adding it to a group, so simply return. 191: return; 192: } 193: else if (current_group != group) 194: { 195: // This peer's owner is currently in a group, and now we're 196: // putting it in another group. This means that we must 197: // remove the backing GtkRadioButton from one group and add it 198: // to the other group. 199: 200: current_group = group; 201: 202: // See if the new group is already stored in our map. 203: Long groupPointer = null; 204: synchronized (groupMap) 205: { 206: groupPointer = (Long) groupMap.get(current_group); 207: } 208: 209: if (groupPointer == null) 210: { 211: // We don't know about this group. Create a new native 212: // group pointer for this group and store it in our map. 213: switchToGroup(0); 214: } 215: else 216: { 217: // We already know about this group. Pass the 218: // corresponding native group pointer value to the native 219: // create method. 220: switchToGroup(groupPointer.longValue()); 221: } 222: } 223: } 224: 225: // Override the superclass postItemEvent so that the peer doesn't 226: // need information that we have. 227: // called back by native side: item_toggled_cb 228: public synchronized void postItemEvent(Object item, boolean state) 229: { 230: // Only fire event is state actually changed. 231: if (currentState != state) 232: { 233: currentState = state; 234: super.postItemEvent(awtComponent, 235: state ? ItemEvent.SELECTED : ItemEvent.DESELECTED); 236: } 237: } 238: 239: public void addToGroupMap(long groupPointer) 240: { 241: synchronized (groupMap) 242: { 243: groupMap.put(current_group, new Long (groupPointer)); 244: } 245: } 246: 247: public void dispose () 248: { 249: groupMap.clear(); 250: current_group = null; 251: currentState = false; 252: super.dispose (); 253: } 254: }