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