blob: b386de7afd54cb95c62c4628e9ffa9fe23050f30 [file] [log] [blame]
/*
$Id$
Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
Redistribution and use of this software and associated documentation
("Software"), with or without modification, are permitted provided
that the following conditions are met:
1. Redistributions of source code must retain copyright
statements and notices. Redistributions must also contain a
copy of this document.
2. Redistributions in binary form must reproduce the
above copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
3. The name "groovy" must not be used to endorse or promote
products derived from this Software without prior written
permission of The Codehaus. For written permission,
please contact info@codehaus.org.
4. Products derived from this Software may not be called "groovy"
nor may "groovy" appear in their names without prior written
permission of The Codehaus. "groovy" is a registered
trademark of The Codehaus.
5. Due credit should be given to The Codehaus -
http://groovy.codehaus.org/
THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package groovy.swing;
import groovy.lang.Closure;
import groovy.lang.MissingMethodException;
import groovy.model.DefaultTableModel;
import groovy.model.ValueHolder;
import groovy.model.ValueModel;
import groovy.swing.impl.ComponentFacade;
import groovy.swing.impl.ContainerFacade;
import groovy.swing.impl.DefaultAction;
import groovy.swing.impl.Factory;
import groovy.swing.impl.Startable;
import groovy.swing.impl.TableLayout;
import groovy.swing.impl.TableLayoutCell;
import groovy.swing.impl.TableLayoutRow;
import groovy.util.BuilderSupport;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Dialog;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.LayoutManager;
import java.awt.Window;
import java.text.Format;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.DefaultBoundedRangeModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JFileChooser;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.JRadioButton;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.JToolTip;
import javax.swing.JTree;
import javax.swing.JViewport;
import javax.swing.JWindow;
import javax.swing.KeyStroke;
import javax.swing.OverlayLayout;
import javax.swing.RootPaneContainer;
import javax.swing.SpinnerDateModel;
import javax.swing.SpinnerListModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.SpringLayout;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import org.codehaus.groovy.runtime.InvokerHelper;
/**
* A helper class for creating Swing widgets using GroovyMarkup
*
* @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
* @version $Revision$
*/
public class SwingBuilder extends BuilderSupport {
private Logger log = Logger.getLogger(getClass().getName());
private Map factories = new HashMap();
private Object constraints;
private Map passThroughNodes = new HashMap();
private Map widgets = new HashMap();
// tracks all containing windows, for auto-owned dialogs
private LinkedList containingWindows = new LinkedList();
public SwingBuilder() {
registerWidgets();
}
public Object getProperty(String name) {
Object widget = widgets.get(name);
if (widget == null) {
return super.getProperty(name);
}
return widget;
}
protected void setParent(Object parent, Object child) {
if (child instanceof Action) {
Action action = (Action) child;
try {
InvokerHelper.setProperty(parent, "action", action);
} catch (RuntimeException re) {
// must not have an action property...
// so we ignore it and go on
}
Object keyStroke = action.getValue("KeyStroke");
//System.out.println("keystroke: " + keyStroke + " for: " + action);
if (parent instanceof JComponent) {
JComponent component = (JComponent) parent;
KeyStroke stroke = null;
if (keyStroke instanceof String) {
stroke = KeyStroke.getKeyStroke((String) keyStroke);
}
else if (keyStroke instanceof KeyStroke) {
stroke = (KeyStroke) keyStroke;
}
if (stroke != null) {
String key = action.toString();
component.getInputMap().put(stroke, key);
component.getActionMap().put(key, action);
}
}
}
else if (child instanceof LayoutManager) {
if (parent instanceof RootPaneContainer) {
RootPaneContainer rpc = (RootPaneContainer) parent;
parent = rpc.getContentPane();
}
InvokerHelper.setProperty(parent, "layout", child);
}
else if (child instanceof JToolTip && parent instanceof JComponent) {
((JToolTip)child).setComponent((JComponent)parent);
}
else if (parent instanceof JTable && child instanceof TableColumn) {
JTable table = (JTable) parent;
TableColumn column = (TableColumn) child;
table.addColumn(column);
}
else if (parent instanceof JTabbedPane && child instanceof Component) {
JTabbedPane tabbedPane = (JTabbedPane) parent;
tabbedPane.add((Component)child);
}
else if (child instanceof Window) {
// do nothing. owner of window is set elsewhere, and this
// shouldn't get added to any parent as a child
// if it is a top level component anyway
}
else {
Component component = null;
if (child instanceof Component) {
component = (Component) child;
}
else if (child instanceof ComponentFacade) {
ComponentFacade facade = (ComponentFacade) child;
component = facade.getComponent();
}
if (component != null) {
if (parent instanceof JFrame && component instanceof JMenuBar) {
JFrame frame = (JFrame) parent;
frame.setJMenuBar((JMenuBar) component);
}
else if (parent instanceof RootPaneContainer) {
RootPaneContainer rpc = (RootPaneContainer) parent;
if (constraints != null) {
rpc.getContentPane().add(component, constraints);
} else {
rpc.getContentPane().add(component);
}
}
else if (parent instanceof JScrollPane) {
JScrollPane scrollPane = (JScrollPane) parent;
if (child instanceof JViewport) {
scrollPane.setViewport((JViewport)component);
}
else {
scrollPane.setViewportView(component);
}
}
else if (parent instanceof JSplitPane) {
JSplitPane splitPane = (JSplitPane) parent;
if (splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
if (splitPane.getTopComponent() == null) {
splitPane.setTopComponent(component);
}
else {
splitPane.setBottomComponent(component);
}
}
else {
if (splitPane.getLeftComponent() == null) {
splitPane.setLeftComponent(component);
}
else {
splitPane.setRightComponent(component);
}
}
}
else if (parent instanceof JMenuBar && component instanceof JMenu) {
JMenuBar menuBar = (JMenuBar) parent;
menuBar.add((JMenu) component);
}
else if (parent instanceof Container) {
Container container = (Container) parent;
if (constraints != null) {
container.add(component, constraints);
}
else {
container.add(component);
}
}
else if (parent instanceof ContainerFacade) {
ContainerFacade facade = (ContainerFacade) parent;
facade.addComponent(component);
}
}
}
}
protected void nodeCompleted(Object parent, Object node) {
// set models after the node has been completed
if (node instanceof TableModel && parent instanceof JTable) {
JTable table = (JTable) parent;
TableModel model = (TableModel) node;
table.setModel(model);
}
if (node instanceof Startable) {
Startable startable = (Startable) node;
startable.start();
}
if (node instanceof Window) {
if (!containingWindows.isEmpty() && containingWindows.getLast() == node) {
containingWindows.removeLast();
}
}
}
protected Object createNode(Object name) {
return createNode(name, Collections.EMPTY_MAP);
}
protected Object createNode(Object name, Object value) {
if (passThroughNodes.containsKey(name) && (value != null) && ((Class)passThroughNodes.get(name)).isAssignableFrom(value.getClass())) {
// value may need to go into containing windows list
if (value instanceof Window) {
containingWindows.add(value);
}
return value;
}
else if (value instanceof String) {
Object widget = createNode(name);
if (widget != null) {
InvokerHelper.invokeMethod(widget, "setText", value);
}
return widget;
}
else {
throw new MissingMethodException((String) name, getClass(), new Object[] {value}, false);
}
}
protected Object createNode(Object name, Map attributes, Object value) {
if (passThroughNodes.containsKey(name) && (value != null) && ((Class)passThroughNodes.get(name)).isAssignableFrom(value.getClass())) {
// value may need to go into containing windows list
if (value instanceof Window) {
containingWindows.add(value);
}
handleWidgetAttributes(value, attributes);
return value;
}
else {
Object widget = createNode(name, attributes);
if (widget != null) {
InvokerHelper.invokeMethod(widget, "setText", value.toString());
}
return widget;
}
}
protected Object createNode(Object name, Map attributes) {
String widgetName = (String) attributes.remove("id");
constraints = attributes.remove("constraints");
Object widget = null;
if (passThroughNodes.containsKey(name)) {
widget = attributes.get(name);
if ((widget != null) && ((Class)passThroughNodes.get(name)).isAssignableFrom(widget.getClass())) {
// value may need to go into containing windows list
if (widget instanceof Window) {
containingWindows.add(widget);
}
attributes.remove(name);
}
else {
widget = null;
}
}
if (widget == null) {
Factory factory = (Factory) factories.get(name);
if (factory != null) {
try {
widget = factory.newInstance(attributes);
if (widgetName != null) {
widgets.put(widgetName, widget);
}
if (widget == null) {
log.log(Level.WARNING, "Factory for name: " + name + " returned null");
}
else {
if (log.isLoggable(Level.FINE)) {
log.fine("For name: " + name + " created widget: " + widget);
}
}
}
catch (Exception e) {
throw new RuntimeException("Failed to create component for" + name + " reason: " + e, e);
}
}
else {
log.log(Level.WARNING, "Could not find match for name: " + name);
}
}
handleWidgetAttributes(widget, attributes);
return widget;
}
protected void handleWidgetAttributes(Object widget, Map attributes) {
if (widget != null) {
if (widget instanceof Action) {
/** @todo we could move this custom logic into the MetaClass for Action */
Action action = (Action) widget;
Closure closure = (Closure) attributes.remove("closure");
if (closure != null && action instanceof DefaultAction) {
DefaultAction defaultAction = (DefaultAction) action;
defaultAction.setClosure(closure);
}
Object accel = attributes.remove("accelerator");
KeyStroke stroke = null;
if (accel instanceof KeyStroke) {
stroke = (KeyStroke) accel;
} else if (accel != null) {
stroke = KeyStroke.getKeyStroke(accel.toString());
}
action.putValue(Action.ACCELERATOR_KEY, stroke);
Object mnemonic = attributes.remove("mnemonic");
if ((mnemonic != null) && !(mnemonic instanceof Number)) {
mnemonic = new Integer(mnemonic.toString().charAt(0));
}
action.putValue(Action.MNEMONIC_KEY, mnemonic);
for (Iterator iter = attributes.entrySet().iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
String actionName = (String) entry.getKey(); // todo dk: misleading naming. this can be any property name
// typically standard Action names start with upper case, so lets upper case it
actionName = capitalize(actionName); // todo dk: in general, this shouldn't be capitalized
Object value = entry.getValue();
action.putValue(actionName, value);
}
}
else {
// some special cases...
if (attributes.containsKey("buttonGroup")) {
Object o = attributes.get("buttonGroup");
if ((o instanceof ButtonGroup) && (widget instanceof AbstractButton)) {
((AbstractButton)widget).getModel().setGroup((ButtonGroup)o);
attributes.remove("buttonGroup");
}
}
// this next statement nd if/else is a workaround until GROOVY-305 is fixed
Object mnemonic = attributes.remove("mnemonic");
if ((mnemonic != null) && (mnemonic instanceof Number)) {
InvokerHelper.setProperty(widget, "mnemonic", new Character((char)((Number)mnemonic).intValue()));
}
else if (mnemonic != null) {
InvokerHelper.setProperty(widget, "mnemonic", new Character(mnemonic.toString().charAt(0)));
}
// set the properties
for (Iterator iter = attributes.entrySet().iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
String property = entry.getKey().toString();
Object value = entry.getValue();
InvokerHelper.setProperty(widget, property, value);
}
}
}
}
protected String capitalize(String text) {
char ch = text.charAt(0);
if (Character.isUpperCase(ch)) {
return text;
}
StringBuffer buffer = new StringBuffer(text.length());
buffer.append(Character.toUpperCase(ch));
buffer.append(text.substring(1));
return buffer.toString();
}
protected void registerWidgets() {
//
// non-widget support classes
//
registerBeanFactory("action", DefaultAction.class);
passThroughNodes.put("action", javax.swing.Action.class);
registerBeanFactory("buttonGroup", ButtonGroup.class);
registerFactory("map", new Factory() { // todo dk: is that still needed?
public Object newInstance(Map properties)
throws InstantiationException, InstantiationException, IllegalAccessException {
return properties;
}
});
// ulimate pass through type
passThroughNodes.put("widget", java.awt.Component.class);
//
// standalone window classes
//
registerFactory("dialog", new Factory() {
public Object newInstance(Map properties)
throws InstantiationException, InstantiationException, IllegalAccessException {
return createDialog(properties);
}
});
registerFactory("frame", new Factory() {
public Object newInstance(Map properties)
throws InstantiationException, InstantiationException, IllegalAccessException {
return createFrame(properties);
}
});
registerBeanFactory("fileChooser", JFileChooser.class);
registerFactory("frame", new Factory() { // todo dk: frame registered twice ???
public Object newInstance(Map properties)
throws InstantiationException, InstantiationException, IllegalAccessException {
return createFrame(properties);
}
});
registerBeanFactory("optionPane", JOptionPane.class);
registerFactory("window", new Factory() {
public Object newInstance(Map properties)
throws InstantiationException, InstantiationException, IllegalAccessException {
return createWindow(properties);
}
});
//
// widgets
//
registerBeanFactory("button", JButton.class);
registerBeanFactory("checkBox", JCheckBox.class);
registerBeanFactory("checkBoxMenuItem", JCheckBoxMenuItem.class);
registerBeanFactory("colorChooser", JColorChooser.class);
registerFactory("comboBox", new Factory() {
public Object newInstance(Map properties)
throws InstantiationException, InstantiationException, IllegalAccessException {
return createComboBox(properties);
}
});
registerBeanFactory("desktopPane", JDesktopPane.class);
registerBeanFactory("editorPane", JEditorPane.class);
registerFactory("formattedTextField", new Factory() {
public Object newInstance(Map properties)
throws InstantiationException, InstantiationException, IllegalAccessException {
return createFormattedTextField(properties);
}
});
registerBeanFactory("internalFrame", JInternalFrame.class);
registerBeanFactory("label", JLabel.class);
registerBeanFactory("layeredPane", JLayeredPane.class);
registerBeanFactory("list", JList.class);
registerBeanFactory("menu", JMenu.class);
registerBeanFactory("menuBar", JMenuBar.class);
registerBeanFactory("menuItem", JMenuItem.class);
registerBeanFactory("panel", JPanel.class);
registerBeanFactory("passwordField", JPasswordField.class);
registerBeanFactory("popupMenu", JPopupMenu.class);
registerBeanFactory("progressBar", JProgressBar.class);
registerBeanFactory("radioButton", JRadioButton.class);
registerBeanFactory("radioButtonMenuItem", JRadioButtonMenuItem.class);
registerBeanFactory("scrollBar", JScrollBar.class);
registerBeanFactory("scrollPane", JScrollPane.class);
registerBeanFactory("separator", JSeparator.class);
registerBeanFactory("slider", JSlider.class);
registerBeanFactory("spinner", JSpinner.class);
registerFactory("splitPane", new Factory() {
public Object newInstance(Map properties) {
JSplitPane answer = new JSplitPane();
answer.setLeftComponent(null);
answer.setRightComponent(null);
answer.setTopComponent(null);
answer.setBottomComponent(null);
return answer;
}
});
registerBeanFactory("tabbedPane", JTabbedPane.class);
registerBeanFactory("table", JTable.class);
registerBeanFactory("textArea", JTextArea.class);
registerBeanFactory("textPane", JTextPane.class);
registerBeanFactory("textField", JTextField.class);
registerBeanFactory("toggleButton", JToggleButton.class);
registerBeanFactory("toolBar", JToolBar.class);
//registerBeanFactory("tooltip", JToolTip.class); // doens't work, user toolTipText property
registerBeanFactory("tree", JTree.class);
registerBeanFactory("viewport", JViewport.class); // sub class?
//
// MVC models
//
registerBeanFactory("boundedRangeModel", DefaultBoundedRangeModel.class);
// spinner models
registerBeanFactory("spinnerDateModel", SpinnerDateModel.class);
registerBeanFactory("spinnerListModel", SpinnerListModel.class);
registerBeanFactory("spinnerNumberModel", SpinnerNumberModel.class);
// table models
registerFactory("tableModel", new Factory() {
public Object newInstance(Map properties) {
ValueModel model = (ValueModel) properties.remove("model");
if (model == null) {
Object list = properties.remove("list");
if (list == null) {
list = new ArrayList();
}
model = new ValueHolder(list);
}
return new DefaultTableModel(model);
}
});
passThroughNodes.put("tableModel", javax.swing.table.TableModel.class);
registerFactory("propertyColumn", new Factory() {
public Object newInstance(Map properties) {
Object current = getCurrent();
if (current instanceof DefaultTableModel) {
DefaultTableModel model = (DefaultTableModel) current;
Object header = properties.remove("header");
if (header == null) {
header = "";
}
String property = (String) properties.remove("propertyName");
if (property == null) {
throw new IllegalArgumentException("Must specify a property for a propertyColumn");
}
Class type = (Class) properties.remove("type");
if (type == null) {
type = Object.class;
}
return model.addPropertyColumn(header, property, type);
}
else {
throw new RuntimeException("propertyColumn must be a child of a tableModel");
}
}
});
registerFactory("closureColumn", new Factory() {
public Object newInstance(Map properties) {
Object current = getCurrent();
if (current instanceof DefaultTableModel) {
DefaultTableModel model = (DefaultTableModel) current;
Object header = properties.remove("header");
if (header == null) {
header = "";
}
Closure readClosure = (Closure) properties.remove("read");
if (readClosure == null) {
throw new IllegalArgumentException("Must specify 'read' Closure property for a closureColumn");
}
Closure writeClosure = (Closure) properties.remove("write");
Class type = (Class) properties.remove("type");
if (type == null) {
type = Object.class;
}
return model.addClosureColumn(header, readClosure, writeClosure, type);
}
else {
throw new RuntimeException("propertyColumn must be a child of a tableModel");
}
}
});
//Standard Layouts
registerBeanFactory("borderLayout", BorderLayout.class);
registerBeanFactory("cardLayout", CardLayout.class);
registerBeanFactory("flowLayout", FlowLayout.class);
registerBeanFactory("gridBagLayout", GridBagLayout.class);
registerBeanFactory("gridLayout", GridLayout.class);
registerBeanFactory("overlayLayout", OverlayLayout.class);
registerBeanFactory("springLayout", SpringLayout.class);
registerBeanFactory("gridBagConstraints", GridBagConstraints.class);
registerBeanFactory("gbc", GridBagConstraints.class); // shortcut name
// box layout
registerFactory("boxLayout", new Factory() {
public Object newInstance(Map properties)
throws InstantiationException, InstantiationException, IllegalAccessException {
return createBoxLayout(properties);
}
});
// Box related layout components
registerFactory("hbox", new Factory() {
public Object newInstance(Map properties) {
return Box.createHorizontalBox();
}
});
registerFactory("hglue", new Factory() {
public Object newInstance(Map properties) {
return Box.createHorizontalGlue();
}
});
registerFactory("hstrut", new Factory() {
public Object newInstance(Map properties) {
try {
Object num = properties.remove("width");
if (num instanceof Number) {
return Box.createHorizontalStrut(((Number)num).intValue());
} else {
return Box.createHorizontalStrut(6);
}
} catch (RuntimeException re) {
re.printStackTrace(System.out);
throw re;
}
}
});
registerFactory("vbox", new Factory() {
public Object newInstance(Map properties) {
return Box.createVerticalBox();
}
});
registerFactory("vglue", new Factory() {
public Object newInstance(Map properties) {
return Box.createVerticalGlue();
}
});
registerFactory("vstrut", new Factory() {
public Object newInstance(Map properties) {
Object num = properties.remove("height");
if (num instanceof Number) {
return Box.createVerticalStrut(((Number)num).intValue());
} else {
return Box.createVerticalStrut(6);
}
}
});
registerFactory("glue", new Factory() {
public Object newInstance(Map properties) {
return Box.createGlue();
}
});
registerFactory("rigidArea", new Factory() {
public Object newInstance(Map properties) {
Dimension dim;
Object o = properties.remove("size");
if (o instanceof Dimension) {
dim = (Dimension) o;
} else {
int w, h;
o = properties.remove("width");
w = ((o instanceof Number)) ? ((Number)o).intValue() : 6;
o = properties.remove("height");
h = ((o instanceof Number)) ? ((Number)o).intValue() : 6;
dim = new Dimension(w, h);
}
return Box.createRigidArea(dim);
}
});
// table layout
registerBeanFactory("tableLayout", TableLayout.class);
registerFactory("tr", new Factory() {
public Object newInstance(Map properties) {
Object parent = getCurrent();
if (parent instanceof TableLayout) {
return new TableLayoutRow((TableLayout) parent);
}
else {
throw new RuntimeException("'tr' must be within a 'tableLayout'");
}
}
});
registerFactory("td", new Factory() {
public Object newInstance(Map properties) {
Object parent = getCurrent();
if (parent instanceof TableLayoutRow) {
return new TableLayoutCell((TableLayoutRow) parent);
}
else {
throw new RuntimeException("'td' must be within a 'tr'");
}
}
});
}
protected Object createBoxLayout(Map properties) {
Object parent = getCurrent();
if (parent instanceof Container) {
Object axisObject = properties.remove("axis");
int axis = BoxLayout.X_AXIS;
if (axisObject != null) {
Integer i = (Integer) axisObject;
axis = i.intValue();
}
Container target = (Container) parent;
if (target instanceof RootPaneContainer) {
target = ((RootPaneContainer) target).getContentPane();
}
BoxLayout answer = new BoxLayout(target, axis);
// now lets try set the layout property
InvokerHelper.setProperty(parent, "layout", answer);
return answer;
}
else {
throw new RuntimeException("Must be nested inside a Container");
}
}
protected Object createDialog(Map properties) {
JDialog dialog;
Object owner = properties.remove("owner");
// if owner not explicit, use the last window type in the list
if ((owner == null) && !containingWindows.isEmpty()) {
owner = containingWindows.getLast();
}
if (owner instanceof Frame) {
dialog = new JDialog((Frame) owner);
}
else if (owner instanceof Dialog) {
dialog = new JDialog((Dialog) owner);
}
else {
dialog = new JDialog();
}
containingWindows.add(dialog);
return dialog;
}
/**
* Uses 'format," or "value," (in order)
*
*/
protected Object createFormattedTextField(Map properties) {
JFormattedTextField ftf;
if (properties.containsKey("format")) {
ftf = new JFormattedTextField((Format) properties.remove("format"));
}
else if (properties.containsKey("value")) {
ftf = new JFormattedTextField(properties.remove("value"));
}
else {
ftf = new JFormattedTextField();
}
return ftf;
}
protected Object createFrame(Map properties) {
JFrame frame = new JFrame();
containingWindows.add(frame);
return frame;
}
protected Object createWindow(Map properties) {
JWindow window;
Object owner = properties.remove("owner");
// if owner not explicit, use the last window type in the list
if ((owner == null) && !containingWindows.isEmpty()) {
owner = containingWindows.getLast();
}
if (owner instanceof Frame) {
window = new JWindow((Frame) owner);
}
else if (owner instanceof Window) {
window = new JWindow((Window) owner);
}
else {
window = new JWindow();
}
containingWindows.add(window);
return window;
}
protected Object createComboBox(Map properties) {
Object items = properties.remove("items");
if (items instanceof Vector) {
return new JComboBox((Vector) items);
}
else if (items instanceof List) {
List list = (List) items;
return new JComboBox(list.toArray());
}
else if (items instanceof Object[]) {
return new JComboBox((Object[]) items);
}
else {
return new JComboBox();
}
}
protected void registerBeanFactory(String name, final Class beanClass) {
registerFactory(name, new Factory() {
public Object newInstance(Map properties) throws InstantiationException, IllegalAccessException {
return beanClass.newInstance();
}
});
}
protected void registerFactory(String name, Factory factory) {
factories.put(name, factory);
}
}