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;
043:
044: import java.util.*;
045: import java.beans.*;
046: import javax.accessibility.*;
047: import javax.swing.*;
048: import javax.swing.MenuElement;
049:
050: import org.openide.nodes.*;
051:
052: import org.netbeans.modules.form.layoutdesign.*;
053: import org.netbeans.modules.form.layoutsupport.*;
054:
055: /**
056: *
057: * @author Ian Formanek
058: */
059:
060: public class RADVisualComponent extends RADComponent {
061: private static final String PROP_LAYOUT_COMPONENT_HORIZONTAL_SIZE = "layoutComponentHorizontalSize"; // NOI18N
062: private static final String PROP_LAYOUT_COMPONENT_VERTICAL_SIZE = "layoutComponentVerticalSize"; // NOI18N
063: private static final String PROP_LAYOUT_COMPONENT_HORIZONTAL_RESIZABLE = "layoutComponentHorizontalResizable"; // NOI18N
064: private static final String PROP_LAYOUT_COMPONENT_VERTICAL_RESIZABLE = "layoutComponentVerticalResizable"; // NOI18N
065:
066: // -----------------------------------------------------------------------------
067: // Private properties
068:
069: // [??]
070: private Map<String, LayoutConstraints> constraints = new HashMap<String, LayoutConstraints>();
071: // transient private RADVisualContainer parent;
072:
073: private Node.Property[] constraintsProperties;
074: private ConstraintsListenerConvertor constraintsListener;
075:
076: private MetaAccessibleContext accessibilityData;
077: private FormProperty[] accessibilityProperties;
078:
079: enum MenuType {
080: JMenuItem, JCheckBoxMenuItem, JRadioButtonMenuItem, JMenu, JMenuBar, JPopupMenu, JSeparator
081: }
082:
083: // -----------------------------------------------------------------------------
084: // Initialization
085:
086: // public void setParentComponent(RADComponent parentComp) {
087: // super.setParentComponent(parentComp);
088: // if (parentComp != null)
089: // getConstraintsProperties();
090: // }
091:
092: // void initParent(RADVisualContainer parent) {
093: // this.parent = parent;
094: // }
095:
096: /* protected void setBeanInstance(Object beanInstance) {
097: if (beanInstance instanceof java.awt.Component) {
098: boolean attached = FakePeerSupport.attachFakePeer(
099: (java.awt.Component)beanInstance);
100: if (attached && beanInstance instanceof java.awt.Container)
101: FakePeerSupport.attachFakePeerRecursively(
102: (java.awt.Container)beanInstance);
103: }
104:
105: super.setBeanInstance(beanInstance);
106: } */
107:
108: // -----------------------------------------------------------------------------
109: // Public interface
110: /** @return The JavaBean visual component represented by this RADVisualComponent */
111: // public java.awt.Component getComponent() { // [is it needed ???]
112: // return (java.awt.Component) getBeanInstance();
113: // }
114: public final RADVisualContainer getParentContainer() {
115: return (RADVisualContainer) getParentComponent();
116: }
117:
118: /** @return The index of this component within visual components of its parent */
119: public final int getComponentIndex() {
120: RADVisualContainer parent = (RADVisualContainer) getParentComponent();
121: return parent != null ? parent.getIndexOf(this ) : -1;
122: // return ((ComponentContainer)getParentComponent()).getIndexOf(this);
123: }
124:
125: final LayoutSupportManager getParentLayoutSupport() {
126: RADVisualContainer parent = (RADVisualContainer) getParentComponent();
127: return parent != null ? parent.getLayoutSupport() : null;
128: }
129:
130: boolean isMenuTypeComponent() {
131: return MenuElement.class.isAssignableFrom(getBeanClass());
132: }
133:
134: /**
135: * Returns whether this component is treated specially as a menu component.
136: * Not only it must be of particluar Swing menu class, but must also be used
137: * as a menu, not as normal visual component. Technically it must be either
138: * contained in another menu, or be a menu bar of a window.
139: * @return whether the component is a menu used in another menu or as menu
140: * bar in a window
141: */
142: public boolean isMenuComponent() {
143: if (isMenuTypeComponent()) {
144: RADVisualContainer parent = getParentContainer();
145: if ((parent == null && !isInModel())
146: || (parent != null && (parent.isMenuTypeComponent() || this == parent
147: .getContainerMenu()))) {
148: return true;
149: }
150: }
151: return false;
152: }
153:
154: static MenuType getMenuType(Class cl) {
155: if (MenuElement.class.isAssignableFrom(cl)) {
156: if (JMenu.class.isAssignableFrom(cl)) {
157: return MenuType.JMenu;
158: }
159: if (JMenuBar.class.isAssignableFrom(cl)) {
160: return MenuType.JMenuBar;
161: }
162: if (JCheckBoxMenuItem.class.isAssignableFrom(cl)) {
163: return MenuType.JCheckBoxMenuItem;
164: }
165: if (JRadioButtonMenuItem.class.isAssignableFrom(cl)) {
166: return MenuType.JRadioButtonMenuItem;
167: }
168: if (JMenuItem.class.isAssignableFrom(cl)) {
169: return MenuType.JMenuItem;
170: }
171: if (JPopupMenu.class.isAssignableFrom(cl)) {
172: return MenuType.JPopupMenu;
173: }
174: } else if (JSeparator.class.isAssignableFrom(cl)) {
175: return MenuType.JSeparator;
176: }
177: return null;
178: }
179:
180: // -----------------------------------------------------------------------------
181: // Layout constraints management
182:
183: /**
184: * Sets component's constraints description for given layout-support class.
185: *
186: * @param layoutDelegateClass class of the layout delegate these constraints belong to.
187: * @param constr layout constraints.
188: */
189: public void setLayoutConstraints(Class layoutDelegateClass,
190: LayoutConstraints constr) {
191: if (constr != null) {
192: constraints.put(layoutDelegateClass.getName(), constr);
193: }
194: }
195:
196: /**
197: * Gets component's constraints description for given layout-support class.
198: *
199: * @param layoutDelegateClass class of the layout delegate.
200: * @return layout constraints for the given layout delegate.
201: */
202: public LayoutConstraints getLayoutConstraints(
203: Class layoutDelegateClass) {
204: return constraints.get(layoutDelegateClass.getName());
205: }
206:
207: Map<String, LayoutConstraints> getConstraintsMap() {
208: return constraints;
209: }
210:
211: void setConstraintsMap(Map<String, LayoutConstraints> map) {
212: constraints.putAll(map);
213: }
214:
215: // ---------------
216: // Properties
217:
218: @Override
219: protected void createPropertySets(List<Node.PropertySet> propSets) {
220: super .createPropertySets(propSets);
221:
222: if (constraintsProperties == null)
223: createConstraintsProperties();
224:
225: if (constraintsProperties != null
226: && constraintsProperties.length > 0)
227: propSets.add(propSets.size() - 1, new Node.PropertySet(
228: "layout", // NOI18N
229: FormUtils.getBundleString("CTL_LayoutTab"), // NOI18N
230: FormUtils.getBundleString("CTL_LayoutTabHint")) // NOI18N
231: {
232: public Node.Property[] getProperties() {
233: return getConstraintsProperties();
234: }
235: });
236:
237: if (accessibilityProperties == null)
238: createAccessibilityProperties();
239:
240: if (accessibilityProperties.length > 0)
241: propSets
242: .add(new Node.PropertySet(
243: "accessibility", // NOI18N
244: FormUtils
245: .getBundleString("CTL_AccessibilityTab"), // NOI18N
246: FormUtils
247: .getBundleString("CTL_AccessibilityTabHint")) // NOI18N
248: {
249: public Node.Property[] getProperties() {
250: return getAccessibilityProperties();
251: }
252: });
253: }
254:
255: @Override
256: public <T> T getPropertyByName(String name,
257: Class<? extends T> propertyType, boolean fromAll) {
258: if (fromAll && accessibilityProperties == null)
259: createAccessibilityProperties();
260: return super .getPropertyByName(name, propertyType, fromAll);
261: }
262:
263: /** Called to modify original properties obtained from BeanInfo.
264: * Properties may be added, removed etc. - due to specific needs
265: * of subclasses. Here used for adding ButtonGroupProperty.
266: */
267: /* protected void changePropertiesExplicitly(List prefProps,
268: List normalProps,
269: List expertProps) {
270:
271: super.changePropertiesExplicitly(prefProps, normalProps, expertProps);
272:
273: if (getBeanInstance() instanceof java.awt.TextComponent) {
274: // hack for AWT text components - "text" property should be first
275: for (int i=0, n=normalProps.size(); i < n; i++) {
276: RADProperty prop = (RADProperty) normalProps.get(i);
277: if ("text".equals(prop.getName())) { // NOI18N
278: normalProps.remove(i);
279: normalProps.add(0, prop);
280: break;
281: }
282: }
283: }
284:
285: // hack for buttons - add a fake property for ButtonGroup
286: // if (getBeanInstance() instanceof javax.swing.AbstractButton)
287: // try {
288: // Node.Property prop = new ButtonGroupProperty(this);
289: // nameToProperty.put(prop.getName(), prop);
290: // if (getBeanInstance() instanceof javax.swing.JToggleButton)
291: // prefProps.add(prop);
292: // else
293: // normalProps.add(prop);
294: // }
295: // catch (IntrospectionException ex) {} // should not happen
296:
297: // if (getBeanInstance() instanceof javax.swing.JLabel)
298: // try {
299: // PropertyDescriptor pd = new PropertyDescriptor("displayedMnemonic",
300: // javax.swing.JLabel.class, "getDisplayedMnemonic", "setDisplayedMnemonic");
301: // normalProps.add(createProperty(pd));
302: // }
303: // catch (IntrospectionException ex) {} // should not happen
304: } */
305:
306: @Override
307: protected void clearProperties() {
308: super .clearProperties();
309: constraintsProperties = null;
310: accessibilityData = null;
311: accessibilityProperties = null;
312: }
313:
314: // ---------
315: // constraints properties
316:
317: public Node.Property[] getConstraintsProperties() {
318: if (constraintsProperties == null)
319: createConstraintsProperties();
320: return constraintsProperties;
321: }
322:
323: public void resetConstraintsProperties() {
324: if (constraintsProperties != null) {
325: for (int i = 0; i < constraintsProperties.length; i++)
326: nameToProperty.remove(constraintsProperties[i]
327: .getName());
328:
329: constraintsProperties = null;
330: propertySets = null;
331:
332: RADComponentNode node = getNodeReference();
333: if (node != null)
334: node.fireComponentPropertySetsChange();
335: }
336: }
337:
338: private void createConstraintsProperties() {
339: constraintsProperties = null;
340:
341: LayoutSupportManager layoutSupport = getParentLayoutSupport();
342: if (layoutSupport != null) {
343: LayoutConstraints constr = layoutSupport
344: .getConstraints(this );
345: if (constr != null)
346: constraintsProperties = constr.getProperties();
347: } else if (getParentContainer() != null) {
348: LayoutComponent component = getFormModel().getLayoutModel()
349: .getLayoutComponent(getId());
350: if (component == null)
351: return; // Will be called again later
352: constraintsProperties = new Node.Property[] {
353: new LayoutComponentSizeProperty(component,
354: LayoutConstants.HORIZONTAL),
355: new LayoutComponentSizeProperty(component,
356: LayoutConstants.VERTICAL),
357: new LayoutComponentResizableProperty(component,
358: LayoutConstants.HORIZONTAL),
359: new LayoutComponentResizableProperty(component,
360: LayoutConstants.VERTICAL) };
361: component
362: .addPropertyChangeListener(new PropertyChangeListener() {
363: public void propertyChange(
364: PropertyChangeEvent evt) {
365: RADComponentNode node = getNodeReference();
366: if (node != null) {
367: String propName = evt.getPropertyName();
368: if (LayoutConstants.PROP_HORIZONTAL_PREF_SIZE
369: .equals(propName)) {
370: node
371: .firePropertyChangeHelper(
372: PROP_LAYOUT_COMPONENT_HORIZONTAL_SIZE,
373: null, null);
374: } else if (LayoutConstants.PROP_VERTICAL_PREF_SIZE
375: .equals(propName)) {
376: node
377: .firePropertyChangeHelper(
378: PROP_LAYOUT_COMPONENT_VERTICAL_SIZE,
379: null, null);
380: } else if (LayoutConstants.PROP_HORIZONTAL_MAX_SIZE
381: .equals(propName)) {
382: node
383: .firePropertyChangeHelper(
384: PROP_LAYOUT_COMPONENT_HORIZONTAL_RESIZABLE,
385: null, null);
386: } else if (LayoutConstants.PROP_VERTICAL_MAX_SIZE
387: .equals(propName)) {
388: node
389: .firePropertyChangeHelper(
390: PROP_LAYOUT_COMPONENT_VERTICAL_RESIZABLE,
391: null, null);
392: }
393: }
394: }
395: });
396: }
397:
398: if (constraintsProperties == null) {
399: constraintsProperties = NO_PROPERTIES;
400: return;
401: }
402:
403: for (int i = 0; i < constraintsProperties.length; i++) {
404: if (constraintsProperties[i] instanceof FormProperty) {
405: FormProperty prop = (FormProperty) constraintsProperties[i];
406:
407: // we suppose the constraint property is not a RADProperty...
408: prop
409: .addVetoableChangeListener(getConstraintsListener());
410: prop
411: .addPropertyChangeListener(getConstraintsListener());
412: prop.addValueConvertor(getConstraintsListener());
413:
414: prop
415: .setPropertyContext(new FormPropertyContext.Component(
416: this ));
417:
418: if (isReadOnly() || !isValid()) {
419: int type = prop.getAccessType()
420: | FormProperty.NO_WRITE;
421: prop.setAccessType(type);
422: }
423: nameToProperty.put(prop.getName(), prop);
424: }
425: }
426: }
427:
428: private ConstraintsListenerConvertor getConstraintsListener() {
429: if (constraintsListener == null)
430: constraintsListener = new ConstraintsListenerConvertor();
431: return constraintsListener;
432: }
433:
434: private class ConstraintsListenerConvertor implements
435: VetoableChangeListener, PropertyChangeListener,
436: FormProperty.ValueConvertor {
437: public void vetoableChange(PropertyChangeEvent ev)
438: throws PropertyVetoException {
439: Object source = ev.getSource();
440: String eventName = ev.getPropertyName();
441: if (source instanceof FormProperty
442: && (FormProperty.PROP_VALUE.equals(eventName) || FormProperty.PROP_VALUE_AND_EDITOR
443: .equals(eventName))) {
444: resourcePropertyChanged(ev);
445:
446: LayoutSupportManager layoutSupport = getParentLayoutSupport();
447: int index = getComponentIndex();
448: LayoutConstraints constraints = layoutSupport
449: .getConstraints(index);
450:
451: ev = new PropertyChangeEvent(constraints,
452: ((FormProperty) source).getName(), ev
453: .getOldValue(), ev.getNewValue());
454:
455: layoutSupport.componentLayoutChanged(index, ev);
456: }
457: }
458:
459: public void propertyChange(PropertyChangeEvent ev) {
460: Object source = ev.getSource();
461: if (source instanceof FormProperty
462: && FormProperty.CURRENT_EDITOR.equals(ev
463: .getPropertyName())) {
464: LayoutSupportManager layoutSupport = getParentLayoutSupport();
465: int index = getComponentIndex();
466: LayoutConstraints constraints = layoutSupport
467: .getConstraints(index);
468:
469: ev = new PropertyChangeEvent(constraints, null, null,
470: null);
471:
472: try {
473: layoutSupport.componentLayoutChanged(index, ev);
474: } catch (PropertyVetoException ex) {
475: } // should not happen
476: }
477: }
478:
479: public Object convert(Object value, FormProperty property) {
480: return resourcePropertyConvert(value, property);
481: }
482: }
483:
484: // ----------
485: // accessibility properties
486:
487: public FormProperty[] getAccessibilityProperties() {
488: if (accessibilityProperties == null)
489: createAccessibilityProperties();
490: return accessibilityProperties;
491: }
492:
493: private void createAccessibilityProperties() {
494: Object comp = getBeanInstance();
495: if (comp instanceof Accessible
496: && ((Accessible) comp).getAccessibleContext() != null) {
497: if (accessibilityData == null)
498: accessibilityData = new MetaAccessibleContext();
499: accessibilityProperties = accessibilityData.getProperties();
500:
501: for (int i = 0; i < accessibilityProperties.length; i++) {
502: FormProperty prop = accessibilityProperties[i];
503: setPropertyListener(prop);
504: prop
505: .setPropertyContext(new FormPropertyContext.Component(
506: this ));
507: nameToProperty.put(prop.getName(), prop);
508: }
509: } else {
510: accessibilityData = null;
511: accessibilityProperties = NO_PROPERTIES;
512: }
513: }
514:
515: private class MetaAccessibleContext {
516: private Object accName = BeanSupport.NO_VALUE;
517: private Object accDescription = BeanSupport.NO_VALUE;
518: private Object accParent = BeanSupport.NO_VALUE;
519:
520: private FormProperty[] properties;
521:
522: FormProperty[] getProperties() {
523: if (properties == null) {
524: properties = new FormProperty[] {
525: new FormProperty(
526: "AccessibleContext.accessibleName", // NOI18N
527: String.class,
528: FormUtils
529: .getBundleString("PROP_AccessibleName"), // NOI18N
530: FormUtils
531: .getBundleString("PROP_AccessibleName")) // NOI18N
532: {
533: public Object getTargetValue() {
534: return accName != BeanSupport.NO_VALUE ? accName
535: : getDefaultValue();
536: }
537:
538: public void setTargetValue(Object value) {
539: accName = (String) value;
540: }
541:
542: @Override
543: public boolean supportsDefaultValue() {
544: return true;
545: }
546:
547: @Override
548: public Object getDefaultValue() {
549: return getAccessibleContext()
550: .getAccessibleName();
551: }
552:
553: @Override
554: public void restoreDefaultValue()
555: throws IllegalAccessException,
556: java.lang.reflect.InvocationTargetException {
557: super .restoreDefaultValue();
558: accName = BeanSupport.NO_VALUE;
559: }
560:
561: @Override
562: String getPartialSetterCode(
563: String javaInitStr) {
564: return "getAccessibleContext().setAccessibleName(" // NOI18N
565: + javaInitStr + ")"; // NOI18N
566: }
567: },
568:
569: new FormProperty(
570: "AccessibleContext.accessibleDescription", // NOI18N
571: String.class,
572: FormUtils
573: .getBundleString("PROP_AccessibleDescription"), // NOI18N
574: FormUtils
575: .getBundleString("PROP_AccessibleDescription")) // NOI18N
576: {
577: public Object getTargetValue() {
578: return accDescription != BeanSupport.NO_VALUE ? accDescription
579: : getDefaultValue();
580: }
581:
582: public void setTargetValue(Object value) {
583: accDescription = (String) value;
584: }
585:
586: @Override
587: public boolean supportsDefaultValue() {
588: return true;
589: }
590:
591: @Override
592: public Object getDefaultValue() {
593: AccessibleContext context = getAccessibleContext();
594: Object bean = getBeanInstance();
595: if (bean instanceof JComponent) {
596: Object o = ((JComponent) bean)
597: .getClientProperty("labeledBy"); // NOI18N
598: if (o instanceof Accessible) {
599: AccessibleContext ac = ((Accessible) o)
600: .getAccessibleContext();
601: if (ac == context) {
602: return FormUtils
603: .getBundleString("MSG_CyclicAccessibleContext"); // NOI18N
604: }
605: }
606: }
607: return context
608: .getAccessibleDescription();
609: }
610:
611: @Override
612: public void restoreDefaultValue()
613: throws IllegalAccessException,
614: java.lang.reflect.InvocationTargetException {
615: super .restoreDefaultValue();
616: accDescription = BeanSupport.NO_VALUE;
617: }
618:
619: @Override
620: String getPartialSetterCode(
621: String javaInitStr) {
622: return "getAccessibleContext().setAccessibleDescription(" // NOI18N
623: + javaInitStr + ")"; // NOI18N
624: }
625: },
626:
627: new FormProperty(
628: "AccessibleContext.accessibleParent", // NOI18N
629: Accessible.class,
630: FormUtils
631: .getBundleString("PROP_AccessibleParent"), // NOI18N
632: FormUtils
633: .getBundleString("PROP_AccessibleParent")) // NOI18N
634: {
635: public Object getTargetValue() {
636: return accParent != BeanSupport.NO_VALUE ? accParent
637: : getDefaultValue();
638: }
639:
640: public void setTargetValue(Object value) {
641: accParent = value;
642: }
643:
644: @Override
645: public boolean supportsDefaultValue() {
646: return true;
647: }
648:
649: @Override
650: public Object getDefaultValue() {
651: Object acP = getAccessibleContext()
652: .getAccessibleParent();
653: if (acP != null) {
654: RADVisualContainer metacont = getParentContainer();
655: if (metacont != null) {
656: Object cont = metacont
657: .getContainerDelegate(metacont
658: .getBeanInstance());
659: if (cont == acP)
660: return metacont;
661: }
662: }
663: return acP;
664: }
665:
666: @Override
667: public void restoreDefaultValue()
668: throws IllegalAccessException,
669: java.lang.reflect.InvocationTargetException {
670: super .restoreDefaultValue();
671: accParent = BeanSupport.NO_VALUE;
672: }
673:
674: @Override
675: public PropertyEditor getExpliciteEditor() {
676: return new AccessibleParentEditor();
677: }
678:
679: @Override
680: String getPartialSetterCode(
681: String javaInitStr) {
682: return javaInitStr == null ? null
683: : "getAccessibleContext().setAccessibleParent(" // NOI18N
684: + javaInitStr + ")"; // NOI18N
685: }
686: } };
687: }
688: return properties;
689: }
690:
691: private AccessibleContext getAccessibleContext() {
692: return ((Accessible) getBeanInstance())
693: .getAccessibleContext();
694: }
695: }
696:
697: public static class AccessibleParentEditor extends
698: ComponentChooserEditor {
699: public AccessibleParentEditor() {
700: super ();
701: setBeanTypes(new Class[] { Accessible.class });
702: }
703: }
704:
705: /**
706: * Preferred size of the component in the layout.
707: */
708: private class LayoutComponentSizeProperty extends
709: PropertySupport.ReadWrite {
710: private LayoutComponent component;
711: private int dimension;
712:
713: private LayoutComponentSizeProperty(LayoutComponent component,
714: int dimension) {
715: super (
716: dimension == LayoutConstants.HORIZONTAL ? PROP_LAYOUT_COMPONENT_HORIZONTAL_SIZE
717: : PROP_LAYOUT_COMPONENT_VERTICAL_SIZE,
718: Integer.class, null, null);
719: boolean horizontal = dimension == LayoutConstants.HORIZONTAL;
720: setDisplayName(FormUtils
721: .getBundleString(horizontal ? "PROP_LAYOUT_COMPONENT_HORIZONTAL_SIZE"
722: : "PROP_LAYOUT_COMPONENT_VERTICAL_SIZE")); // NOI18N
723: setShortDescription(FormUtils
724: .getBundleString(horizontal ? "HINT_LAYOUT_COMPONENT_HORIZONTAL_SIZE"
725: : "HINT_LAYOUT_COMPONENT_VERTICAL_SIZE")); // NOI18N
726: this .component = component;
727: this .dimension = dimension;
728: setValue("canEditAsText", Boolean.TRUE); // NOI18N
729: }
730:
731: public void setValue(Object value) {
732: if (!(value instanceof Integer))
733: throw new IllegalArgumentException();
734:
735: Integer oldValue = (Integer) getValue();
736: Integer newValue = (Integer) value;
737: LayoutModel layoutModel = getFormModel().getLayoutModel();
738: LayoutInterval interval = component
739: .getLayoutInterval(dimension);
740: Object layoutUndoMark = layoutModel.getChangeMark();
741: javax.swing.undo.UndoableEdit ue = layoutModel
742: .getUndoableEdit();
743: boolean autoUndo = true;
744: try {
745: layoutModel.setIntervalSize(interval, interval
746: .getMinimumSize(false), newValue.intValue(),
747: interval.getMaximumSize(false));
748: getNodeReference().firePropertyChangeHelper(getName(),
749: oldValue, newValue);
750: autoUndo = false;
751: } finally {
752: getFormModel().fireContainerLayoutChanged(
753: getParentContainer(), null, null, null);
754: if (!layoutUndoMark.equals(layoutModel.getChangeMark())) {
755: getFormModel().addUndoableEdit(ue);
756: }
757: if (autoUndo) {
758: getFormModel().forceUndoOfCompoundEdit();
759: }
760: }
761: }
762:
763: public Object getValue() {
764: int size = component.getLayoutInterval(dimension)
765: .getPreferredSize(false);
766: return new Integer(size);
767: }
768:
769: @Override
770: public boolean supportsDefaultValue() {
771: return true;
772: }
773:
774: @Override
775: public void restoreDefaultValue() {
776: setValue(new Integer(LayoutConstants.NOT_EXPLICITLY_DEFINED));
777: }
778:
779: @Override
780: public boolean isDefaultValue() {
781: return ((Integer) getValue()).intValue() == LayoutConstants.NOT_EXPLICITLY_DEFINED;
782: }
783:
784: @Override
785: public PropertyEditor getPropertyEditor() {
786: return new PropertyEditorSupport() {
787: private String notExplicitelyDefined = FormUtils
788: .getBundleString("VALUE_SizeNotExplicitelyDefined"); // NOI18N
789:
790: @Override
791: public String[] getTags() {
792: return new String[] { notExplicitelyDefined };
793: }
794:
795: @Override
796: public String getAsText() {
797: Integer value = (Integer) getValue();
798: if (value.intValue() == LayoutConstants.NOT_EXPLICITLY_DEFINED) {
799: return notExplicitelyDefined;
800: } else {
801: return value.toString();
802: }
803: }
804:
805: @Override
806: public void setAsText(String str) {
807: if (notExplicitelyDefined.equals(str)) {
808: setValue(new Integer(
809: LayoutConstants.NOT_EXPLICITLY_DEFINED));
810: } else {
811: try {
812: setValue(new Integer(Integer.parseInt(str)));
813: } catch (NumberFormatException e) {
814: } // ignore
815: }
816: }
817: };
818: }
819:
820: @Override
821: public boolean canWrite() {
822: return !isReadOnly();
823: }
824:
825: }
826:
827: /**
828: * Property that determines whether the component should be resizable.
829: */
830: private class LayoutComponentResizableProperty extends
831: PropertySupport.ReadWrite {
832: private LayoutComponent component;
833: private int dimension;
834:
835: private LayoutComponentResizableProperty(
836: LayoutComponent component, int dimension) {
837: super (
838: dimension == LayoutConstants.HORIZONTAL ? PROP_LAYOUT_COMPONENT_HORIZONTAL_RESIZABLE
839: : PROP_LAYOUT_COMPONENT_VERTICAL_RESIZABLE,
840: Boolean.class, null, null);
841: boolean horizontal = dimension == LayoutConstants.HORIZONTAL;
842: setDisplayName(FormUtils
843: .getBundleString(horizontal ? "PROP_LAYOUT_COMPONENT_HORIZONTAL_RESIZABLE"
844: : "PROP_LAYOUT_COMPONENT_VERTICAL_RESIZABLE")); // NOI18N
845: setShortDescription(FormUtils
846: .getBundleString(horizontal ? "HINT_LAYOUT_COMPONENT_HORIZONTAL_RESIZABLE"
847: : "HINT_LAYOUT_COMPONENT_VERTICAL_RESIZABLE")); // NOI18N
848: this .component = component;
849: this .dimension = dimension;
850: }
851:
852: public void setValue(Object value) {
853: if (!(value instanceof Boolean))
854: throw new IllegalArgumentException();
855:
856: Boolean oldValue = (Boolean) getValue();
857: Boolean newValue = (Boolean) value;
858: boolean resizable = newValue.booleanValue();
859: LayoutModel layoutModel = getFormModel().getLayoutModel();
860: LayoutInterval interval = component
861: .getLayoutInterval(dimension);
862: Object layoutUndoMark = layoutModel.getChangeMark();
863: javax.swing.undo.UndoableEdit ue = layoutModel
864: .getUndoableEdit();
865: boolean autoUndo = true;
866: try {
867: layoutModel
868: .setIntervalSize(
869: interval,
870: resizable ? LayoutConstants.NOT_EXPLICITLY_DEFINED
871: : LayoutConstants.USE_PREFERRED_SIZE,
872: interval.getPreferredSize(false),
873: resizable ? Short.MAX_VALUE
874: : LayoutConstants.USE_PREFERRED_SIZE);
875: getNodeReference().firePropertyChangeHelper(getName(),
876: oldValue, newValue);
877: autoUndo = false;
878: } finally {
879: getFormModel().fireContainerLayoutChanged(
880: getParentContainer(), null, null, null);
881: if (!layoutUndoMark.equals(layoutModel.getChangeMark())) {
882: getFormModel().addUndoableEdit(ue);
883: }
884: if (autoUndo) {
885: getFormModel().forceUndoOfCompoundEdit();
886: }
887: }
888: }
889:
890: public Object getValue() {
891: int pref = component.getLayoutInterval(dimension)
892: .getPreferredSize(false);
893: int max = component.getLayoutInterval(dimension)
894: .getMaximumSize(false);
895: return Boolean.valueOf((max != pref)
896: && (max != LayoutConstants.USE_PREFERRED_SIZE));
897: }
898:
899: @Override
900: public boolean supportsDefaultValue() {
901: return true;
902: }
903:
904: @Override
905: public void restoreDefaultValue() {
906: setValue(Boolean.FALSE);
907: }
908:
909: @Override
910: public boolean isDefaultValue() {
911: return getValue().equals(Boolean.FALSE);
912: }
913:
914: @Override
915: public boolean canWrite() {
916: return !isReadOnly();
917: }
918:
919: }
920:
921: }
|