001: package net.xoetrope.builder.editor.components;
002:
003: import java.beans.BeanInfo;
004: import java.beans.EventSetDescriptor;
005: import java.beans.IntrospectionException;
006: import java.beans.Introspector;
007: import java.beans.PropertyDescriptor;
008: import java.lang.reflect.InvocationTargetException;
009: import java.lang.reflect.Method;
010: import java.util.Hashtable;
011: import java.util.Vector;
012:
013: import java.awt.AWTEvent;
014: import java.awt.Color;
015: import java.awt.Component;
016: import java.awt.Container;
017: import java.awt.Font;
018: import java.awt.event.FocusEvent;
019:
020: import net.xoetrope.builder.editor.XPageResource;
021: import net.xoetrope.debug.DebugLogger;
022: import net.xoetrope.xui.XPage;
023: import net.xoetrope.xui.XProjectManager;
024: import net.xoetrope.xui.data.XDataBinding;
025: import net.xoetrope.xui.data.XTextBinding;
026: import net.xoetrope.xui.style.XStyle;
027: import net.xoetrope.xui.validation.XValidationHandler;
028: import net.xoetrope.xui.validation.XValidator;
029: import net.xoetrope.builder.editor.XEditorProjectManager;
030: import net.xoetrope.builder.editor.XEditorResourceManager;
031: import java.awt.Image;
032: import net.xoetrope.xui.XAttributedComponent;
033: import net.xoetrope.xui.XImageHolder;
034: import java.net.URL;
035: import net.xoetrope.xui.build.BuildProperties;
036: import net.xoetrope.builder.editor.components.swing.XComponentProxy;
037: import net.xoetrope.xui.data.XRadioBinding;
038: import net.xoetrope.xui.data.XModel;
039:
040: /**
041: * A helper class to describe the properties of an individual component
042: * <p>Copyright (c) Xoetrope Ltd., 2002-2003</p>
043: * <p> $Revision: 1.19 $</p>
044: */
045: public abstract class PropertyHelper {
046: public final static int PLAIN_PROPERTY = 0;
047: public final static int STYLE_PROPERTY = 1;
048: public final static int EVENT_HANDLER_PROPERTY = 2;
049: public final static int IMAGE_NAME_PROPERTY = 3;
050: public final static int LIST_PROPERTY = 4;
051: public final static int VALIDATION_PROPERTY = 5;
052: public final static int BOOLEAN_PROPERTY = 6;
053: public final static int DATA_PROPERTY = 7;
054: public final static int INTEGER_PROPERTY = 8;
055: public final static int DOUBLE_PROPERTY = 9;
056:
057: protected final static String propertyName[] = { "Type", "Name",
058: "X", "Y", "W", "H", "Style" };
059: protected final static int numBasicProperties = propertyName.length;
060: public final static int PROP_NAME = 1;
061:
062: protected static Hashtable propertyTypes, eventMasks;
063:
064: protected Hashtable optionSets;
065:
066: protected String extraPropertyNames[];
067: protected boolean usesContentFile;
068: protected boolean allowsChildren;
069: protected boolean restrictsSize;
070: protected boolean isSwing;
071:
072: protected String className;
073: protected String componentType;
074:
075: protected PropertyDescriptor reflectedProperties[];
076: protected EventSetDescriptor reflectedEvents[];
077:
078: protected String[] extensions = { "xml" };
079: protected String fileTypeDesc = "XML Files";
080: protected String defExt = "xml";
081:
082: public PropertyHelper() {
083: isSwing = true;
084: optionSets = new Hashtable();
085: usesContentFile = allowsChildren = restrictsSize = false;
086: if (propertyTypes == null) {
087: propertyTypes = new Hashtable();
088: propertyTypes.put("Content", new Integer(PLAIN_PROPERTY));
089: propertyTypes.put("Alignment", new Integer(LIST_PROPERTY));
090: propertyTypes.put("HorizontalAlignment", new Integer(
091: LIST_PROPERTY));
092: propertyTypes.put("VerticalAlignment", new Integer(
093: LIST_PROPERTY));
094: propertyTypes.put("ActionHandler", new Integer(
095: EVENT_HANDLER_PROPERTY));
096: propertyTypes.put("ItemHandler", new Integer(
097: EVENT_HANDLER_PROPERTY));
098: propertyTypes.put("FocusHandler", new Integer(
099: EVENT_HANDLER_PROPERTY));
100: propertyTypes.put("MouseHandler", new Integer(
101: EVENT_HANDLER_PROPERTY));
102: propertyTypes.put("Data", new Integer(DATA_PROPERTY));
103: propertyTypes.put("DestinationData", new Integer(
104: DATA_PROPERTY));
105: propertyTypes.put("TextData", new Integer(DATA_PROPERTY));
106: propertyTypes.put("SelectionData", new Integer(
107: DATA_PROPERTY));
108: propertyTypes.put("FocusHandler", new Integer(
109: EVENT_HANDLER_PROPERTY));
110: propertyTypes.put("KeyHandler", new Integer(
111: EVENT_HANDLER_PROPERTY));
112: propertyTypes.put("Validation", new Integer(
113: VALIDATION_PROPERTY));
114: propertyTypes.put("ImageName", new Integer(
115: IMAGE_NAME_PROPERTY));
116: propertyTypes.put("Opaque", new Integer(BOOLEAN_PROPERTY));
117: propertyTypes.put("resource", new Integer(PLAIN_PROPERTY));
118: propertyTypes.put("HorizontalScrollbar", new Integer(
119: LIST_PROPERTY));
120: propertyTypes.put("VerticalScrollbar", new Integer(
121: LIST_PROPERTY));
122: propertyTypes.put("SelectionHandler", new Integer(
123: EVENT_HANDLER_PROPERTY));
124: propertyTypes.put("Rows", new Integer(PLAIN_PROPERTY));
125: propertyTypes.put("Columns", new Integer(PLAIN_PROPERTY));
126: propertyTypes.put("Wrap", new Integer(BOOLEAN_PROPERTY));
127: propertyTypes
128: .put("WordWrap", new Integer(BOOLEAN_PROPERTY));
129:
130: eventMasks = new Hashtable();
131: eventMasks.put("ActionHandler", new Long(
132: AWTEvent.ACTION_EVENT_MASK));
133: eventMasks.put("ItemHandler", new Long(
134: AWTEvent.ITEM_EVENT_MASK));
135: eventMasks.put("FocusHandler", new Long(
136: AWTEvent.FOCUS_EVENT_MASK));
137: eventMasks.put("KeyHandler", new Long(
138: AWTEvent.KEY_EVENT_MASK));
139: eventMasks.put("SelectionHandler", new Long(
140: AWTEvent.ITEM_EVENT_MASK));
141: eventMasks.put("MouseHandler", new Long(
142: AWTEvent.MOUSE_EVENT_MASK));
143: eventMasks.put("MouseMotionHandler", new Long(
144: AWTEvent.MOUSE_MOTION_EVENT_MASK));
145: eventMasks.put("TextHandler", new Long(
146: AWTEvent.TEXT_EVENT_MASK));
147: }
148: }
149:
150: /**
151: * Add a property type if it is not already present
152: * @param name the name of the new property
153: * @param type the property type
154: * @return true if successfully added, otherwise false (if it already exists)
155: */
156: public boolean addPropertyType(String name, Object type) {
157: if (propertyTypes.get(name) == null) {
158: propertyTypes.put(name, type);
159: return true;
160: }
161:
162: return false;
163: }
164:
165: /**
166: * Gets the className of the soure component. If the name has not been explicitly
167: * set the class name of this helper is used and the name is truncated to
168: * remove the 'Helper' part.
169: * @return the class name of the source component
170: */
171: public String getClassName() {
172: if (className == null) {
173: className = getClass().toString();
174: className = className.substring(0, className.length() - 7);
175: }
176: return className;
177: }
178:
179: public String getComponentType() {
180: return componentType;
181: }
182:
183: protected final static String booleanOptions[] = { "true", "false" };
184:
185: /**
186: * Get the number of properties that the component exposes
187: * @return the number of propeties
188: */
189: public int getNumProperties() {
190: return propertyName.length
191: + (reflectedProperties != null ? reflectedProperties.length
192: : 0)
193: + (reflectedEvents != null ? reflectedEvents.length : 0)
194: + (extraPropertyNames == null ? 0
195: : extraPropertyNames.length);
196: }
197:
198: /**
199: * Get the number of basic properties that every component exposes
200: * @return the number of propeties
201: */
202: public int getNumBasicProperties() {
203: return propertyName.length;
204: }
205:
206: /**
207: * Get the name of the property
208: * @param i the property index
209: * @param pageResource the page resource to which this component belongs
210: * @param comp the component instance
211: * @return the name
212: */
213: public String getPropertyName(XPageResource pageResource,
214: Component comp, int i) {
215: if (i < numBasicProperties)
216: return propertyName[i];
217: else {
218: int numExtraProperties = 0;
219: if (extraPropertyNames != null) {
220: numExtraProperties = extraPropertyNames.length;
221: if (i < (numBasicProperties + numExtraProperties))
222: return extraPropertyNames[i - numBasicProperties];
223: }
224:
225: int numReflectedProperties = 0;
226: if (reflectedProperties != null) {
227: numReflectedProperties = reflectedProperties.length;
228: if (i < (numBasicProperties + numExtraProperties + numReflectedProperties))
229: return reflectedProperties[i
230: - (numBasicProperties + numExtraProperties)]
231: .getName();
232: }
233:
234: if (reflectedEvents != null)
235: return reflectedEvents[i
236: - (numBasicProperties + numExtraProperties + numReflectedProperties)]
237: .getName();
238: }
239: return null;
240: }
241:
242: /**
243: * Get the type of the property
244: * @param i the property index
245: * @return the type as defined by XPropertiesEditor
246: */
247: public int getPropertyType(int i) {
248: if (i == 6)
249: return STYLE_PROPERTY;
250: else if ((i >= numBasicProperties)
251: && (i < numBasicProperties + extraPropertyNames.length)) {
252: String propertyName = getPropertyName(null, null, i);
253: if (propertyName.equals("Content") && usesContentFile)
254: return IMAGE_NAME_PROPERTY;
255: Object obj = propertyTypes.get(propertyName);
256: if (obj != null)
257: return ((Integer) obj).intValue();
258: }
259:
260: return PLAIN_PROPERTY;
261: }
262:
263: /**
264: * Get the value of the property exposed by the component
265: * @param pageResource the page resource to which this component belongs
266: * @param comp the component instance
267: * @param i the component property index
268: * @return the value
269: */
270: public String getPropertyValue(XPageResource pageResource,
271: Component comp, int i) {
272: if (i < numBasicProperties) {
273: switch (i) {
274: case 0: {
275: String s = getComponentType();
276: if (s == null)
277: comp.getClass().toString();
278: int idx = s.lastIndexOf('.');
279: return s.substring(idx + 1);
280: }
281: case 1:
282: return comp.getName();
283: case 2:
284: return new Integer(comp.getLocation().x).toString();
285: case 3:
286: return new Integer(comp.getLocation().y).toString();
287: case 4:
288: return new Integer(comp.getSize().width).toString();
289: case 5:
290: return new Integer(comp.getSize().height).toString();
291: case 6:
292: return pageResource.getStyleName(comp);
293: }
294: } else {
295: int numExtraProperties = 0;
296: if (extraPropertyNames != null) {
297: numExtraProperties = extraPropertyNames.length;
298: if (i < (numBasicProperties + numExtraProperties)) {
299: int propertyType = getPropertyType(i);
300: if (propertyType == LIST_PROPERTY)
301: return getListPropertyValue(comp, i);
302: else if (propertyType == EVENT_HANDLER_PROPERTY)
303: return pageResource.getCtlEvent(comp,
304: getEventMask(i));
305: else if (propertyType == DATA_PROPERTY)
306: return getData(pageResource, comp, i);
307: else if (propertyType == IMAGE_NAME_PROPERTY) {
308: Object obj = getViaReflection(
309: extraPropertyNames[i
310: - numBasicProperties], comp,
311: false);
312: if (obj == null)
313: return null;
314: return (String) obj;
315: } else if (propertyType == VALIDATION_PROPERTY)
316: return getValidation(comp);
317: else if (extraPropertyNames[i - numBasicProperties]
318: .equals("Content"))
319: return (String) getViaReflection(
320: usesContentFile ? "FileName" : "Text",
321: comp, false);
322: else if (comp instanceof XPage)
323: return pageResource
324: .getPageAttribute(extraPropertyNames[i
325: - numBasicProperties]);
326: else {
327: Object obj = getViaReflection(
328: extraPropertyNames[i
329: - numBasicProperties], comp,
330: (propertyType == BOOLEAN_PROPERTY));
331: if (obj == null)
332: return null;
333:
334: if (propertyType == BOOLEAN_PROPERTY)
335: return ((Boolean) obj).toString();
336: else if (propertyType == INTEGER_PROPERTY)
337: return ((Integer) obj).toString();
338: else if (propertyType == DOUBLE_PROPERTY)
339: return ((Double) obj).toString();
340: else
341: //if ( propertyType == STYLE_PROPERTY )
342: return (String) obj;
343: }
344: }
345: }
346:
347: int numReflectedProperties = 0;
348: if (reflectedProperties != null) {
349: numReflectedProperties = reflectedProperties.length;
350: if (i < (numBasicProperties + numExtraProperties + numReflectedProperties)) {
351: try {
352: Method method = reflectedProperties[i
353: - (numBasicProperties + numExtraProperties)]
354: .getReadMethod();
355: Object args[] = {};
356: Object result = null;
357: if (method != null)
358: result = method.invoke(comp, args);
359: if (result == null)
360: return null;
361: return result.toString();
362: } catch (IllegalAccessException ex) {
363: return null;
364: } catch (IllegalArgumentException ex) {
365: return null;
366: } catch (InvocationTargetException ex) {
367: return null;
368: }
369: }
370: }
371:
372: if (reflectedEvents != null) {
373: try {
374: Method methods[] = reflectedEvents[i
375: - (numBasicProperties + numExtraProperties + numReflectedProperties)]
376: .getListenerMethods();
377: if (methods.length == 0) {
378: return "";
379: }
380: Object args[] = {};
381: return methods[0].getName();
382: } catch (Exception ex1) {
383: return null;
384: }
385: }
386: }
387: return null;
388: }
389:
390: /**
391: * Set the value of the property exposed by the component
392: * @param pageResource the page resource to which this component belongs
393: * @param comp the component instance
394: * @param i the component property index
395: * @return the value
396: */
397: public void setPropertyValue(XPageResource pageResource,
398: Component comp, int i, String value) {
399: if (i < numBasicProperties) {
400: switch (i) {
401: case 0:
402: break;
403: case 1:
404: comp.setName(value);
405: break;
406: case 2:
407: comp.setLocation(new Integer(value).intValue(), comp
408: .getLocation().y);
409: break;
410: case 3:
411: comp.setLocation(comp.getLocation().x, new Integer(
412: value).intValue());
413: break;
414: case 4:
415: comp.setSize(new Integer(value).intValue(), comp
416: .getSize().height);
417: break;
418: case 5:
419: comp.setSize(comp.getSize().width, new Integer(value)
420: .intValue());
421: break;
422: case 6: {
423: pageResource.setStyleName(comp, value);
424:
425: XStyle style = XProjectManager.getStyleManager()
426: .getStyle(value);
427: if (style != null) {
428: int fontStyle = 0;
429: if (style.getStyleAsInt(XStyle.FONT_WEIGHT) == 1)
430: fontStyle = Font.BOLD;
431: if (style.getStyleAsInt(XStyle.FONT_ITALIC) == 1)
432: fontStyle = fontStyle | Font.ITALIC;
433: int fontSize = style
434: .getStyleAsInt(XStyle.FONT_SIZE);
435: if (fontSize == 0)
436: fontSize = 10;
437:
438: Font font = new Font(style
439: .getStyleAsString(XStyle.FONT_FACE),
440: fontStyle, fontSize);
441:
442: Color fgColor = style
443: .getStyleAsColor(XStyle.COLOR_FORE);
444: Color bkColor = style
445: .getStyleAsColor(XStyle.COLOR_BACK);
446:
447: comp.setForeground(fgColor);
448: comp.setBackground(bkColor);
449: comp.setFont(font);
450: }
451: }
452: break;
453: }
454: } else {
455: int numExtraProperties = 0;
456: if (extraPropertyNames != null) {
457: numExtraProperties = extraPropertyNames.length;
458: if (i < (numBasicProperties + numExtraProperties)) {
459: int propertyType = getPropertyType(i);
460: if (propertyType == DATA_PROPERTY)
461: setData(pageResource, comp, getPropertyName(
462: pageResource, comp, i), value);
463: else if (propertyType == VALIDATION_PROPERTY)
464: setValidation(comp, value);
465: else if (propertyType == IMAGE_NAME_PROPERTY)
466: setImageName(pageResource, comp, i, value);
467: else if (extraPropertyNames[i - numBasicProperties]
468: .equals("Content"))
469: setViaReflection(usesContentFile ? "FileName"
470: : "Text", comp, value, false);
471: else if (comp instanceof XPage)
472: pageResource.setPageAttribute(
473: extraPropertyNames[i
474: - numBasicProperties], value);
475: else if (propertyType == BOOLEAN_PROPERTY)
476: setViaReflection(extraPropertyNames[i
477: - numBasicProperties], comp, Boolean
478: .valueOf(value), true);
479: else if (propertyType == INTEGER_PROPERTY)
480: setViaReflection(extraPropertyNames[i
481: - numBasicProperties], comp, Integer
482: .valueOf(value), int.class);
483: else if (propertyType == DOUBLE_PROPERTY)
484: setViaReflection(extraPropertyNames[i
485: - numBasicProperties], comp, Double
486: .valueOf(value), double.class);
487: else if (propertyType == STYLE_PROPERTY)
488: setViaReflection(extraPropertyNames[i
489: - numBasicProperties], comp, String
490: .valueOf(value), String.class);
491: return;
492: }
493: }
494: int numReflectedProperties = 0;
495: if (reflectedProperties != null) {
496: numReflectedProperties = reflectedProperties.length;
497: if (i < (numBasicProperties + numExtraProperties + numReflectedProperties)) {
498: try {
499: Method setter = reflectedProperties[i
500: - propertyName.length].getWriteMethod();
501: Object args[] = { value };
502: args[0] = value;
503: setter.invoke(comp, args);
504: return;
505: } catch (IllegalAccessException ex) {
506: } catch (IllegalArgumentException ex) {
507: } catch (InvocationTargetException ex) {
508: }
509: }
510: }
511:
512: if (reflectedEvents != null) {
513: try {
514: Method adder = reflectedEvents[i
515: - (propertyName.length + reflectedProperties.length)]
516: .getAddListenerMethod();
517: Object args[] = { value };
518: args[0] = value;
519: adder.invoke(comp, args);
520: } catch (IllegalAccessException ex1) {
521: } catch (IllegalArgumentException ex1) {
522: } catch (InvocationTargetException ex1) {
523: }
524: }
525: }
526: }
527:
528: /**
529: * Set the value of the property exposed by the component
530: * @param comp the component instance
531: * @param i the component property index
532: * @param selIdx the index into the list of the selected item
533: * @return the value
534: */
535: public void setListPropertyValue(Component comp, int i, int selIdx) {
536: if (getPropertyType(i) == BOOLEAN_PROPERTY)
537: setPropertyValue(null, comp, i, booleanOptions[selIdx]);
538: else {
539: String property = getPropertyName(null, null, i);
540: OptionSet os = (OptionSet) optionSets.get(property);
541: if (os != null) {
542: try {
543: Class params[] = new Class[1];
544: params[0] = int.class;
545: Component target = comp;
546: if (comp instanceof XComponentProxy)
547: target = ((XComponentProxy) comp)
548: .getProxiedComponent();
549: Method method = target.getClass().getMethod(
550: "set" + os.property, params);
551: Object args[] = new Object[1];
552: args[0] = new Integer(os.ids[selIdx]);
553: method.invoke(target, args);
554: } catch (Exception ex) {
555: ex.printStackTrace();
556: }
557: }
558: }
559: }
560:
561: protected String getListPropertyValue(Component comp, int i) {
562: String property = getPropertyName(null, null, i);
563: OptionSet os = (OptionSet) optionSets.get(property);
564: if (os != null) {
565: try {
566: Class params[] = new Class[0];
567: Component target = comp;
568: if (comp instanceof XComponentProxy)
569: target = ((XComponentProxy) comp)
570: .getProxiedComponent();
571: Method method = target.getClass().getMethod(
572: "get" + os.property, params);
573: Object args[] = new Object[0];
574: int rc = ((Integer) method.invoke(target, args))
575: .intValue();
576: for (int idx = 0; idx < os.ids.length; idx++) {
577: if (os.ids[idx] == rc)
578: return os.options[idx];
579: }
580: } catch (Exception ex) {
581: ex.printStackTrace();
582: }
583: }
584: return null;
585: }
586:
587: /**
588: * Get the event mask attribute
589: * @param i the component property index
590: * @return the value
591: */
592: public long getEventMask(int i) {
593: String eventName = getPropertyName(null, null, i);
594: Object obj = eventMasks.get(eventName);
595: if (obj != null)
596: return ((Long) obj).longValue();
597:
598: return 0l;
599: }
600:
601: /**
602: * Get the items to display for a list property
603: * @param i the property index
604: * @return an array of list items
605: */
606: public String[] getListItems(int i) {
607: if (getPropertyType(i) == BOOLEAN_PROPERTY)
608: return booleanOptions;
609: else {
610: String property = getPropertyName(null, null, i);
611: OptionSet os = (OptionSet) optionSets.get(property);
612: if (os != null)
613: return os.options;
614: }
615:
616: return null;
617: }
618:
619: /**
620: * Get the first validation for this component
621: * @param comp the component reference
622: * @return the first validation
623: */
624: public String getValidation(Component comp) {
625: Container page = comp.getParent();
626: while (!(page instanceof XPage))
627: page = page.getParent();
628:
629: XValidationHandler handler = ((XPage) page)
630: .getValidationHandler();
631: if (handler != null) {
632: Vector validations = handler.getValidations(comp);
633: if (validations != null) {
634: int size = validations.size();
635: for (int j = 0; j < size; j++)
636: if (validations.elementAt(j) instanceof XValidator)
637: return ((XValidator) validations.elementAt(j))
638: .getName();
639: }
640: }
641:
642: return "[None]";
643: }
644:
645: /**
646: * Set the validation rule for this component
647: * @param comp the component reference
648: * @param ruleName the name of the validation rule
649: */
650: public void setValidation(Component comp, String ruleName) {
651: if ((ruleName == null) || (ruleName.compareTo("[None]") == 0))
652: return;
653:
654: Container page = comp.getParent();
655: while (!(page instanceof XPage))
656: page = page.getParent();
657:
658: ((XPage) page).addValidation(comp, ruleName, null,
659: FocusEvent.FOCUS_LOST);
660: }
661:
662: /**
663: * Set the image name property.
664: * @param page the page that owns the component
665: * @param comp the component whose property is being set
666: * @param propertyIdx teh index of the property
667: * @param imageName the path to the image
668: */
669: public void setImageName(XPageResource pageResource,
670: Component comp, int propertyIdx, String imageName) {
671: XEditorResourceManager rm = ((XEditorResourceManager) XEditorProjectManager
672: .getCurrentProject().getResourceManager());
673: Image image = rm.getImage(imageName);
674: setViaReflection("Image", comp, image, Image.class);
675: ((XAttributedComponent) comp)
676: .setAttribute("content", imageName);
677: }
678:
679: public String getData(XPageResource pageResource, Component comp,
680: int i) {
681: XDataBinding binding = pageResource.getDataBinding(comp);
682: if (binding == null)
683: return "";
684:
685: String dataName = getPropertyName(null, null, i);
686: String res = null;
687: if (dataName.compareTo("DestinationData") == 0)
688: res = binding.getOutputPath();
689: else if ((dataName.compareTo("SelectionData") == 0)
690: && (binding instanceof XRadioBinding))
691: res = binding.getSourcePath();
692: else if ((dataName.compareTo("TextData") == 0)
693: && (binding instanceof XTextBinding))
694: res = binding.getSourcePath();
695: else if (dataName.compareTo("Data") == 0)
696: res = binding.getSourcePath();
697:
698: return res == null ? "" : res;
699: }
700:
701: public void setData(XPageResource pageResource, Component comp,
702: String propertyName, String value) {
703: XModel srcModel = (XModel) XProjectManager.getModel()
704: .get(value);
705: if (propertyName.compareTo("TextData") == 0)
706: setData(pageResource, comp, new XTextBinding(comp, value,
707: srcModel));
708: else if (propertyName.compareTo("SelectionData") == 0)
709: setData(pageResource, comp, new XRadioBinding(comp, value,
710: srcModel));
711: else
712: setData(pageResource, comp, new XTextBinding(comp, value,
713: srcModel));
714: }
715:
716: public void setData(XPageResource pageResource, Component comp,
717: XDataBinding binding) {
718: pageResource.addDataBinding(comp, binding);
719: }
720:
721: /**
722: * Check if this component allows children to be added.
723: * @return true to allow addition of children. By default false is returned
724: * as most components do not intend to allow addition of children
725: */
726: public boolean allowsChildren() {
727: return allowsChildren;
728: }
729:
730: /**
731: * Flag the component as having a restricted size if true is returned
732: * @return false
733: */
734: public boolean restrictsSize() {
735: return restrictsSize;
736: }
737:
738: /**
739: * Sets the flag to indicate if this is a swing component helper?
740: * @param iss true if it is a swing helper
741: */
742: public void setSwing(boolean iss) {
743: isSwing = iss;
744: }
745:
746: /**
747: * Is this a swing component helper?
748: * @return true if it is a swing helper
749: */
750: public boolean isSwing() {
751: return isSwing;
752: }
753:
754: // Setup the introspection----------------------------------------------------
755: public void setComponent(Component comp) {
756: try {
757: className = comp.getClass().getName();
758: if (className.indexOf(".swing.") > 0)
759: isSwing = true;
760:
761: Class clazz = (comp instanceof XComponentProxy ? ((XComponentProxy) comp)
762: .getProxiedComponent().getClass()
763: : comp.getClass());
764: BeanInfo bi = Introspector.getBeanInfo(clazz);
765: PropertyDescriptor props[] = bi.getPropertyDescriptors();
766: int numProps = 0;
767: for (int i = 0; i < props.length; i++) {
768: if ((props[i].getReadMethod() != null)
769: && (props[i].getWriteMethod() != null))
770: numProps++;
771: }
772:
773: reflectedProperties = new PropertyDescriptor[numProps];
774: int j = 0;
775: for (int i = 0; i < props.length; i++) {
776: if ((props[i].getReadMethod() != null)
777: && (props[i].getWriteMethod() != null))
778: reflectedProperties[j++] = props[i];
779: }
780: reflectedEvents = bi.getEventSetDescriptors();
781: } catch (IntrospectionException ex) {
782: DebugLogger.logError("Couldn't introspect property: "
783: + ex.getMessage());
784: }
785: }
786:
787: /**
788: * Get a property using refelction instead of the property helper.
789: * @param methodName the method name
790: * @param comp the component being modified
791: * @param isBoolean is it a boolean property being modified
792: * @return the property value
793: */
794: private Object getViaReflection(String methodName, Component comp,
795: boolean isBoolean) {
796: try {
797: Class params[] = new Class[0];
798: Component target = comp;
799: if (comp instanceof XComponentProxy)
800: target = ((XComponentProxy) comp).getProxiedComponent();
801: Method method = target.getClass().getMethod(
802: (isBoolean ? "is" : "get") + methodName, params);
803: Object args[] = {};
804: Object result = null;
805: if (method != null) {
806: return method.invoke(target, args);
807: }
808: } catch (NoSuchMethodException ex) {
809: if (BuildProperties.DEBUG)
810: DebugLogger.logWarning("No such method: "
811: + (isBoolean ? "is" : "get") + methodName);
812: } catch (Exception ex) {
813: ex.printStackTrace();
814: }
815: return null;
816: }
817:
818: /**
819: * Set a property using refelction instead of the property helper.
820: * @param methodName the method name
821: * @param comp the component being modified
822: * @param value the new value
823: * @param isBoolean is it a boolean property being modified
824: */
825: public void setViaReflection(String methodName, Component comp,
826: Object value, boolean isBoolean) {
827: try {
828: Class params[] = new Class[1];
829: params[0] = isBoolean ? boolean.class : value.getClass();
830: Component target = comp;
831: if (comp instanceof XComponentProxy)
832: target = ((XComponentProxy) comp).getProxiedComponent();
833: Method method = target.getClass().getMethod(
834: "set" + methodName, params);
835: Object args[] = new Object[1];
836: args[0] = value;
837: if (method != null) {
838: method.invoke(target, args);
839: }
840: } catch (Exception ex) {
841: ex.printStackTrace();
842: }
843: }
844:
845: /**
846: * Set a property using refelction instead of the property helper.
847: * @param methodName the method name
848: * @param comp the component being modified
849: * @param value the new value
850: * @param objectClass the class of the argument of the set method being invoked
851: */
852: public void setViaReflection(String methodName, Component comp,
853: Object value, Class objectClass) {
854: try {
855: Class params[] = new Class[1];
856: params[0] = objectClass;
857: Component target = comp;
858: if (comp instanceof XComponentProxy)
859: target = ((XComponentProxy) comp).getProxiedComponent();
860: Method method = target.getClass().getMethod(
861: "set" + methodName, params);
862: Object args[] = new Object[1];
863: args[0] = value;
864: if (method != null) {
865: method.invoke(target, args);
866: target.repaint();
867: }
868: } catch (Exception ex) {
869: ex.printStackTrace();
870: }
871: }
872:
873: /**
874: * Is the property read-only?
875: * @param obj the name of the selected property
876: * @return true if the property is read-only
877: */
878: public boolean isReadOnly(Object obj) {
879: if (obj.toString().compareTo("Type") == 0)
880: return true;
881: else
882: return false;
883: }
884:
885: // List option support--------------------------------------------------------
886: /**
887: * Set the list options
888: * @param name the name by which the list is identified
889: * @param property the property being modified
890: * @param options the list of option values
891: * @param ids the values associated with the options
892: */
893: public void setListOptions(String name, String property,
894: String[] options, int[] ids) {
895: optionSets.put(name, new OptionSet(property, options, ids));
896: }
897:
898: /**
899: * Calls the relevant component helper to set the attributes of a new component
900: * when a paste operation has been invoked from the main menu.
901: * @param srcComp the component which was selected when the copy or cut command
902: * was invoked
903: * @param targetComp the new component which will be added to the current page
904: */
905: public void setCopiedProperties(XPageResource page,
906: Component srcComp, Component targetComp) {
907: for (int i = 0; i < getNumProperties(); i++) {
908: if (this .getPropertyType(i) != this .DATA_PROPERTY) {
909: String propName = getPropertyName(page, srcComp, i);
910: setPropertyValue(page, targetComp, i, getPropertyValue(
911: page, srcComp, i));
912: }
913: }
914: if (getPropertyValue(page, srcComp, PROP_NAME) != null)
915: setPropertyValue(page, targetComp, PROP_NAME, "");
916: }
917:
918: /**
919: * Get the file extension set to be used for file/image names in the popup chooser
920: * @return an array of strings
921: */
922: public String[] getFileExtensions() {
923: return extensions;
924: }
925:
926: /**
927: * Get a description of the file extension set to be used for file/image names in the popup chooser
928: * @return an array of strings
929: */
930: public String getFileDescription() {
931: return fileTypeDesc;
932: }
933:
934: public String getDefaultExtension() {
935: return defExt;
936: }
937:
938: /**
939: * Set the array/list of extensions used by the file/image name chooser
940: * @param desc the description of the file type.
941: * @param defaultExt the default file extension
942: * @param newExtensions
943: */
944: public void setFileExtensions(String desc, String defaultExt,
945: String[] newExtensions) {
946: fileTypeDesc = desc;
947: defExt = defaultExt;
948: extensions = newExtensions;
949: }
950: }
951:
952: class OptionSet {
953: final String property;
954: final String[] options;
955: final int[] ids;
956:
957: public OptionSet(String _property, String[] _options, int[] _ids) {
958: property = _property;
959: options = _options;
960: ids = _ids;
961: }
962: }
|