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