/*
Launch4j (http://launch4j.sourceforge.net/)
Cross-platform Java application wrapper for creating Windows native executables.
Copyright (C) 2004, 2006 Grzegorz Kowal
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* Created on Apr 30, 2005
*/
package net.sf.launch4j.binding;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.swing.JComponent;
import javax.swing.JRadioButton;
import javax.swing.JTextArea;
import javax.swing.JToggleButton;
import javax.swing.text.JTextComponent;
import org.apache.commons.beanutils.PropertyUtils;
/**
* Creates and handles bindings.
*
* @author Copyright (C) 2005 Grzegorz Kowal
*/
public class Bindings implements PropertyChangeListener {
private final Map _bindings = new HashMap();
private final Map _optComponents = new HashMap();
private boolean _modified = false;
/**
* Used to track component modifications.
*/
public void propertyChange(PropertyChangeEvent evt) {
if ("AccessibleValue".equals(evt.getPropertyName()) //$NON-NLS-1$
|| "AccessibleText".equals(evt.getPropertyName())) { //$NON-NLS-1$
_modified = true;
}
}
/**
* Any of the components modified?
*/
public boolean isModified() {
return _modified;
}
public Binding getBinding(String property) {
return (Binding) _bindings.get(property);
}
private void registerPropertyChangeListener(JComponent c) {
c.getAccessibleContext().addPropertyChangeListener(this);
}
private void registerPropertyChangeListener(JComponent[] cs) {
for (int i = 0; i < cs.length; i++) {
cs[i].getAccessibleContext().addPropertyChangeListener(this);
}
}
private boolean isPropertyNull(IValidatable bean, Binding b) {
try {
for (Iterator iter = _optComponents.keySet().iterator(); iter.hasNext();) {
String property = (String) iter.next();
if (b.getProperty().startsWith(property)) {
return PropertyUtils.getProperty(bean, property) == null;
}
}
return false;
} catch (Exception e) {
throw new BindingException(e);
}
}
/**
* Enables or disables all components bound to properties that begin with given prefix.
*/
public void setComponentsEnabled(String prefix, boolean enabled) {
for (Iterator iter = _bindings.values().iterator(); iter.hasNext();) {
Binding b = (Binding) iter.next();
if (b.getProperty().startsWith(prefix)) {
b.setEnabled(enabled);
}
}
}
/**
* Clear all components, set them to their default values.
* Clears the _modified flag.
*/
public void clear(IValidatable bean) {
for (Iterator iter = _optComponents.values().iterator(); iter.hasNext();) {
((Binding) iter.next()).clear(bean);
}
for (Iterator iter = _bindings.values().iterator(); iter.hasNext();) {
((Binding) iter.next()).clear(bean);
}
_modified = false;
}
/**
* Copies data from the Java Bean to the UI components.
* Clears the _modified flag.
*/
public void put(IValidatable bean) {
for (Iterator iter = _optComponents.values().iterator(); iter.hasNext();) {
((Binding) iter.next()).put(bean);
}
for (Iterator iter = _bindings.values().iterator(); iter.hasNext();) {
Binding b = (Binding) iter.next();
if (isPropertyNull(bean, b)) {
b.clear(null);
} else {
b.put(bean);
}
}
_modified = false;
}
/**
* Copies data from UI components to the Java Bean and checks it's class invariants.
* Clears the _modified flag.
* @throws InvariantViolationException
* @throws BindingException
*/
public void get(IValidatable bean) {
try {
for (Iterator iter = _optComponents.values().iterator(); iter.hasNext();) {
((Binding) iter.next()).get(bean);
}
for (Iterator iter = _bindings.values().iterator(); iter.hasNext();) {
Binding b = (Binding) iter.next();
if (!isPropertyNull(bean, b)) {
b.get(bean);
}
}
bean.checkInvariants();
for (Iterator iter = _optComponents.keySet().iterator(); iter.hasNext();) {
String property = (String) iter.next();
IValidatable component = (IValidatable) PropertyUtils.getProperty(bean, property);
if (component != null) {
component.checkInvariants();
}
}
_modified = false; // XXX
} catch (InvariantViolationException e) {
e.setBinding(getBinding(e.getProperty()));
throw e;
} catch (Exception e) {
throw new BindingException(e);
}
}
private Bindings add(Binding b) {
if (_bindings.containsKey(b.getProperty())) {
throw new BindingException(Messages.getString("Bindings.duplicate.binding")); //$NON-NLS-1$
}
_bindings.put(b.getProperty(), b);
return this;
}
/**
* Add an optional (nullable) Java Bean component of type clazz.
*/
public Bindings addOptComponent(String property, Class clazz, JToggleButton c,
boolean enabledByDefault) {
Binding b = new OptComponentBinding(this, property, clazz, c, enabledByDefault);
if (_optComponents.containsKey(property)) {
throw new BindingException(Messages.getString("Bindings.duplicate.binding")); //$NON-NLS-1$
}
_optComponents.put(property, b);
return this;
}
/**
* Add an optional (nullable) Java Bean component of type clazz.
*/
public Bindings addOptComponent(String property, Class clazz, JToggleButton c) {
return addOptComponent(property, clazz, c, false);
}
/**
* Handles JEditorPane, JTextArea, JTextField
*/
public Bindings add(String property, JTextComponent c, String defaultValue) {
registerPropertyChangeListener(c);
return add(new JTextComponentBinding(property, c, defaultValue));
}
/**
* Handles JEditorPane, JTextArea, JTextField
*/
public Bindings add(String property, JTextComponent c) {
registerPropertyChangeListener(c);
return add(new JTextComponentBinding(property, c, "")); //$NON-NLS-1$
}
/**
* Handles JToggleButton, JCheckBox
*/
public Bindings add(String property, JToggleButton c, boolean defaultValue) {
registerPropertyChangeListener(c);
return add(new JToggleButtonBinding(property, c, defaultValue));
}
/**
* Handles JToggleButton, JCheckBox
*/
public Bindings add(String property, JToggleButton c) {
registerPropertyChangeListener(c);
return add(new JToggleButtonBinding(property, c, false));
}
/**
* Handles JRadioButton
*/
public Bindings add(String property, JRadioButton[] cs, int defaultValue) {
registerPropertyChangeListener(cs);
return add(new JRadioButtonBinding(property, cs, defaultValue));
}
/**
* Handles JRadioButton
*/
public Bindings add(String property, JRadioButton[] cs) {
registerPropertyChangeListener(cs);
return add(new JRadioButtonBinding(property, cs, 0));
}
public Bindings add(String property, String stateProperty,
JToggleButton button, JTextArea textArea) {
registerPropertyChangeListener(button);
registerPropertyChangeListener(textArea);
return add(new OptListBinding(property, stateProperty, button, textArea));
}
}