1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.jelly.tags.swt;
17
18 import java.lang.reflect.Constructor;
19 import java.lang.reflect.InvocationTargetException;
20 import java.util.Map;
21
22 import org.apache.commons.jelly.JellyTagException;
23 import org.apache.commons.jelly.XMLOutput;
24 import org.apache.commons.jelly.tags.core.UseBeanTag;
25 import org.apache.commons.jelly.tags.swt.converters.ColorConverter;
26 import org.apache.commons.jelly.tags.swt.converters.PointConverter;
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.eclipse.swt.SWT;
30 import org.eclipse.swt.custom.ScrolledComposite;
31 import org.eclipse.swt.graphics.Color;
32 import org.eclipse.swt.graphics.Point;
33 import org.eclipse.swt.graphics.RGB;
34 import org.eclipse.swt.widgets.Control;
35 import org.eclipse.swt.widgets.Widget;
36
37 /***
38 * This tag creates an SWT widget based on the parent tag, optionally declaring
39 * this widget as a variable if the <i>var</i> attribute is specified.</p>
40 *
41 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
42 * @author <a href="mailto:ckl@dacelo.nl">Christiaan ten Klooster</a>
43 * @version 1.1
44 */
45 public class WidgetTag extends UseBeanTag {
46
47 /*** The Log to which logging calls will be made. */
48 private static final Log log = LogFactory.getLog(WidgetTag.class);
49
50 protected Widget parent;
51 private int style = SWT.NULL;
52
53 public WidgetTag(Class widgetClass) {
54 super(widgetClass);
55 }
56
57 public WidgetTag(Class widgetClass, int style) {
58 super(widgetClass);
59 this.style = style;
60 }
61
62 public String toString() {
63 return "WidgetTag[widget=" + getWidget() + "]";
64 }
65
66
67
68
69 /***
70 * @return the visible widget, if there is one.
71 */
72 public Widget getWidget() {
73 Object bean = getBean();
74 if (bean instanceof Widget) {
75 return (Widget) bean;
76 }
77 return null;
78 }
79
80 /***
81 * @return the parent widget which this widget will be added to.
82 */
83 public Widget getParentWidget() {
84
85 if (parent == null) {
86 WidgetTag tag = (WidgetTag) findAncestorWithClass(WidgetTag.class);
87 if (tag != null) {
88 return tag.getWidget();
89 }
90 }
91
92 return parent;
93 }
94
95
96
97 public void doTag(XMLOutput output) throws JellyTagException {
98 Map attributes = getAttributes();
99 Object parent = attributes.remove("parent");
100 if (parent != null) {
101 if (parent instanceof Widget) {
102 this.parent = (Widget) parent;
103 } else {
104 throw new JellyTagException(
105 "The parent attribute is not a Widget, it is of type: "
106 + parent.getClass().getName()
107 + " value: "
108 + parent);
109 }
110 }
111 super.doTag(output);
112 clearBean();
113 }
114
115
116
117
118 /***
119 * Factory method to create a new widget
120 */
121 protected Object newInstance(Class theClass, Map attributes, XMLOutput output)
122 throws JellyTagException {
123 int style = getStyle(attributes);
124
125
126 Widget parent = getParentWidget();
127
128 Widget widget = (Widget) createWidget(theClass, parent, style);
129 if (parent != null) {
130 attachWidgets(parent, widget);
131 }
132
133 return widget;
134 }
135
136
137
138
139 protected void setBeanProperties(Object bean, Map attributes) throws JellyTagException {
140
141 if (bean instanceof Control) {
142 Control control = (Control) bean;
143
144
145
146 Object size = attributes.remove("size");
147 setSize(control, size);
148
149
150
151 Object colorValue = attributes.remove("background");
152 Color background =
153 (colorValue instanceof Color)
154 ? (Color) colorValue : getColor(control, colorValue);
155 control.setBackground(background);
156
157 colorValue = attributes.remove("foreground");
158 Color foreground =
159 (colorValue instanceof Color)
160 ? (Color) colorValue : getColor(control, colorValue);
161 control.setForeground(foreground);
162 }
163
164 super.setBeanProperties(bean, attributes);
165 }
166
167 /***
168 * Get a color for the control
169 * @param control
170 * @param colorValue
171 */
172 protected Color getColor(Control control, Object colorValue) {
173 Color color = null;
174 if (colorValue != null) {
175 RGB rgb = null;
176 if (color instanceof Color) {
177 color = (Color) colorValue;
178 } else {
179 rgb = ColorConverter.getInstance().parse(colorValue.toString());
180 color = new Color(control.getDisplay(), rgb);
181 }
182 }
183 return color;
184 }
185
186 /***
187 * set the size of the control
188 * @param control
189 * @param size
190 */
191 protected void setSize(Control control, Object size) {
192 Point point = null;
193 if (size != null) {
194 if (size instanceof Point) {
195 point = (Point) size;
196 } else {
197 point = PointConverter.getInstance().parse(size.toString());
198 }
199 control.setSize(point);
200 }
201
202 }
203
204 /***
205 * Provides a strategy method to allow a new child widget to be attached to
206 * its parent
207 *
208 * @param parent is the parent widget which is never null
209 * @param widget is the new child widget to be attached to the parent
210 */
211 protected void attachWidgets(Object parent, Widget widget) throws JellyTagException {
212
213 if (parent instanceof ScrolledComposite && widget instanceof Control) {
214 ScrolledComposite scrolledComposite = (ScrolledComposite) parent;
215 scrolledComposite.setContent((Control) widget);
216 }
217 }
218
219 /***
220 * Factory method to create an instance of the given Widget class with
221 * the given parent and SWT style
222 *
223 * @param theClass is the type of widget to create
224 * @param parent is the parent widget
225 * @param style the SWT style code
226 * @return the new Widget
227 */
228 protected Object createWidget(Class theClass, Widget parent, int style)
229 throws JellyTagException {
230 if (theClass == null) {
231 throw new JellyTagException("No Class available to create the new widget");
232 }
233
234 try {
235 if (parent == null) {
236
237 Class[] types = { int.class };
238 Constructor constructor = theClass.getConstructor(types);
239 if (constructor != null) {
240 Object[] arguments = { new Integer(style)};
241 return constructor.newInstance(arguments);
242 }
243 } else {
244
245 Constructor[] constructors = theClass.getConstructors();
246 if (constructors != null) {
247 for (int i = 0, size = constructors.length; i < size; i++) {
248 Constructor constructor = constructors[i];
249 Class[] types = constructor.getParameterTypes();
250 if (types.length == 2 && types[1].isAssignableFrom(int.class)) {
251 if (types[0].isAssignableFrom(parent.getClass())) {
252 Object[] arguments = { parent, new Integer(style)};
253 return constructor.newInstance(arguments);
254 }
255 }
256 }
257 }
258 }
259 return theClass.newInstance();
260 } catch (NoSuchMethodException e) {
261 throw new JellyTagException(e);
262 } catch (InstantiationException e) {
263 throw new JellyTagException(e);
264 } catch (IllegalAccessException e) {
265 throw new JellyTagException(e);
266 } catch (InvocationTargetException e) {
267 throw new JellyTagException(e);
268 }
269 }
270
271 /***
272 * Creates the SWT style code for the current attributes
273 * @return the SWT style code
274 */
275 protected int getStyle(Map attributes) throws JellyTagException {
276 String text = (String) attributes.remove("style");
277 if (text != null) {
278 return SwtHelper.parseStyle(SWT.class, text);
279 }
280 return style;
281 }
282
283 /*** Sets the bean to null, to prevent it from
284 * sticking around in the event that this tag instance is
285 * cached. This method is called at the end of doTag.
286 *
287 */
288 protected void clearBean() {
289 setBean(null);
290 }
291 }