001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.form.editors2;
043:
044: import java.awt.*;
045: import java.awt.event.*;
046: import java.beans.*;
047: import java.io.IOException;
048: import java.util.ResourceBundle;
049: import javax.swing.*;
050: import javax.swing.border.Border;
051: import javax.swing.event.ChangeEvent;
052: import javax.swing.event.ChangeListener;
053: import org.w3c.dom.Document;
054: import org.w3c.dom.Node;
055:
056: import org.jdesktop.layout.GroupLayout;
057: import org.jdesktop.layout.LayoutStyle;
058:
059: import org.openide.awt.Mnemonics;
060: import org.openide.explorer.propertysheet.editors.XMLPropertyEditor;
061: import org.openide.explorer.propertysheet.PropertyEnv;
062: import org.openide.util.NbBundle;
063:
064: import org.netbeans.modules.form.*;
065: import org.netbeans.modules.form.codestructure.CodeVariable;
066:
067: /**
068: * Font property editor that wraps a default property editor for fonts plus it
069: * adds the ability to specify relative changes to the font.
070: * As ResourceWrapperEditor subclass it also allows to wrap the font in a
071: * ResourceValue (store as a resource). This "resource wrapping" is only used
072: * for absolute fonts (relative changes can't be resources).
073: *
074: * @author Jan Stola, Tomas Pavek
075: */
076: public class FontEditor extends ResourceWrapperEditor implements
077: XMLPropertyEditor {
078:
079: public FontEditor() {
080: super (PropertyEditorManager.findEditor(Font.class));
081: }
082:
083: @Override
084: public PropertyEditor getDelegatedPropertyEditor() {
085: // hack for saving: this is not only a wrapper of FontEditor for
086: // absolute fonts, but also a complete property editor for relative
087: // fonts - in which case it returns itself as the property editor
088: // responsible for saving
089: Object value = getValue();
090: if (!(value instanceof NbFont))
091: return super .getDelegatedPropertyEditor();
092: else
093: return this ;
094: }
095:
096: @Override
097: public void updateFormVersionLevel() {
098: if (getValue() instanceof NbFont) {
099: formModel.raiseVersionLevel(FormModel.FormVersion.NB60_PRE,
100: FormModel.FormVersion.NB60);
101: } else {
102: super .updateFormVersionLevel();
103: }
104: }
105:
106: @Override
107: public void attachEnv(PropertyEnv env) {
108: super .attachEnv(env);
109: FeatureDescriptor prop = env.getFeatureDescriptor();
110: if (prop != null) {
111: prop.setValue("canEditAsText", Boolean.FALSE); // NOI18N
112: }
113: }
114:
115: @Override
116: public Object getUnwrappedValue() {
117: // NbFont can't be stored in the delegate FontEditor, so we can't use
118: // delegateEditor.getValue() to get the unwrapped value
119: Object value = getValue();
120: return value instanceof ResourceValue ? ((ResourceValue) value)
121: .getDesignValue() : value;
122: }
123:
124: @Override
125: protected void setValueToDelegate(Object value) {
126: if (value instanceof ResourceValue)
127: value = ((ResourceValue) value).getValue();
128: if (value instanceof NbFont)
129: value = ((NbFont) value).getDesignValue();
130: delegateEditor.setValue(value);
131: }
132:
133: @Override
134: public String getJavaInitializationString() {
135: String exp;
136: Object value = getValue();
137: if (value instanceof NbFont) {
138: NbFont propertyValue = (NbFont) value;
139: RADProperty property = (RADProperty) this .property;
140: RADComponent comp = property.getRADComponent();
141: CodeVariable var = comp.getCodeExpression().getVariable();
142: String varName = (var == null) ? null : var.getName();
143: String readMethod = property.getPropertyDescriptor()
144: .getReadMethod().getName();
145: String getter = readMethod + "()"; // NOI18N
146: if (varName != null) {
147: getter = varName + '.' + getter;
148: }
149: exp = getter + ".deriveFont("; // NOI18N
150: boolean styleChanged = (propertyValue.italic != null)
151: || (propertyValue.bold != null);
152: if (styleChanged) {
153: String styleExp = null;
154: if (propertyValue.italic != null) {
155: styleExp = getter + ".getStyle()"; // NOI18N
156: if (Boolean.TRUE.equals(propertyValue.italic)) {
157: styleExp += " | "; // NOI18N
158: } else {
159: styleExp += " & ~"; // NOI18N
160: }
161: styleExp += "java.awt.Font.ITALIC"; // NOI18N
162: }
163: if (styleExp == null) {
164: styleExp = getter + ".getStyle()"; // NOI18N
165: } else {
166: styleExp = "(" + styleExp + ")"; // NOI18N
167: }
168: if (propertyValue.bold != null) {
169: if (Boolean.TRUE.equals(propertyValue.bold)) {
170: styleExp += " | "; // NOI18N
171: } else {
172: styleExp += " & ~"; // NOI18N
173: }
174: styleExp += "java.awt.Font.BOLD"; // NOI18N
175: }
176: exp += styleExp;
177: }
178: if (propertyValue.absoluteSize) {
179: exp += styleChanged ? ", " : "(float)"; // NOI18N
180: exp += propertyValue.size + ")"; // NOI18N
181: } else {
182: if (propertyValue.size == 0) {
183: if (styleChanged) {
184: exp += ')';
185: } else {
186: exp = getter;
187: }
188: } else {
189: if (styleChanged) {
190: exp += ", "; // NOI18N
191: }
192: exp += getter + ".getSize()"; // NOI18N
193: if (propertyValue.size > 0) {
194: exp += '+';
195: }
196: exp += propertyValue.size;
197: if (!styleChanged)
198: exp += "f"; // NOI18N
199: exp += ")"; // NOI18N
200: }
201: }
202: } else if (value instanceof Font) {
203: // plain font - let the default editor handle the code
204: // add NOI18N comment - font name is a string
205: exp = "*/\n\\1NOI18N*/\n\\0"
206: + delegateEditor.getJavaInitializationString(); // NOI18N
207: // */\n\\1 is a special code mark for line comment
208: // */\n\\0 is a special code mark to indicate that a real code follows
209: } else { // neither NbFont nor Font - let ResourceWrapperEditor handle it
210: exp = super .getJavaInitializationString();
211: }
212: return exp;
213: }
214:
215: @Override
216: public String getAsText() {
217: Object value = getValue();
218: return value instanceof NbFont ? ((NbFont) value)
219: .getDescription() : super .getAsText();
220: }
221:
222: @Override
223: protected Component createCustomEditorGUI(
224: final Component resourcePanelGUI) {
225: Object value = getUnwrappedValue();
226: boolean absolute = !(value instanceof NbFont);
227:
228: final Component absoluteComp = absolute ? createAbsolutePanel(resourcePanelGUI)
229: : null;
230: final JCheckBox switchBox = new JCheckBox();
231: switchBox.setVisible(this .property instanceof RADProperty);
232: Mnemonics.setLocalizedText(switchBox, NbBundle.getMessage(
233: FontEditor.class, "CTL_DeriveFont")); // NOI18N
234: switchBox.setSelected(!absolute);
235: final RelativeFontPanel relativeComp = new RelativeFontPanel();
236: Component pane = absolute ? absoluteComp : relativeComp;
237: if (!absolute)
238: relativeComp.updateFromPropertyValue();
239:
240: final JPanel editor = new JPanel();
241: final GroupLayout layout = new GroupLayout(editor);
242: editor.setLayout(layout);
243: layout.setHorizontalGroup(layout.createParallelGroup().add(
244: layout.createSequentialGroup().addContainerGap().add(
245: switchBox)).add(pane));
246: layout.setVerticalGroup(layout.createSequentialGroup()
247: .addContainerGap().add(switchBox).addPreferredGap(
248: LayoutStyle.RELATED).add(pane));
249: // .addContainerGap());
250:
251: switchBox.addItemListener(new ItemListener() {
252: private Component absoluteInLayout = absoluteComp;
253:
254: public void itemStateChanged(ItemEvent e) {
255: if (switchBox.isSelected()) {
256: layout.replace(absoluteInLayout, relativeComp);
257: convertToRelative();
258: relativeComp.updateFromPropertyValue();
259: } else {
260: absoluteInLayout = createAbsolutePanel(resourcePanelGUI);
261: layout.replace(relativeComp, absoluteInLayout);
262: convertToAbsolute();
263: }
264: editor.revalidate();
265: editor.repaint();
266: }
267: });
268:
269: return editor;
270: }
271:
272: private Component createAbsolutePanel(Component resourcePanelGUI) {
273: Component fontEditor = delegateEditor.getCustomEditor();
274: if (resourcePanelGUI == null)
275: return fontEditor;
276:
277: JPanel panel = new JPanel();
278: GroupLayout layout = new GroupLayout(panel);
279:
280: layout.setAutocreateGaps(true);
281: panel.setLayout(layout);
282: layout.setHorizontalGroup(layout.createParallelGroup().add(
283: fontEditor).add(resourcePanelGUI));
284: layout.setVerticalGroup(layout.createSequentialGroup().add(
285: fontEditor).add(resourcePanelGUI));
286: return panel;
287: }
288:
289: private void convertToRelative() {
290: Object value = getUnwrappedValue();
291: if (!(value instanceof Font)) {
292: return;
293: }
294: Font font = (Font) value;
295: NbFont propertyValue = new NbFont();
296: propertyValue.property = property;
297:
298: Font defaultFont = (Font) property.getDefaultValue();
299: if (propertyValue.absoluteSize) {
300: propertyValue.size = font.getSize();
301: } else {
302: if (defaultFont == null)
303: return;
304: propertyValue.size = font.getSize() - defaultFont.getSize();
305: }
306: if (defaultFont == null)
307: return;
308: int absoluteStyle = font.getStyle();
309: int defaultStyle = defaultFont.getStyle();
310: boolean aItalic = ((absoluteStyle & Font.ITALIC) != 0);
311: boolean dItalic = ((defaultStyle & Font.ITALIC) != 0);
312: if (aItalic && !dItalic) {
313: propertyValue.italic = Boolean.TRUE;
314: }
315: if (!aItalic && dItalic) {
316: propertyValue.italic = Boolean.FALSE;
317: }
318: if ((propertyValue.italic != null) && (aItalic == dItalic)
319: && (aItalic != propertyValue.italic.booleanValue())) {
320: propertyValue.italic = null;
321: }
322: boolean aBold = ((absoluteStyle & Font.BOLD) != 0);
323: boolean dBold = ((defaultStyle & Font.BOLD) != 0);
324: if (aBold && !dBold) {
325: propertyValue.bold = Boolean.TRUE;
326: }
327: if (!aBold && dBold) {
328: propertyValue.bold = Boolean.FALSE;
329: }
330: if ((propertyValue.bold != null) && (aBold == dBold)
331: && (aBold != propertyValue.bold.booleanValue())) {
332: propertyValue.bold = null;
333: }
334: setValue(propertyValue);
335: }
336:
337: private void convertToAbsolute() {
338: Object value = getUnwrappedValue();
339: if (value instanceof NbFont) {
340: setValue(((NbFont) value).getDesignValue());
341: }
342: }
343:
344: // XMLPropertyEditor implementation
345: /** Root of the XML representation of the font. */
346: public static final String XML_FONT_ROOT = "FontInfo"; // NOI18N
347: /** Element with information about the font. */
348: public static final String XML_FONT = "Font"; // NOI18N
349: /** Determines whether the font is relative. */
350: public static final String ATTR_RELATIVE = "relative"; // NOI18N
351: /** Determines whether the font size is relative to the default value. */
352: public static final String ATTR_RELATIVE_SIZE = "relativeSize"; // NOI18N
353: /** Attribute for the font size. */
354: public static final String ATTR_SIZE = "size"; // NOI18N
355: /** Attribute for the change of italic. */
356: public static final String ATTR_ITALIC_CHANGE = "italic"; // NOI18N
357: /** Attribute for the change of thickness. */
358: public static final String ATTR_BOLD_CHANGE = "bold"; // NOI18N
359: /** Name of the component this value belongs to. */
360: public static final String ATTR_COMP_NAME = "component"; // NOI18N
361: /** Name of the property this value belongs to. */
362: public static final String ATTR_PROP_NAME = "property"; // NOI18N
363:
364: public void readFromXML(Node element) throws IOException {
365: if (!XML_FONT_ROOT.equals(element.getNodeName())) {
366: // Backward compatibility with the default FontEditor from core
367: ((XMLPropertyEditor) delegateEditor).readFromXML(element);
368: setValue(delegateEditor.getValue());
369: return;
370: }
371: org.w3c.dom.NamedNodeMap attributes = element.getAttributes();
372: boolean relative = Boolean.valueOf(
373: attributes.getNamedItem(ATTR_RELATIVE).getNodeValue())
374: .booleanValue();
375: org.w3c.dom.NodeList subnodes = element.getChildNodes();
376: for (int i = 0; i < subnodes.getLength(); i++) {
377: org.w3c.dom.Node subnode = subnodes.item(i);
378: if (subnode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
379: if (relative) {
380: if (!XML_FONT.equals(subnode.getNodeName())) {
381: throw new java.io.IOException();
382: }
383: NbFont propertyValue = new NbFont();
384: propertyValue.property = property;
385: attributes = subnode.getAttributes();
386: propertyValue.absoluteSize = !Boolean.valueOf(
387: attributes.getNamedItem(ATTR_RELATIVE_SIZE)
388: .getNodeValue()).booleanValue();
389: propertyValue.size = Integer.parseInt(attributes
390: .getNamedItem(ATTR_SIZE).getNodeValue());
391: org.w3c.dom.Node italicChange = attributes
392: .getNamedItem(ATTR_ITALIC_CHANGE);
393: if (italicChange != null) {
394: propertyValue.italic = Boolean
395: .valueOf(italicChange.getNodeValue());
396: }
397: org.w3c.dom.Node boldChange = attributes
398: .getNamedItem(ATTR_BOLD_CHANGE);
399: if (boldChange != null) {
400: propertyValue.bold = Boolean.valueOf(boldChange
401: .getNodeValue());
402: }
403: setValue(propertyValue);
404: } else {
405: ((XMLPropertyEditor) delegateEditor)
406: .readFromXML(subnode);
407: }
408: break;
409: }
410: }
411: }
412:
413: public Node storeToXML(Document doc) {
414: Object value = getUnwrappedValue();
415: org.w3c.dom.Element el = doc.createElement(XML_FONT_ROOT);
416: el.setAttribute(ATTR_RELATIVE, Boolean.TRUE.toString());
417: if (!(value instanceof NbFont)) {// || propertyValue.absolute) {
418: org.w3c.dom.Node absNode = ((XMLPropertyEditor) delegateEditor)
419: .storeToXML(doc);
420: el.appendChild(absNode);
421: } else {
422: NbFont propertyValue = (NbFont) value;
423: org.w3c.dom.Element subel = doc.createElement(XML_FONT);
424: el.appendChild(subel);
425: subel.setAttribute(ATTR_RELATIVE_SIZE, Boolean
426: .toString(!propertyValue.absoluteSize));
427: subel.setAttribute(ATTR_SIZE, Integer
428: .toString(propertyValue.size));
429: if (propertyValue.italic != null) {
430: subel.setAttribute(ATTR_ITALIC_CHANGE,
431: propertyValue.italic.toString());
432: }
433: if (propertyValue.bold != null) {
434: subel.setAttribute(ATTR_BOLD_CHANGE, propertyValue.bold
435: .toString());
436: }
437: subel.setAttribute(ATTR_COMP_NAME, ((RADProperty) property)
438: .getRADComponent().getName());
439: subel.setAttribute(ATTR_PROP_NAME, property.getName());
440: }
441: return el;
442: }
443:
444: static class NbFont extends FormDesignValueAdapter {
445: /**
446: * Describes the relative change of italic.
447: * <code>true = add italic, false = remove italic, null = leave it as it is</code>
448: */
449: Boolean italic;
450: /**
451: * Describes the relative change of bold.
452: * <code>true = add bold, false = remove false, null = leave it as it is</code>
453: */
454: Boolean bold;
455: /**
456: * Determines whether the change of the font size is relative or absolute.
457: */
458: boolean absoluteSize;
459: /**
460: * Describes the change of the font size.
461: * <code>size = (absoluteSize) ? absolute size : relative change</code>
462: */
463: int size;
464: /**
465: * Property that contains this value.
466: */
467: FormProperty property;
468:
469: public Object getDesignValue() {
470: Font value = defaultValue(property);
471: if (value != null) {
472: int origStyle = value.getStyle();
473: int style = origStyle;
474: if (italic != null) {
475: if (italic.booleanValue()) {
476: style |= Font.ITALIC;
477: } else {
478: style &= ~Font.ITALIC;
479: }
480: }
481: if (bold != null) {
482: if (bold.booleanValue()) {
483: style |= Font.BOLD;
484: } else {
485: style &= ~Font.BOLD;
486: }
487: }
488: int origSize = value.getSize();
489: int newSize = (absoluteSize) ? size : (size + origSize);
490: if ((style != origStyle) || (origSize != newSize)) {
491: value = value.deriveFont(style, newSize);
492: }
493: }
494: return value;
495: }
496:
497: private Font defaultValue(FormProperty property) {
498: if ((property instanceof RADProperty)
499: && FormLAF.getUsePreviewDefaults()) {
500: RADProperty radProp = (RADProperty) property;
501: PropertyDescriptor propDesc = radProp
502: .getPropertyDescriptor();
503: java.lang.reflect.Method readMethod = propDesc
504: .getReadMethod();
505: if (readMethod != null) {
506: try {
507: Class clazz = radProp.getRADComponent()
508: .getBeanClass();
509: Object beanInstance = BeanSupport
510: .createBeanInstance(clazz);
511: return (Font) readMethod.invoke(beanInstance,
512: new Object[0]);
513: } catch (Exception e) {
514: }
515: }
516: }
517: return (Font) property.getDefaultValue();
518: }
519:
520: @Override
521: public String getDescription() {
522: ResourceBundle bundle = NbBundle
523: .getBundle(FontEditor.class);
524: String description;
525: description = Integer.toString(size);
526: if (!absoluteSize && (size > 0)) {
527: description = '+' + description;
528: }
529: if (italic != null) {
530: description += " "
531: + (italic.booleanValue() ? '+' : '-')
532: + bundle.getString("CTL_FontStyleItalic"); // NOI18N
533: }
534: if (bold != null) {
535: description += " " + (bold.booleanValue() ? '+' : '-')
536: + bundle.getString("CTL_FontStyleBold"); // NOI18N
537: }
538: if (description.charAt(0) == '0')
539: description = description.substring(Math.min(2,
540: description.length()));
541: return description;
542: }
543:
544: @Override
545: public FormDesignValue copy(FormProperty targetFormProperty) {
546: NbFont copy = copy();
547: copy.property = targetFormProperty;
548: return copy;
549: }
550:
551: NbFont copy() {
552: NbFont newValue = new NbFont();
553: newValue.italic = italic;
554: newValue.bold = bold;
555: newValue.absoluteSize = absoluteSize;
556: newValue.size = size;
557: newValue.property = property;
558: return newValue;
559: }
560: }
561:
562: /**
563: * Panel used to configure the relative change.
564: */
565: private class RelativeFontPanel extends JPanel {
566: private JRadioButton absoluteChoice;
567: private JSpinner absoluteSize;
568: private JRadioButton addBoldChoice;
569: private JRadioButton addItalicChoice;
570: private JCheckBox italicCheckBox;
571: private JRadioButton relativeChoice;
572: private JSpinner relativeSize;
573: private JRadioButton removeBoldChoice;
574: private JRadioButton removeItalicChoice;
575: private JCheckBox thicknessCheckBox;
576:
577: private boolean ignoreUpdates;
578:
579: RelativeFontPanel() {
580: initComponents();
581: }
582:
583: void updateFromPropertyValue() {
584: NbFont propertyValue = (NbFont) getUnwrappedValue();
585:
586: ignoreUpdates = true;
587: boolean changeItalic = (propertyValue.italic != null);
588: italicCheckBox.setSelected(changeItalic);
589: addItalicChoice.setEnabled(changeItalic);
590: removeItalicChoice.setEnabled(changeItalic);
591: if (!changeItalic) {
592: addItalicChoice.setSelected(true);
593: } else if (Boolean.TRUE.equals(propertyValue.italic)) {
594: addItalicChoice.setSelected(true);
595: } else if (Boolean.FALSE.equals(propertyValue.italic)) {
596: removeItalicChoice.setSelected(true);
597: }
598: boolean changeBold = (propertyValue.bold != null);
599: thicknessCheckBox.setSelected(changeBold);
600: addBoldChoice.setEnabled(changeBold);
601: removeBoldChoice.setEnabled(changeBold);
602: if (!changeBold) {
603: addBoldChoice.setSelected(true);
604: } else if (Boolean.TRUE.equals(propertyValue.bold)) {
605: addBoldChoice.setSelected(true);
606: } else if (Boolean.FALSE.equals(propertyValue.bold)) {
607: removeBoldChoice.setSelected(true);
608: }
609: absoluteSize.setEnabled(propertyValue.absoluteSize);
610: relativeSize.setEnabled(!propertyValue.absoluteSize);
611: if (propertyValue.absoluteSize) {
612: absoluteSize.setValue(new Integer(propertyValue.size));
613: absoluteChoice.setSelected(true);
614: synchronizeSizeControls(propertyValue);
615: } else {
616: relativeSize.setValue(new Integer(propertyValue.size));
617: relativeChoice.setSelected(true);
618: synchronizeSizeControls(propertyValue);
619: }
620: ignoreUpdates = false;
621: }
622:
623: private void synchronizeSizeControls(NbFont propertyValue) {
624: if (propertyValue.absoluteSize) {
625: Font defaultFont = (Font) property.getDefaultValue();
626: if (defaultFont != null) {
627: relativeSize
628: .setValue(new Integer(propertyValue.size
629: - defaultFont.getSize()));
630: }
631: } else {
632: Font font = (Font) propertyValue.getDesignValue();
633: absoluteSize.setValue(new Integer(font == null ? 12
634: : font.getSize()));
635: }
636: }
637:
638: private void initComponents() {
639: relativeSize = new JSpinner(new SpinnerNumberModel(0,
640: Short.MIN_VALUE, Short.MAX_VALUE, 1));
641: relativeSize.setEditor(new JSpinner.NumberEditor(
642: relativeSize, "+#;-#")); // NOI18N
643: absoluteSize = new JSpinner(new SpinnerNumberModel(12, 1,
644: Short.MAX_VALUE, 1));
645:
646: ResourceBundle bundle = NbBundle
647: .getBundle(FontEditor.class);
648: JLabel fontSizeLabel = new JLabel(bundle
649: .getString("CTL_FontSize")); // NOI18N
650: JLabel fontStyleLabel = new JLabel(bundle
651: .getString("CTL_FontStyle")); // NOI18N
652:
653: absoluteChoice = new JRadioButton();
654: Mnemonics.setLocalizedText(absoluteChoice, bundle
655: .getString("CTL_AbsoluteFontSize")); // NOI18N
656:
657: relativeChoice = new JRadioButton();
658: Mnemonics.setLocalizedText(relativeChoice, bundle
659: .getString("CTL_RelativeFontSize")); // NOI18N
660:
661: italicCheckBox = new JCheckBox();
662: Mnemonics.setLocalizedText(italicCheckBox, bundle
663: .getString("CTL_ChangeItalic")); // NOI18N
664:
665: addItalicChoice = new JRadioButton();
666: Mnemonics.setLocalizedText(addItalicChoice, bundle
667: .getString("CTL_AddItalic")); // NOI18N
668:
669: removeItalicChoice = new JRadioButton();
670: Mnemonics.setLocalizedText(removeItalicChoice, bundle
671: .getString("CTL_RemoveItalic")); // NOI18N
672:
673: thicknessCheckBox = new JCheckBox();
674: Mnemonics.setLocalizedText(thicknessCheckBox, bundle
675: .getString("CTL_ChangeBold")); // NOI18N
676:
677: addBoldChoice = new JRadioButton();
678: Mnemonics.setLocalizedText(addBoldChoice, bundle
679: .getString("CTL_AddBold")); // NOI18N
680:
681: removeBoldChoice = new JRadioButton();
682: Mnemonics.setLocalizedText(removeBoldChoice, bundle
683: .getString("CTL_RemoveBold")); // NOI18N
684:
685: // Listener
686: Listener listener = new Listener();
687: relativeChoice.addItemListener(listener);
688: thicknessCheckBox.addItemListener(listener);
689: italicCheckBox.addItemListener(listener);
690: relativeSize.addChangeListener(listener);
691: absoluteSize.addChangeListener(listener);
692: addItalicChoice.addItemListener(listener);
693: addBoldChoice.addItemListener(listener);
694:
695: // Radio button groups
696: ButtonGroup italicGroup = new ButtonGroup();
697: italicGroup.add(addItalicChoice);
698: italicGroup.add(removeItalicChoice);
699:
700: ButtonGroup thicknessGroup = new ButtonGroup();
701: thicknessGroup.add(addBoldChoice);
702: thicknessGroup.add(removeBoldChoice);
703:
704: ButtonGroup fontSizeGroup = new ButtonGroup();
705: fontSizeGroup.add(absoluteChoice);
706: fontSizeGroup.add(relativeChoice);
707:
708: // Eliminate redundant borders
709: Border emptyBorder = BorderFactory.createEmptyBorder(0, 0,
710: 0, 0);
711: Insets emptyInsets = new Insets(0, 0, 0, 0);
712:
713: absoluteChoice.setBorder(emptyBorder);
714: absoluteChoice.setMargin(emptyInsets);
715: relativeChoice.setBorder(emptyBorder);
716: relativeChoice.setMargin(emptyInsets);
717: italicCheckBox.setBorder(emptyBorder);
718: italicCheckBox.setMargin(emptyInsets);
719: addItalicChoice.setBorder(emptyBorder);
720: addItalicChoice.setMargin(emptyInsets);
721: removeItalicChoice.setBorder(emptyBorder);
722: removeItalicChoice.setMargin(emptyInsets);
723: thicknessCheckBox.setBorder(emptyBorder);
724: thicknessCheckBox.setMargin(emptyInsets);
725: addBoldChoice.setBorder(emptyBorder);
726: addBoldChoice.setMargin(emptyInsets);
727: removeBoldChoice.setBorder(emptyBorder);
728: removeBoldChoice.setMargin(emptyInsets);
729:
730: GroupLayout layout = new GroupLayout(this );
731: setLayout(layout);
732: layout
733: .setHorizontalGroup(layout
734: .createSequentialGroup()
735: .addContainerGap()
736: .add(
737: layout
738: .createParallelGroup()
739: .add(fontSizeLabel)
740: .add(
741: layout
742: .createSequentialGroup()
743: .add(
744: layout
745: .createParallelGroup()
746: .add(
747: relativeChoice)
748: .add(
749: absoluteChoice))
750: .addPreferredGap(
751: LayoutStyle.RELATED)
752: .add(
753: layout
754: .createParallelGroup()
755: .add(
756: relativeSize,
757: GroupLayout.PREFERRED_SIZE,
758: 50,
759: GroupLayout.PREFERRED_SIZE)
760: .add(
761: absoluteSize,
762: GroupLayout.PREFERRED_SIZE,
763: 50,
764: GroupLayout.PREFERRED_SIZE))))
765: .addPreferredGap(LayoutStyle.UNRELATED)
766: .add(
767: layout
768: .createParallelGroup()
769: .add(fontStyleLabel)
770: .add(
771: layout
772: .createSequentialGroup()
773: .add(
774: layout
775: .createParallelGroup()
776: .add(
777: italicCheckBox)
778: .add(
779: layout
780: .createSequentialGroup()
781: .add(
782: 17)
783: .add(
784: layout
785: .createParallelGroup()
786: .add(
787: addItalicChoice)
788: .add(
789: removeItalicChoice))))
790: .addPreferredGap(
791: LayoutStyle.RELATED)
792: .add(
793: layout
794: .createParallelGroup()
795: .add(
796: thicknessCheckBox)
797: .add(
798: layout
799: .createSequentialGroup()
800: .add(
801: 17)
802: .add(
803: layout
804: .createParallelGroup()
805: .add(
806: removeBoldChoice)
807: .add(
808: addBoldChoice))))))
809: .addContainerGap());
810: layout
811: .setVerticalGroup(layout.createSequentialGroup()
812: .addContainerGap().add(
813: layout.createParallelGroup(
814: GroupLayout.BASELINE).add(
815: fontSizeLabel).add(
816: fontStyleLabel))
817: .addPreferredGap(LayoutStyle.RELATED).add(
818: layout.createParallelGroup(
819: GroupLayout.BASELINE).add(
820: relativeChoice).add(
821: relativeSize,
822: GroupLayout.PREFERRED_SIZE,
823: GroupLayout.DEFAULT_SIZE,
824: GroupLayout.PREFERRED_SIZE)
825: .add(italicCheckBox).add(
826: thicknessCheckBox))
827: .addPreferredGap(LayoutStyle.RELATED).add(
828: layout.createParallelGroup(
829: GroupLayout.BASELINE).add(
830: absoluteChoice).add(
831: absoluteSize,
832: GroupLayout.PREFERRED_SIZE,
833: GroupLayout.DEFAULT_SIZE,
834: GroupLayout.PREFERRED_SIZE)
835: .add(addItalicChoice).add(
836: addBoldChoice))
837: .addPreferredGap(LayoutStyle.RELATED).add(
838: layout.createParallelGroup(
839: GroupLayout.BASELINE).add(
840: removeItalicChoice).add(
841: removeBoldChoice))
842: .addContainerGap(260, 260));
843: }
844:
845: private class Listener implements ItemListener, ChangeListener {
846: // called when some of the checkboxes/radiobuttons is selected/unselected
847: public void itemStateChanged(ItemEvent e) {
848: if (ignoreUpdates)
849: return;
850: ignoreUpdates = true;
851: NbFont propertyValue = ((NbFont) getUnwrappedValue())
852: .copy();
853: Object source = e.getSource();
854: if (source == relativeChoice) {
855: boolean relative = relativeChoice.isSelected();
856: relativeSize.setEnabled(relative);
857: absoluteSize.setEnabled(!relative);
858: propertyValue.absoluteSize = !relative;
859: propertyValue.size = ((Number) ((relative ? relativeSize
860: : absoluteSize).getValue())).intValue();
861: } else if (source == italicCheckBox) {
862: boolean changeItalic = italicCheckBox.isSelected();
863: addItalicChoice.setEnabled(changeItalic);
864: removeItalicChoice.setEnabled(changeItalic);
865: propertyValue.italic = changeItalic ? Boolean
866: .valueOf(addItalicChoice.isSelected())
867: : null;
868: } else if (source == thicknessCheckBox) {
869: boolean changeBold = thicknessCheckBox.isSelected();
870: addBoldChoice.setEnabled(changeBold);
871: removeBoldChoice.setEnabled(changeBold);
872: propertyValue.bold = changeBold ? Boolean
873: .valueOf(addBoldChoice.isSelected()) : null;
874: } else if (source == addBoldChoice) {
875: propertyValue.bold = Boolean.valueOf(addBoldChoice
876: .isSelected());
877: } else if (source == addItalicChoice) {
878: propertyValue.italic = Boolean
879: .valueOf(addItalicChoice.isSelected());
880: }
881: ignoreUpdates = false;
882: setValue(propertyValue);
883: }
884:
885: // called when the size of the font is changed in one of the spinners
886: public void stateChanged(ChangeEvent e) {
887: if (ignoreUpdates)
888: return;
889: ignoreUpdates = true;
890: NbFont propertyValue = ((NbFont) getUnwrappedValue())
891: .copy();
892: Object source = e.getSource();
893: if (source == relativeSize) {
894: propertyValue.size = ((Number) relativeSize
895: .getValue()).intValue();
896: synchronizeSizeControls(propertyValue);
897: } else if (source == absoluteSize) {
898: propertyValue.size = ((Number) absoluteSize
899: .getValue()).intValue();
900: synchronizeSizeControls(propertyValue);
901: }
902: ignoreUpdates = false;
903: setValue(propertyValue);
904: }
905: }
906: }
907:
908: }
|