1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 package groovy.swing;
47
48 import groovy.lang.Closure;
49 import groovy.lang.MissingMethodException;
50
51 import groovy.model.DefaultTableModel;
52 import groovy.model.ValueHolder;
53 import groovy.model.ValueModel;
54
55 import groovy.swing.impl.ComponentFacade;
56 import groovy.swing.impl.ContainerFacade;
57 import groovy.swing.impl.DefaultAction;
58 import groovy.swing.impl.Factory;
59 import groovy.swing.impl.Startable;
60 import groovy.swing.impl.TableLayout;
61 import groovy.swing.impl.TableLayoutCell;
62 import groovy.swing.impl.TableLayoutRow;
63
64 import groovy.util.BuilderSupport;
65
66 import java.awt.BorderLayout;
67 import java.awt.CardLayout;
68 import java.awt.Component;
69 import java.awt.Container;
70 import java.awt.Dimension;
71 import java.awt.Dialog;
72 import java.awt.FlowLayout;
73 import java.awt.Frame;
74 import java.awt.GridBagConstraints;
75 import java.awt.GridBagLayout;
76 import java.awt.GridLayout;
77 import java.awt.LayoutManager;
78 import java.awt.Window;
79
80 import java.text.Format;
81
82 import java.util.ArrayList;
83 import java.util.Collections;
84 import java.util.HashMap;
85 import java.util.Iterator;
86 import java.util.LinkedList;
87 import java.util.List;
88 import java.util.Map;
89 import java.util.Vector;
90 import java.util.logging.Level;
91 import java.util.logging.Logger;
92
93 import javax.swing.AbstractButton;
94 import javax.swing.Action;
95 import javax.swing.Box;
96 import javax.swing.BoxLayout;
97 import javax.swing.ButtonGroup;
98 import javax.swing.DefaultBoundedRangeModel;
99 import javax.swing.JButton;
100 import javax.swing.JCheckBox;
101 import javax.swing.JCheckBoxMenuItem;
102 import javax.swing.JColorChooser;
103 import javax.swing.JComboBox;
104 import javax.swing.JComponent;
105 import javax.swing.JDesktopPane;
106 import javax.swing.JDialog;
107 import javax.swing.JEditorPane;
108 import javax.swing.JFileChooser;
109 import javax.swing.JFormattedTextField;
110 import javax.swing.JFrame;
111 import javax.swing.JInternalFrame;
112 import javax.swing.JLabel;
113 import javax.swing.JLayeredPane;
114 import javax.swing.JList;
115 import javax.swing.JMenu;
116 import javax.swing.JMenuBar;
117 import javax.swing.JMenuItem;
118 import javax.swing.JOptionPane;
119 import javax.swing.JPanel;
120 import javax.swing.JPasswordField;
121 import javax.swing.JPopupMenu;
122 import javax.swing.JProgressBar;
123 import javax.swing.JRadioButton;
124 import javax.swing.JRadioButtonMenuItem;
125 import javax.swing.JScrollBar;
126 import javax.swing.JScrollPane;
127 import javax.swing.JSeparator;
128 import javax.swing.JSlider;
129 import javax.swing.JSpinner;
130 import javax.swing.JSplitPane;
131 import javax.swing.JTabbedPane;
132 import javax.swing.JTable;
133 import javax.swing.JTextArea;
134 import javax.swing.JTextField;
135 import javax.swing.JTextPane;
136 import javax.swing.JToggleButton;
137 import javax.swing.JToolBar;
138 import javax.swing.JToolTip;
139 import javax.swing.JTree;
140 import javax.swing.JViewport;
141 import javax.swing.JWindow;
142 import javax.swing.KeyStroke;
143 import javax.swing.OverlayLayout;
144 import javax.swing.RootPaneContainer;
145 import javax.swing.SpinnerDateModel;
146 import javax.swing.SpinnerListModel;
147 import javax.swing.SpinnerNumberModel;
148 import javax.swing.SpringLayout;
149 import javax.swing.table.TableColumn;
150 import javax.swing.table.TableModel;
151
152 import org.codehaus.groovy.runtime.InvokerHelper;
153
154 /***
155 * A helper class for creating Swing widgets using GroovyMarkup
156 *
157 * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
158 * @version $Revision: 1.13 $
159 */
160 public class SwingBuilder extends BuilderSupport {
161
162 private Logger log = Logger.getLogger(getClass().getName());
163 private Map factories = new HashMap();
164 private Object constraints;
165 private Map passThroughNodes = new HashMap();
166 private Map widgets = new HashMap();
167
168 private LinkedList containingWindows = new LinkedList();
169
170 public SwingBuilder() {
171 registerWidgets();
172 }
173
174 public Object getProperty(String name) {
175 Object widget = widgets.get(name);
176 if (widget == null) {
177 return super.getProperty(name);
178 }
179 return widget;
180 }
181
182 protected void setParent(Object parent, Object child) {
183 if (child instanceof Action) {
184 Action action = (Action) child;
185 try {
186 InvokerHelper.setProperty(parent, "action", action);
187 } catch (RuntimeException re) {
188
189
190 }
191 Object keyStroke = action.getValue("KeyStroke");
192
193 if (parent instanceof JComponent) {
194 JComponent component = (JComponent) parent;
195 KeyStroke stroke = null;
196 if (keyStroke instanceof String) {
197 stroke = KeyStroke.getKeyStroke((String) keyStroke);
198 }
199 else if (keyStroke instanceof KeyStroke) {
200 stroke = (KeyStroke) keyStroke;
201 }
202 if (stroke != null) {
203 String key = action.toString();
204 component.getInputMap().put(stroke, key);
205 component.getActionMap().put(key, action);
206 }
207 }
208 }
209 else if (child instanceof LayoutManager) {
210 if (parent instanceof RootPaneContainer) {
211 RootPaneContainer rpc = (RootPaneContainer) parent;
212 parent = rpc.getContentPane();
213 }
214 InvokerHelper.setProperty(parent, "layout", child);
215 }
216 else if (child instanceof JToolTip && parent instanceof JComponent) {
217 ((JToolTip)child).setComponent((JComponent)parent);
218 }
219 else if (parent instanceof JTable && child instanceof TableColumn) {
220 JTable table = (JTable) parent;
221 TableColumn column = (TableColumn) child;
222 table.addColumn(column);
223 }
224 else if (parent instanceof JTabbedPane && child instanceof Component) {
225 JTabbedPane tabbedPane = (JTabbedPane) parent;
226 tabbedPane.add((Component)child);
227 }
228 else if (child instanceof Window) {
229
230
231
232 }
233 else {
234 Component component = null;
235 if (child instanceof Component) {
236 component = (Component) child;
237 }
238 else if (child instanceof ComponentFacade) {
239 ComponentFacade facade = (ComponentFacade) child;
240 component = facade.getComponent();
241 }
242 if (component != null) {
243 if (parent instanceof JFrame && component instanceof JMenuBar) {
244 JFrame frame = (JFrame) parent;
245 frame.setJMenuBar((JMenuBar) component);
246 }
247 else if (parent instanceof RootPaneContainer) {
248 RootPaneContainer rpc = (RootPaneContainer) parent;
249 rpc.getContentPane().add(component);
250 }
251 else if (parent instanceof JScrollPane) {
252 JScrollPane scrollPane = (JScrollPane) parent;
253 if (child instanceof JViewport) {
254 scrollPane.setViewport((JViewport)component);
255 }
256 else {
257 scrollPane.setViewportView(component);
258 }
259 }
260 else if (parent instanceof JSplitPane) {
261 JSplitPane splitPane = (JSplitPane) parent;
262 if (splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
263 if (splitPane.getTopComponent() == null) {
264 splitPane.setTopComponent(component);
265 }
266 else {
267 splitPane.setBottomComponent(component);
268 }
269 }
270 else {
271 if (splitPane.getLeftComponent() == null) {
272 splitPane.setLeftComponent(component);
273 }
274 else {
275 splitPane.setRightComponent(component);
276 }
277 }
278 }
279 else if (parent instanceof JMenuBar && component instanceof JMenu) {
280 JMenuBar menuBar = (JMenuBar) parent;
281 menuBar.add((JMenu) component);
282 }
283 else if (parent instanceof Container) {
284 Container container = (Container) parent;
285 if (constraints != null) {
286 container.add(component, constraints);
287 }
288 else {
289 container.add(component);
290 }
291 }
292 else if (parent instanceof ContainerFacade) {
293 ContainerFacade facade = (ContainerFacade) parent;
294 facade.addComponent(component);
295 }
296 }
297 }
298 }
299
300 protected void nodeCompleted(Object parent, Object node) {
301
302 if (node instanceof TableModel && parent instanceof JTable) {
303 JTable table = (JTable) parent;
304 TableModel model = (TableModel) node;
305 table.setModel(model);
306 }
307 if (node instanceof Startable) {
308 Startable startable = (Startable) node;
309 startable.start();
310 }
311 if (node instanceof Window) {
312 if (!containingWindows.isEmpty() && containingWindows.getLast() == node) {
313 containingWindows.removeLast();
314 }
315 }
316 }
317
318 protected Object createNode(Object name) {
319 return createNode(name, Collections.EMPTY_MAP);
320 }
321
322 protected Object createNode(Object name, Object value) {
323 if (passThroughNodes.containsKey(name) && (value != null) && ((Class)passThroughNodes.get(name)).isAssignableFrom(value.getClass())) {
324
325 if (value instanceof Window) {
326 containingWindows.add(value);
327 }
328 return value;
329 }
330 else if (value instanceof String) {
331 Object widget = createNode(name);
332 if (widget != null) {
333 InvokerHelper.invokeMethod(widget, "setText", value);
334 }
335 return widget;
336 }
337 else {
338 throw new MissingMethodException((String) name, getClass(), new Object[] {value});
339 }
340 }
341
342 protected Object createNode(Object name, Map attributes, Object value) {
343 if (passThroughNodes.containsKey(name) && (value != null) && ((Class)passThroughNodes.get(name)).isAssignableFrom(value.getClass())) {
344
345 if (value instanceof Window) {
346 containingWindows.add(value);
347 }
348 handleWidgetAttributes(value, attributes);
349 return value;
350 }
351 else {
352 Object widget = createNode(name, attributes);
353 if (widget != null) {
354 InvokerHelper.invokeMethod(widget, "setText", value.toString());
355 }
356 return widget;
357 }
358 }
359
360 protected Object createNode(Object name, Map attributes) {
361 String widgetName = (String) attributes.remove("id");
362 constraints = attributes.remove("constraints");
363 Object widget = null;
364 if (passThroughNodes.containsKey(name)) {
365 widget = attributes.get(name);
366 if ((widget != null) && ((Class)passThroughNodes.get(name)).isAssignableFrom(widget.getClass())) {
367
368 if (widget instanceof Window) {
369 containingWindows.add(widget);
370 }
371 attributes.remove(name);
372 }
373 else {
374 widget = null;
375 }
376 }
377 if (widget == null) {
378 Factory factory = (Factory) factories.get(name);
379 if (factory != null) {
380 try {
381 widget = factory.newInstance(attributes);
382 if (widgetName != null) {
383 widgets.put(widgetName, widget);
384 }
385 if (widget == null) {
386 log.log(Level.WARNING, "Factory for name: " + name + " returned null");
387 }
388 else {
389 if (log.isLoggable(Level.FINE)) {
390 log.fine("For name: " + name + " created widget: " + widget);
391 }
392 }
393 }
394 catch (Exception e) {
395 throw new RuntimeException("Failed to create component for" + name + " reason: " + e, e);
396 }
397 }
398 else {
399 log.log(Level.WARNING, "Could not find match for name: " + name);
400 }
401 }
402 handleWidgetAttributes(widget, attributes);
403 return widget;
404 }
405
406 protected void handleWidgetAttributes(Object widget, Map attributes) {
407 if (widget != null) {
408 if (widget instanceof Action) {
409 /*** @todo we could move this custom logic into the MetaClass for Action */
410 Action action = (Action) widget;
411
412 Closure closure = (Closure) attributes.remove("closure");
413 if (closure != null && action instanceof DefaultAction) {
414 DefaultAction defaultAction = (DefaultAction) action;
415 defaultAction.setClosure(closure);
416 }
417
418 Object accel = attributes.remove("accelerator");
419 KeyStroke stroke = null;
420 if (accel instanceof KeyStroke) {
421 stroke = (KeyStroke) accel;
422 } else if (accel != null) {
423 stroke = KeyStroke.getKeyStroke(accel.toString());
424 }
425 action.putValue(Action.ACCELERATOR_KEY, stroke);
426
427 Object mnemonic = attributes.remove("mnemonic");
428 if ((mnemonic != null) && !(mnemonic instanceof Number)) {
429 mnemonic = new Integer(mnemonic.toString().charAt(0));
430 }
431 action.putValue(Action.MNEMONIC_KEY, mnemonic);
432
433 for (Iterator iter = attributes.entrySet().iterator(); iter.hasNext();) {
434 Map.Entry entry = (Map.Entry) iter.next();
435 String actionName = (String) entry.getKey();
436
437
438 actionName = capitalize(actionName);
439 Object value = entry.getValue();
440
441 action.putValue(actionName, value);
442 }
443
444 }
445 else {
446
447 if (attributes.containsKey("buttonGroup")) {
448 Object o = attributes.get("buttonGroup");
449 if ((o instanceof ButtonGroup) && (widget instanceof AbstractButton)) {
450 ((AbstractButton)widget).getModel().setGroup((ButtonGroup)o);
451 attributes.remove("buttonGroup");
452 }
453 }
454
455
456 Object mnemonic = attributes.remove("mnemonic");
457 if ((mnemonic != null) && (mnemonic instanceof Number)) {
458 InvokerHelper.setProperty(widget, "mnemonic", new Character((char)((Number)mnemonic).intValue()));
459 }
460 else if (mnemonic != null) {
461 InvokerHelper.setProperty(widget, "mnemonic", new Character(mnemonic.toString().charAt(0)));
462 }
463
464
465 for (Iterator iter = attributes.entrySet().iterator(); iter.hasNext();) {
466 Map.Entry entry = (Map.Entry) iter.next();
467 String property = entry.getKey().toString();
468 Object value = entry.getValue();
469 InvokerHelper.setProperty(widget, property, value);
470 }
471 }
472 }
473 }
474
475 protected String capitalize(String text) {
476 char ch = text.charAt(0);
477 if (Character.isUpperCase(ch)) {
478 return text;
479 }
480 StringBuffer buffer = new StringBuffer(text.length());
481 buffer.append(Character.toUpperCase(ch));
482 buffer.append(text.substring(1));
483 return buffer.toString();
484 }
485
486 protected void registerWidgets() {
487
488
489
490 registerBeanFactory("action", DefaultAction.class);
491 passThroughNodes.put("action", javax.swing.Action.class);
492 registerBeanFactory("buttonGroup", ButtonGroup.class);
493 registerFactory("map", new Factory() {
494 public Object newInstance(Map properties)
495 throws InstantiationException, InstantiationException, IllegalAccessException {
496 return properties;
497 }
498 });
499
500 passThroughNodes.put("widget", java.awt.Component.class);
501
502
503
504
505 registerFactory("dialog", new Factory() {
506 public Object newInstance(Map properties)
507 throws InstantiationException, InstantiationException, IllegalAccessException {
508 return createDialog(properties);
509 }
510 });
511 registerFactory("frame", new Factory() {
512 public Object newInstance(Map properties)
513 throws InstantiationException, InstantiationException, IllegalAccessException {
514 return createFrame(properties);
515 }
516 });
517 registerBeanFactory("fileChooser", JFileChooser.class);
518 registerFactory("frame", new Factory() {
519 public Object newInstance(Map properties)
520 throws InstantiationException, InstantiationException, IllegalAccessException {
521 return createFrame(properties);
522 }
523 });
524 registerBeanFactory("optionPane", JOptionPane.class);
525 registerFactory("window", new Factory() {
526 public Object newInstance(Map properties)
527 throws InstantiationException, InstantiationException, IllegalAccessException {
528 return createWindow(properties);
529 }
530 });
531
532
533
534
535 registerBeanFactory("button", JButton.class);
536 registerBeanFactory("checkBox", JCheckBox.class);
537 registerBeanFactory("checkBoxMenuItem", JCheckBoxMenuItem.class);
538 registerBeanFactory("colorChooser", JColorChooser.class);
539 registerFactory("comboBox", new Factory() {
540 public Object newInstance(Map properties)
541 throws InstantiationException, InstantiationException, IllegalAccessException {
542 return createComboBox(properties);
543 }
544 });
545 registerBeanFactory("desktopPane", JDesktopPane.class);
546 registerBeanFactory("editorPane", JEditorPane.class);
547 registerFactory("formattedTextField", new Factory() {
548 public Object newInstance(Map properties)
549 throws InstantiationException, InstantiationException, IllegalAccessException {
550 return createFormattedTextField(properties);
551 }
552 });
553 registerBeanFactory("internalFrame", JInternalFrame.class);
554 registerBeanFactory("label", JLabel.class);
555 registerBeanFactory("layeredPane", JLayeredPane.class);
556 registerBeanFactory("list", JList.class);
557 registerBeanFactory("menu", JMenu.class);
558 registerBeanFactory("menuBar", JMenuBar.class);
559 registerBeanFactory("menuItem", JMenuItem.class);
560 registerBeanFactory("panel", JPanel.class);
561 registerBeanFactory("passwordField", JPasswordField.class);
562 registerBeanFactory("popupMenu", JPopupMenu.class);
563 registerBeanFactory("progressBar", JProgressBar.class);
564 registerBeanFactory("radioButton", JRadioButton.class);
565 registerBeanFactory("radioButtonMenuItem", JRadioButtonMenuItem.class);
566 registerBeanFactory("scrollBar", JScrollBar.class);
567 registerBeanFactory("scrollPane", JScrollPane.class);
568 registerBeanFactory("separator", JSeparator.class);
569 registerBeanFactory("slider", JSlider.class);
570 registerBeanFactory("spinner", JSpinner.class);
571 registerFactory("splitPane", new Factory() {
572 public Object newInstance(Map properties) {
573 JSplitPane answer = new JSplitPane();
574 answer.setLeftComponent(null);
575 answer.setRightComponent(null);
576 answer.setTopComponent(null);
577 answer.setBottomComponent(null);
578 return answer;
579 }
580 });
581 registerBeanFactory("tabbedPane", JTabbedPane.class);
582 registerBeanFactory("table", JTable.class);
583 registerBeanFactory("textArea", JTextArea.class);
584 registerBeanFactory("textPane", JTextPane.class);
585 registerBeanFactory("textField", JTextField.class);
586 registerBeanFactory("toggleButton", JToggleButton.class);
587 registerBeanFactory("toolBar", JToolBar.class);
588
589 registerBeanFactory("tree", JTree.class);
590 registerBeanFactory("viewport", JViewport.class);
591
592
593
594
595 registerBeanFactory("boundedRangeModel", DefaultBoundedRangeModel.class);
596
597
598 registerBeanFactory("spinnerDateModel", SpinnerDateModel.class);
599 registerBeanFactory("spinnerListModel", SpinnerListModel.class);
600 registerBeanFactory("spinnerNumberModel", SpinnerNumberModel.class);
601
602
603 registerFactory("tableModel", new Factory() {
604 public Object newInstance(Map properties) {
605 ValueModel model = (ValueModel) properties.remove("model");
606 if (model == null) {
607 Object list = properties.remove("list");
608 if (list == null) {
609 list = new ArrayList();
610 }
611 model = new ValueHolder(list);
612 }
613 return new DefaultTableModel(model);
614 }
615 });
616 passThroughNodes.put("tableModel", javax.swing.table.TableModel.class);
617
618 registerFactory("propertyColumn", new Factory() {
619 public Object newInstance(Map properties) {
620 Object current = getCurrent();
621 if (current instanceof DefaultTableModel) {
622 DefaultTableModel model = (DefaultTableModel) current;
623 Object header = properties.remove("header");
624 if (header == null) {
625 header = "";
626 }
627 String property = (String) properties.remove("propertyName");
628 if (property == null) {
629 throw new IllegalArgumentException("Must specify a property for a propertyColumn");
630 }
631 Class type = (Class) properties.remove("type");
632 if (type == null) {
633 type = Object.class;
634 }
635 return model.addPropertyColumn(header, property, type);
636 }
637 else {
638 throw new RuntimeException("propertyColumn must be a child of a tableModel");
639 }
640 }
641 });
642
643 registerFactory("closureColumn", new Factory() {
644 public Object newInstance(Map properties) {
645 Object current = getCurrent();
646 if (current instanceof DefaultTableModel) {
647 DefaultTableModel model = (DefaultTableModel) current;
648 Object header = properties.remove("header");
649 if (header == null) {
650 header = "";
651 }
652 Closure readClosure = (Closure) properties.remove("read");
653 if (readClosure == null) {
654 throw new IllegalArgumentException("Must specify 'read' Closure property for a closureColumn");
655 }
656 Closure writeClosure = (Closure) properties.remove("write");
657 Class type = (Class) properties.remove("type");
658 if (type == null) {
659 type = Object.class;
660 }
661 return model.addClosureColumn(header, readClosure, writeClosure, type);
662 }
663 else {
664 throw new RuntimeException("propertyColumn must be a child of a tableModel");
665 }
666 }
667 });
668
669
670
671 registerBeanFactory("borderLayout", BorderLayout.class);
672 registerBeanFactory("cardLayout", CardLayout.class);
673 registerBeanFactory("flowLayout", FlowLayout.class);
674 registerBeanFactory("gridBagLayout", GridBagLayout.class);
675 registerBeanFactory("gridLayout", GridLayout.class);
676 registerBeanFactory("overlayLayout", OverlayLayout.class);
677 registerBeanFactory("springLayout", SpringLayout.class);
678 registerBeanFactory("gridBagConstarints", GridBagConstraints.class);
679 registerBeanFactory("gbc", GridBagConstraints.class);
680
681
682 registerFactory("boxLayout", new Factory() {
683 public Object newInstance(Map properties)
684 throws InstantiationException, InstantiationException, IllegalAccessException {
685 return createBoxLayout(properties);
686 }
687 });
688
689
690 registerFactory("hbox", new Factory() {
691 public Object newInstance(Map properties) {
692 return Box.createHorizontalBox();
693 }
694 });
695 registerFactory("hglue", new Factory() {
696 public Object newInstance(Map properties) {
697 return Box.createHorizontalGlue();
698 }
699 });
700 registerFactory("hstrut", new Factory() {
701 public Object newInstance(Map properties) {
702 try {
703 Object num = properties.remove("width");
704 if (num instanceof Number) {
705 return Box.createHorizontalStrut(((Number)num).intValue());
706 } else {
707 return Box.createHorizontalStrut(6);
708 }
709 } catch (RuntimeException re) {
710 re.printStackTrace(System.out);
711 throw re;
712 }
713 }
714 });
715 registerFactory("vbox", new Factory() {
716 public Object newInstance(Map properties) {
717 return Box.createVerticalBox();
718 }
719 });
720 registerFactory("vglue", new Factory() {
721 public Object newInstance(Map properties) {
722 return Box.createVerticalGlue();
723 }
724 });
725 registerFactory("vstrut", new Factory() {
726 public Object newInstance(Map properties) {
727 Object num = properties.remove("height");
728 if (num instanceof Number) {
729 return Box.createVerticalStrut(((Number)num).intValue());
730 } else {
731 return Box.createVerticalStrut(6);
732 }
733 }
734 });
735 registerFactory("glue", new Factory() {
736 public Object newInstance(Map properties) {
737 return Box.createGlue();
738 }
739 });
740 registerFactory("rigidArea", new Factory() {
741 public Object newInstance(Map properties) {
742 Dimension dim;
743 Object o = properties.remove("size");
744 if (o instanceof Dimension) {
745 dim = (Dimension) o;
746 } else {
747 int w, h;
748 o = properties.remove("width");
749 w = ((o instanceof Number)) ? ((Number)o).intValue() : 6;
750 o = properties.remove("height");
751 h = ((o instanceof Number)) ? ((Number)o).intValue() : 6;
752 dim = new Dimension(w, h);
753 }
754 return Box.createRigidArea(dim);
755 }
756 });
757
758
759 registerBeanFactory("tableLayout", TableLayout.class);
760 registerFactory("tr", new Factory() {
761 public Object newInstance(Map properties) {
762 Object parent = getCurrent();
763 if (parent instanceof TableLayout) {
764 return new TableLayoutRow((TableLayout) parent);
765 }
766 else {
767 throw new RuntimeException("'tr' must be within a 'tableLayout'");
768 }
769 }
770 });
771 registerFactory("td", new Factory() {
772 public Object newInstance(Map properties) {
773 Object parent = getCurrent();
774 if (parent instanceof TableLayoutRow) {
775 return new TableLayoutCell((TableLayoutRow) parent);
776 }
777 else {
778 throw new RuntimeException("'td' must be within a 'tr'");
779 }
780 }
781 });
782 }
783
784 protected Object createBoxLayout(Map properties) {
785 Object parent = getCurrent();
786 if (parent instanceof Container) {
787 Object axisObject = properties.remove("axis");
788 int axis = 0;
789 if (axisObject != null) {
790 Integer i = (Integer) axisObject;
791 axis = i.intValue();
792 }
793 BoxLayout answer = new BoxLayout((Container) parent, axis);
794
795
796 InvokerHelper.setProperty(parent, "layout", answer);
797 return answer;
798 }
799 else {
800 throw new RuntimeException("Must be nested inside a Container");
801 }
802 }
803
804 protected Object createDialog(Map properties) {
805 JDialog dialog;
806 Object owner = properties.remove("owner");
807
808 if ((owner == null) && !containingWindows.isEmpty()) {
809 owner = containingWindows.getLast();
810 }
811 if (owner instanceof Frame) {
812 dialog = new JDialog((Frame) owner);
813 }
814 else if (owner instanceof Dialog) {
815 dialog = new JDialog((Dialog) owner);
816 }
817 else {
818 dialog = new JDialog();
819 }
820 containingWindows.add(dialog);
821 return dialog;
822 }
823
824 /***
825 * Uses 'format," or "value," (in order)
826 *
827 */
828 protected Object createFormattedTextField(Map properties) {
829 JFormattedTextField ftf;
830 if (properties.containsKey("format")) {
831 ftf = new JFormattedTextField((Format) properties.remove("format"));
832 }
833 else if (properties.containsKey("value")) {
834 ftf = new JFormattedTextField(properties.remove("value"));
835 }
836 else {
837 ftf = new JFormattedTextField();
838 }
839 return ftf;
840 }
841
842 protected Object createFrame(Map properties) {
843 JFrame frame = new JFrame();
844 containingWindows.add(frame);
845 return frame;
846 }
847
848 protected Object createWindow(Map properties) {
849 JWindow window;
850 Object owner = properties.remove("owner");
851
852 if ((owner == null) && !containingWindows.isEmpty()) {
853 owner = containingWindows.getLast();
854 }
855 if (owner instanceof Frame) {
856 window = new JWindow((Frame) owner);
857 }
858 else if (owner instanceof Window) {
859 window = new JWindow((Window) owner);
860 }
861 else {
862 window = new JWindow();
863 }
864 containingWindows.add(window);
865 return window;
866 }
867
868 protected Object createComboBox(Map properties) {
869 Object items = properties.remove("items");
870 if (items instanceof Vector) {
871 return new JComboBox((Vector) items);
872 }
873 else if (items instanceof List) {
874 List list = (List) items;
875 return new JComboBox(list.toArray());
876 }
877 else if (items instanceof Object[]) {
878 return new JComboBox((Object[]) items);
879 }
880 else {
881 return new JComboBox();
882 }
883 }
884
885 protected void registerBeanFactory(String name, final Class beanClass) {
886 registerFactory(name, new Factory() {
887 public Object newInstance(Map properties) throws InstantiationException, IllegalAccessException {
888 return beanClass.newInstance();
889 }
890 });
891
892 }
893
894 protected void registerFactory(String name, Factory factory) {
895 factories.put(name, factory);
896 }
897 }