001: /*
002: * Copyright 1995-2000 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.awt.motif;
027:
028: import java.awt.*;
029: import java.awt.peer.*;
030: import java.awt.event.*;
031:
032: public class MCheckboxPeer extends MComponentPeer implements
033: CheckboxPeer {
034: private boolean inUpCall = false;
035: private boolean inInit = false;
036:
037: native void create(MComponentPeer parent);
038:
039: native void pSetState(boolean state);
040:
041: native boolean pGetState();
042:
043: public native void setLabel(String label);
044:
045: public native void setCheckboxGroup(CheckboxGroup g);
046:
047: void initialize() {
048: Checkbox t = (Checkbox) target;
049: inInit = true;
050:
051: setState(t.getState());
052: setCheckboxGroup(t.getCheckboxGroup());
053: super .initialize();
054: inInit = false;
055: }
056:
057: public MCheckboxPeer(Checkbox target) {
058: super (target);
059: }
060:
061: public boolean isFocusable() {
062: return true;
063: }
064:
065: public void setState(boolean state) {
066: if (inInit) {
067: pSetState(state);
068: } else if (!inUpCall && (state != pGetState())) {
069: pSetState(state);
070: // 4135725 : do not notify on programatic changes
071: // notifyStateChanged(state);
072: }
073: }
074:
075: private native int getIndicatorSize();
076:
077: private native int getSpacing();
078:
079: public Dimension getMinimumSize() {
080: String lbl = ((Checkbox) target).getLabel();
081: if (lbl == null) {
082: lbl = "";
083: }
084: FontMetrics fm = getFontMetrics(target.getFont());
085: /*
086: * Spacing (number of pixels between check mark and label text) is
087: * currently set to 0, but in case it ever changes we have to add
088: * it. 8 is a heuristic number. Indicator size depends on font
089: * height, so we don't need to include it in checkbox's height
090: * calculation.
091: */
092: int wdth = fm.stringWidth(lbl) + getIndicatorSize()
093: + getSpacing() + 8;
094: int hght = Math.max(fm.getHeight() + 8, 15);
095: return new Dimension(wdth, hght);
096: }
097:
098: void notifyStateChanged(boolean state) {
099: Checkbox cb = (Checkbox) target;
100: ItemEvent e = new ItemEvent(cb, ItemEvent.ITEM_STATE_CHANGED,
101: cb.getLabel(), state ? ItemEvent.SELECTED
102: : ItemEvent.DESELECTED);
103: postEvent(e);
104: }
105:
106: // NOTE: This method is called by privileged threads.
107: // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
108: void action(boolean state) {
109: final Checkbox cb = (Checkbox) target;
110: final boolean newState = state;
111: MToolkit.executeOnEventHandlerThread(cb, new Runnable() {
112: public void run() {
113: CheckboxGroup cbg = cb.getCheckboxGroup();
114: /* Bugid 4039594. If this is the current Checkbox in
115: * a CheckboxGroup, then return to prevent deselection.
116: * Otherwise, it's logical state will be turned off,
117: * but it will appear on.
118: */
119: if ((cbg != null) && (cbg.getSelectedCheckbox() == cb)
120: && cb.getState()) {
121: inUpCall = false;
122: cb.setState(true);
123: return;
124: }
125: // All clear - set the new state
126: cb.setState(newState);
127: notifyStateChanged(newState);
128: } // run()
129: });
130: } // action()
131:
132: static final int SIZE = 19;
133: static final int BORDER = 4;
134: static final int SIZ = SIZE - BORDER * 2 - 1;
135:
136: /*
137: * Print the native component by rendering the Motif look ourselves.
138: * ToDo(aim): needs to query native motif for more accurate size and
139: * color information; need to render check mark.
140: */
141: public void print(Graphics g) {
142: Checkbox cb = (Checkbox) target;
143: Dimension d = cb.size();
144: Color bg = cb.getBackground();
145: Color fg = cb.getForeground();
146: Color shadow = bg.darker();
147: int x = BORDER;
148: int y = ((d.height - SIZE) / 2) + BORDER;
149:
150: g.setColor(cb.getState() ? shadow : bg);
151:
152: if (cb.getCheckboxGroup() != null) {
153: g.fillOval(x, y, SIZ, SIZ);
154: draw3DOval(g, bg, x, y, SIZ, SIZ, !(cb.getState()));
155: if (cb.getState()) {
156: g.setColor(fg);
157: g.fillOval(x + 3, y + 3, SIZ - 6, SIZ - 6);
158: }
159: } else {
160: g.fillRect(x, y, SIZ, SIZ);
161: draw3DRect(g, bg, x, y, SIZ, SIZ, !(cb.getState()));
162: if (cb.getState()) {
163: g.setColor(fg);
164: g.drawLine(x + 1, y + 1, x + SIZ - 1, y + SIZ - 1);
165: g.drawLine(x + 1, y + SIZ - 1, x + SIZ - 1, y + 1);
166: }
167: }
168: g.setColor(fg);
169: String lbl = cb.getLabel();
170: if (lbl != null) {
171: // REMIND: align
172: g.setFont(cb.getFont());
173: FontMetrics fm = g.getFontMetrics();
174: g.drawString(lbl, SIZE, (d.height + fm.getMaxAscent() - fm
175: .getMaxDescent()) / 2);
176: }
177:
178: target.print(g);
179: }
180:
181: /**
182: * DEPRECATED
183: */
184: public Dimension minimumSize() {
185: return getMinimumSize();
186: }
187:
188: }
|