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