summaryrefslogtreecommitdiff
path: root/wizards/com/sun/star/wizards/ui/event/DataAware.java
diff options
context:
space:
mode:
Diffstat (limited to 'wizards/com/sun/star/wizards/ui/event/DataAware.java')
-rw-r--r--wizards/com/sun/star/wizards/ui/event/DataAware.java365
1 files changed, 365 insertions, 0 deletions
diff --git a/wizards/com/sun/star/wizards/ui/event/DataAware.java b/wizards/com/sun/star/wizards/ui/event/DataAware.java
new file mode 100644
index 000000000000..b81b8e71bcdb
--- /dev/null
+++ b/wizards/com/sun/star/wizards/ui/event/DataAware.java
@@ -0,0 +1,365 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.wizards.ui.event;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * @author rpiterman
+ * DataAware objects are used to live-synchronize UI and DataModel/DataObject.
+ * It is used as listener on UI events, to keep the DataObject up to date.
+ * This class, as a base abstract class, sets a frame of functionality,
+ * delegating the data Object get/set methods to a Value object,
+ * and leaving the UI get/set methods abstract.
+ * Note that event listenning is *not* a part of this model.
+ * the updateData() or updateUI() methods should be porogramatically called.
+ * in child classes, the updateData() will be binded to UI event calls.
+ * <br><br>
+ * This class holds references to a Data Object and a Value object.
+ * The Value object "knows" how to get and set a value from the
+ * Data Object.
+ */
+public abstract class DataAware {
+
+ /**
+ * this is the data object.
+ */
+ protected Object dataObject;
+ //protected Method setMethod;
+ //protected Method getMethod;
+ /**
+ * A Value Object knows how to get/set a value
+ * from/to the data object.
+ */
+ protected Value value;
+
+ /**
+ * creates a DataAware object for the given data object and Value object.
+ * @param dataObject_
+ * @param value_
+ */
+ protected DataAware(Object dataObject_, Value value_) {
+ dataObject = dataObject_;
+ value = value_;
+ //getMethod = createGetMethod(dataPropName, dataObject);
+ //setMethod = createSetMethod(dataPropName, dataObject, getMethod.getReturnType());
+ }
+
+ /**
+ * returns the data object.
+ * @return
+ */
+ public Object getDataObject() {
+ return dataObject;
+ }
+
+ /**
+ * sets a new data object. Optionally
+ * update the UI.
+ * @param obj the new data object.
+ * @param updateUI if true updateUI() will be called.
+ */
+ public void setDataObject(Object obj, boolean updateUI) {
+
+ if (obj != null && !value.isAssignable(obj.getClass()))
+ throw new ClassCastException("can not cast new DataObject to original Class");
+
+ dataObject = obj;
+
+ if (updateUI)
+ updateUI();
+
+ }
+
+ /**
+ * Sets the given value to the data object.
+ * this method delegates the job to the
+ * Value object, but can be overwritten if
+ * another kind of Data is needed.
+ * @param newValue the new value to set to the DataObject.
+ */
+ protected void setToData(Object newValue) {
+ value.set(newValue,getDataObject());
+ }
+
+ /**
+ * gets the current value from the data obejct.
+ * this method delegates the job to
+ * the value object.
+ * @return the current value of the data object.
+ */
+ protected Object getFromData() {
+ return value.get(getDataObject());
+ }
+
+ /**
+ * sets the given value to the UI control
+ * @param newValue the value to set to the ui control.
+ */
+ protected abstract void setToUI(Object newValue);
+
+ /**
+ * gets the current value from the UI control.
+ * @return the current value from the UI control.
+ */
+ protected abstract Object getFromUI();
+
+ /**
+ * updates the UI control according to the
+ * current state of the data object.
+ */
+ public void updateUI() {
+ Object data = getFromData();
+ Object ui = getFromUI();
+ if (!equals(data, ui))
+ try {
+ setToUI(data);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ //TODO tell user...
+ }
+ enableControls(data);
+ }
+
+ /**
+ * enables
+ * @param currentValue
+ */
+ protected void enableControls(Object currentValue) {
+ }
+
+ /**
+ * updates the DataObject according to
+ * the current state of the UI control.
+ */
+ public void updateData() {
+ Object data = getFromData();
+ Object ui = getFromUI();
+ if (!equals(data, ui))
+ setToData(ui);
+ enableControls(ui);
+ }
+
+ public interface Listener {
+ public void eventPerformed(Object event);
+ }
+
+ /**
+ * compares the two given objects.
+ * This method is null safe and returns true also if both are null...
+ * If both are arrays, treats them as array of short and compares them.
+ * @param a first object to compare
+ * @param b second object to compare.
+ * @return true if both are null or both are equal.
+ */
+ protected boolean equals(Object a, Object b) {
+ if (a == null && b == null)
+ return true;
+ if (a == null || b == null)
+ return false;
+ if (a.getClass().isArray()) {
+ if (b.getClass().isArray())
+ return Arrays.equals((short[]) a, (short[]) b);
+ else
+ return false;
+ }
+ return a.equals(b);
+ }
+
+ /**
+ * given a collection containing DataAware objects,
+ * calls updateUI() on each memebr of the collection.
+ * @param dataAwares a collection containing DataAware objects.
+ */
+ public static void updateUI(Collection dataAwares) {
+ for (Iterator i = dataAwares.iterator(); i.hasNext();)
+ ((DataAware) i.next()).updateUI();
+ }
+
+ public static void updateData(Collection dataAwares) {
+ for (Iterator i = dataAwares.iterator(); i.hasNext();)
+ ((DataAware) i.next()).updateData();
+ }
+
+ /**
+ * /**
+ * Given a collection containing DataAware objects,
+ * sets the given DataObject to each DataAware object
+ * in the given collection
+ * @param dataAwares a collection of DataAware objects.
+ * @param dataObject new data object to set to the DataAware objects in the given collection.
+ * @param updateUI if true, calls updateUI() on each DataAware object.
+ */public static void setDataObject(Collection dataAwares, Object dataObject, boolean updateUI) {
+ for (Iterator i = dataAwares.iterator(); i.hasNext();)
+ ((DataAware) i.next()).setDataObject(dataObject, updateUI);
+ }
+
+ /**
+ * Value objects read and write a value from and
+ * to an object. Typically using reflection and JavaBeans properties
+ * or directly using memeber reflection API.
+ * DataAware delegates the handling of the DataObject
+ * to a Value object.
+ * 2 implementations currently exist: PropertyValue,
+ * using JavaBeans properties reflection, and DataAwareFields classes
+ * which implement different memeber types.
+ */
+ public interface Value {
+ /**
+ * gets a value from the given object.
+ * @param target the object to get the value from.
+ * @return the value from the given object.
+ */
+ public Object get(Object target);
+ /**
+ * sets a value to the given object.
+ * @param value the value to set to the object.
+ * @param target the object to set the value to.
+ */
+ public void set(Object value, Object target);
+ /**
+ * checks if this Value object can handle
+ * the given object type as a target.
+ * @param type the type of a target to check
+ * @return true if the given class is acceptible for
+ * the Value object. False if not.
+ */
+ public boolean isAssignable(Class type);
+ }
+
+ /**
+ * implementation of Value, handling JavaBeans properties through
+ * reflection.
+ * This Object gets and sets a value a specific
+ * (JavaBean-style) property on a given object.
+ * @author rp143992
+ */
+ public static class PropertyValue implements Value {
+ /**
+ * the get method of the JavaBean-style property
+ */
+ private Method getMethod;
+ /**
+ * the set method of the JavaBean-style property
+ */
+ private Method setMethod;
+
+ /**
+ * creates a PropertyValue for the property with
+ * the given name, of the given JavaBean object.
+ * @param propertyName the property to access. Must be a Cup letter (e.g. "Name" for getName() and setName("..."). )
+ * @param propertyOwner the object which "own" or "contains" the property.
+ */
+ public PropertyValue(String propertyName, Object propertyOwner) {
+ getMethod = createGetMethod(propertyName, propertyOwner);
+ setMethod = createSetMethod(propertyName, propertyOwner, getMethod.getReturnType());
+ }
+
+ /**
+ * called from the constructor, and creates a get method reflection object
+ * for the given property and object.
+ * @param propName the property name0
+ * @param obj the object which contains the property.
+ * @return the get method reflection object.
+ */
+ private static Class[] EMPTY_ARRAY = new Class[0];
+
+ protected Method createGetMethod(String propName, Object obj)
+ {
+ Method m = null;
+ try
+ { //try to get a "get" method.
+
+ m = obj.getClass().getMethod("get" + propName, EMPTY_ARRAY);
+ }
+ catch (NoSuchMethodException ex1)
+ {
+ throw new IllegalArgumentException("get" + propName + "() method does not exist on " + obj.getClass().getName());
+ }
+ return m;
+ }
+
+ /* (non-Javadoc)
+ * @see com.sun.star.wizards.ui.event.DataAware.Value#get(java.lang.Object)
+ */
+ public Object get(Object target) {
+ try {
+ return getMethod.invoke(target, EMPTY_ARRAY);
+ } catch (IllegalAccessException ex1) {
+ ex1.printStackTrace();
+ } catch (InvocationTargetException ex2) {
+ ex2.printStackTrace();
+ } catch (NullPointerException npe) {
+ if (getMethod.getReturnType().equals(String.class))
+ return "";
+ if (getMethod.getReturnType().equals(Short.class))
+ return new Short((short) 0);
+ if (getMethod.getReturnType().equals(Integer.class))
+ return new Integer(0);
+ if (getMethod.getReturnType().equals(short[].class))
+ return new short[0];
+ }
+ return null;
+
+ }
+
+ protected Method createSetMethod(String propName, Object obj, Class paramClass) {
+ Method m = null;
+ try {
+ m = obj.getClass().getMethod("set" + propName, new Class[] { paramClass });
+ } catch (NoSuchMethodException ex1) {
+ throw new IllegalArgumentException("set" + propName + "(" + getMethod.getReturnType().getName() + ") method does not exist on " + obj.getClass().getName());
+ }
+ return m;
+ }
+
+ /* (non-Javadoc)
+ * @see com.sun.star.wizards.ui.event.DataAware.Value#set(java.lang.Object, java.lang.Object)
+ */
+ public void set(Object value, Object target) {
+ try {
+ setMethod.invoke(target, new Object[] {value});
+ } catch (IllegalAccessException ex1) {
+ ex1.printStackTrace();
+ } catch (InvocationTargetException ex2) {
+ ex2.printStackTrace();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see com.sun.star.wizards.ui.event.DataAware.Value#isAssignable(java.lang.Class)
+ */
+ public boolean isAssignable(Class type) {
+ return getMethod.getDeclaringClass().isAssignableFrom(type) &&
+ setMethod.getDeclaringClass().isAssignableFrom(type);
+ }
+ }
+}