/******************************************************************************* * Copyright (c) 2000, 2003 Advanced Systems Concepts, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * David Orme (ASC) - Initial implementation ******************************************************************************/ package com.swtworkbench.community.xswt.layoutbuilder; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.LinkedList; import org.eclipse.swt.widgets.Widget; import com.swtworkbench.community.xswt.XSWT; import com.swtworkbench.community.xswt.XSWTException; import com.swtworkbench.community.xswt.dataparser.parsers.ClassDataParser; /** * Class SWTLayoutBuilder. The default ILayoutBuilder; constructs an actual * SWT UI from an XSWT file. * * @author daveo */ public class SWTLayoutBuilder extends LayoutBuilder { public SWTLayoutBuilder(XSWT xswt) { super(xswt); } /* (non-Javadoc) * @see com.swtworkbench.community.xswt.layoutbuilder.ILayoutBuilder#setProperty(java.lang.String, java.lang.Object, java.lang.String) */ public boolean setProperty(String propertyName, Object receiver, String valueSource, Object contextElement) throws XSWTException { Method[] setMethods = resolveAttributeSetMethod(receiver, propertyName, null); if (setMethods == null) return false; Exception lastException = null; for (Method method : setMethods) { Object value = parseData(valueSource, method.getParameterTypes()[0]); try { invokeMethod(propertyName, receiver, method, value); return true; } catch (Exception e) { lastException = e; } } throw new XSWTException("Error calling setter " + propertyName, lastException, contextElement); } private void invokeMethod(String propertyName, Object receiver, Method setter, Object value) throws IllegalAccessException, InvocationTargetException { fireSetProperty(receiver, propertyName, value, false); setter.invoke(receiver, new Object[] {value}); fireSetProperty(receiver, propertyName, value, true); } /* (non-Javadoc) * @see com.swtworkbench.community.xswt.layoutbuilder.ILayoutBuilder#setProperty(java.lang.reflect.Method, java.lang.Object, java.lang.Object) */ public void setProperty(Method setter, Object receiver, Object value, Object contextElement) throws XSWTException { try { invokeMethod(setter.getName(), receiver, setter, value); } catch (Throwable t) { throw new XSWTException("Error calling setter " + setter.getName(), t, contextElement); } } /* (non-Javadoc) * @see com.swtworkbench.community.xswt.layoutbuilder.ILayoutBuilder#setField(java.lang.String, java.lang.Object, java.lang.String) */ public boolean setField(String fieldName, Object receiver, String valueSource, Object contextElement) throws XSWTException { Field field = null; try { field = receiver.getClass().getField(fieldName); } catch (Throwable t) {} if (field == null) { return false; } try { Object value = parseData(valueSource, field.getType()); setFieldValue(fieldName, receiver, field, value); } catch (Exception e) { throw new XSWTException("Error setting field " + fieldName, e, contextElement); } return true; } private void setFieldValue(String fieldName, Object receiver, Field field, Object value) throws IllegalAccessException { fireSetProperty(receiver, fieldName, value, false); field.set(receiver, value); fireSetProperty(receiver, fieldName, value, true); } /* (non-Javadoc) * @see com.swtworkbench.community.xswt.layoutbuilder.ILayoutBuilder#setField(java.lang.reflect.Field, java.lang.Object, java.lang.Object) */ public void setField(Field field, Object receiver, Object value, Object contextElement) throws XSWTException { try { field.set(receiver, value); } catch (Throwable t) { throw new XSWTException("Error setting field " + field.getName(), t, contextElement); } } /* (non-Javadoc) * @see com.swtworkbench.community.xswt.layoutbuilder.ILayoutBuilder#construct(java.lang.String, org.eclipse.swt.widgets.Widget, java.lang.String) */ public Object construct(Class klass, Object parent, int style, String name, Object contextElement) throws XSWTException { Object result = getClassBuilder().constructControl(klass, parent, style); // If there's a name, this has to be a Widget, and set the name on it if (name != null && result instanceof Widget) { ((Widget) result).setData("Sweet_id", name); // Added Sweet_ to avoid naming conflicts } return result; } /* (non-Javadoc) * @see com.swtworkbench.community.xswt.layoutbuilder.ILayoutBuilder#construct(java.lang.Class, java.util.LinkedList) */ public Object construct(Class valueType, LinkedList argList, Object contextElement) throws XSWTException { // If there were no arguments, construct and return the new object if (argList.size() < 1) { try { if (valueType.isArray()) throw new XSWTException("Class array must declare an instance, try to add x:p0", contextElement); else return valueType.newInstance(); } catch (Exception e) { throw new XSWTException("Unable to create a newInstance() of " + valueType.getName(), e, contextElement); } } if (valueType.isArray()) { Object value = parseData((String)argList.get(0), valueType); //Object result = Array.newInstance(valueType, value.length); return value; } // Try to match a constructor to the arguments we've got ConstructorInfo constructorInfo = getConstructorInfo(ClassDataParser.getObjectClass(valueType), argList); // Make sure we actually found an appropriate constructor if (constructorInfo.constructor == null || constructorInfo.args == null) throw new XSWTException("Unable to locate a constructor for type " + valueType.getName() +" with " + argList.size() + " parameters.", contextElement); // Construct and return the object try { return constructorInfo.constructor.newInstance(constructorInfo.args); } catch (Exception e) { String paramTypeStr = ""; if (constructorInfo.paramTypes != null) { paramTypeStr = "(" + constructorInfo.paramTypes[0].getName(); for (int i = 1; i < constructorInfo.paramTypes.length; i++) { paramTypeStr += ", " + constructorInfo.paramTypes[i].getName(); } paramTypeStr += ")"; } throw new XSWTException("Unable to invoke constructor with parameters of type: " + paramTypeStr, e, contextElement); } } /* (non-Javadoc) * @see com.swtworkbench.community.xswt.layoutbuilder.ILayoutBuilder#getClass(java.lang.Object) */ public Class getClass(Object obj) throws XSWTException { // In this case we're constructing real objects, so just delegate to the object's // own getClass() method return obj.getClass(); } /* (non-Javadoc) * @see com.swtworkbench.community.xswt.layoutbuilder.ILayoutBuilder#getProperty(java.lang.reflect.Method, java.lang.Object, java.lang.Object) */ public Object getProperty(Method getter, Object receiver, Object value, Object contextElement) throws XSWTException { try { if (value == null) return getter.invoke(receiver, null); else return getter.invoke(receiver, new Object[] {value}); } catch (Throwable t) { throw new XSWTException("Error calling getter " + getter.getName(), t, contextElement); } } }