001/* 002 * Copyright (c) 2004-2007 by Michael Connor. All Rights Reserved. 003 * 004 * Redistribution and use in source and binary forms, with or without 005 * modification, are permitted provided that the following conditions are met: 006 * 007 * o Redistributions of source code must retain the above copyright notice, 008 * this list of conditions and the following disclaimer. 009 * 010 * o Redistributions in binary form must reproduce the above copyright notice, 011 * this list of conditions and the following disclaimer in the documentation 012 * and/or other materials provided with the distribution. 013 * 014 * o Neither the name of FormLayoutBuilder or Michael Connor nor the names of 015 * its contributors may be used to endorse or promote products derived 016 * from this software without specific prior written permission. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 020 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 021 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 022 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 023 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 024 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 025 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 026 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 027 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.mlc.swing.layout; 031 032import java.awt.Component; 033import java.beans.BeanInfo; 034import java.beans.IntrospectionException; 035import java.beans.Introspector; 036import java.beans.PropertyDescriptor; 037import java.lang.reflect.InvocationTargetException; 038import java.lang.reflect.Method; 039import java.util.ArrayList; 040import java.util.HashMap; 041import java.util.List; 042import java.util.Map; 043 044import javax.swing.JPanel; 045 046/** 047 * This is meant to be subclassed when you want to create a ComponentBuilder 048 * that has simplistic behavior. 049 * 050 * @author Michael Connor mlconnor@yahoo.com 051@version $Id$ 052@since Ptolemy II 8.0 053 */ 054public class DefaultComponentBuilder implements ComponentBuilder { 055 Class clazz; 056 057 BeanInfo beanInfo; 058 059 List<PropertyDescriptor> editableProperties = new ArrayList<PropertyDescriptor>(); 060 061 Map<String, PropertyDescriptor> nameToDescriptor = new HashMap<String, PropertyDescriptor>(); 062 063 List<BeanProperty> properties = new ArrayList<BeanProperty>(); 064 065 /** Creates a new instance of DefaultComponentFactory */ 066 public DefaultComponentBuilder(Class clazz) throws IntrospectionException { 067 this(clazz, null); 068 } 069 070 /** Creates a new instance of DefaultComponentFactory */ 071 public DefaultComponentBuilder(Class clazz, String[] properties) 072 throws IntrospectionException { 073 this.clazz = clazz; 074 075 beanInfo = Introspector.getBeanInfo(clazz); 076 PropertyDescriptor[] propertyDescriptors = beanInfo 077 .getPropertyDescriptors(); 078 079 if (properties != null) { 080 for (String propertyName : properties) { 081 PropertyDescriptor propertyDescriptor = null; 082 083 for (PropertyDescriptor thisDescriptor : propertyDescriptors) { 084 if (thisDescriptor.getName().equals(propertyName)) { 085 propertyDescriptor = thisDescriptor; 086 break; 087 } 088 } 089 090 if (propertyDescriptor == null) { 091 throw new RuntimeException("Could not find property '" 092 + propertyName + "' in class " + clazz.getName()); 093 } else { 094 this.properties 095 .add(new BeanProperty(propertyDescriptor.getName(), 096 propertyDescriptor.getPropertyType())); 097 nameToDescriptor.put(propertyDescriptor.getName(), 098 propertyDescriptor); 099 } 100 } 101 } 102 } 103 104 @Override 105 public String getDeclaration(String name, 106 Map<String, Object> beanProperties) { 107 StringBuffer buffer = new StringBuffer(); 108 buffer.append(clazz.getName() + " " + name + " = new " + clazz.getName() 109 + "("); 110 111 if (beanProperties.containsKey("text")) { 112 buffer.append("\"" + (String) beanProperties.get("text") + "\""); 113 } 114 115 buffer.append(");\n"); 116 return buffer.toString(); 117 } 118 119 @Override 120 public ComponentDef getComponentDef(String name, 121 Map<String, Object> beanProperties) { 122 // imports 123 // declarations 124 // add 125 126 String imp = "import " + clazz.getName() + ";"; 127 // does not work with JDK 1.4 128 // String decl = clazz.getSimpleName() + " ${name}= new " + clazz.getSimpleName() + "("; 129 String decl = clazz.getName() + " ${name}= new " + clazz.getName() 130 + "("; 131 132 if (beanProperties.containsKey("text")) { 133 decl += "\"" + (String) beanProperties.get("text") + "\""; 134 } 135 decl += ");"; 136 137 // String decl = getDeclaration(name, beanProperties); 138 String add = "${container}.add(${name}, \"${name}\");"; 139 140 ComponentDef cd = new ComponentDef(name, imp, decl, add); 141 return cd; 142 } 143 144 @Override 145 public java.awt.Component getInstance( 146 java.util.Map<String, Object> objectProperties) 147 throws InstantiationException, IllegalAccessException, 148 InvocationTargetException { 149 Object instance = clazz.newInstance(); 150 151 for (Object element : objectProperties.keySet()) { 152 String key = (String) element; 153 PropertyDescriptor propertyDescriptor = nameToDescriptor.get(key); 154 Object value = objectProperties.get(key); 155 Method writeMethod = propertyDescriptor.getWriteMethod(); 156 writeMethod.invoke(instance, new Object[] { value }); 157 } 158 159 return (Component) instance; 160 } 161 162 @Override 163 public boolean isComponentALayoutContainer() { 164 return clazz.equals(JPanel.class); 165 } 166 167 @Override 168 public String toString() { 169 return clazz.getName(); 170 } 171 172 @Override 173 public List<BeanProperty> getProperties() { 174 return properties; 175 } 176 177}