DasIOException without detail message.
+ */
+ public DasIOException() {
+ }
+
+
+ /**
+ * Constructs an instance of DasIOException with the specified detail message.
+ * @param msg the detail message.
+ */
+ public DasIOException(String msg) {
+ super(msg);
+ }
+
+ public DasIOException(String msg, Throwable t) {
+ super(msg,t);
+ }
+
+ public DasIOException(java.io.IOException ex) {
+ super( ex.getMessage() );
+ initCause(ex);
+ }
+}
diff --git a/dasCore/src/main/java/org/das2/DasNameException.java b/dasCore/src/main/java/org/das2/DasNameException.java
new file mode 100644
index 000000000..a39b758cd
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/DasNameException.java
@@ -0,0 +1,40 @@
+/* File: DasNameException.java
+ * Copyright (C) 2002-2003 The University of Iowa
+ * Created by: Jeremy Faden NameContext defines the name space for a
+ * dasml/das2 application. Methods for querying values of properties are
+ * also provided.
+ *
+ * @author eew
+ */
+public class NameContext {
+
+ private static final String SIMPLE_NAME_STRING = "[A-Za-z][A-Za-z0-9_]*";
+ private static final String INDEX_STRING = "0|[1-9][0-9]*";
+ private static final String INDEXED_NAME_STRING
+ = "(" + SIMPLE_NAME_STRING + ")" + "\\[(" + INDEX_STRING + ")\\]";
+ private static final String QUALIFIED_NAME_STRING
+ = SIMPLE_NAME_STRING + "(\\." + SIMPLE_NAME_STRING + "|\\." + INDEXED_NAME_STRING + ")*";
+
+ public static final Pattern SIMPLE_NAME = Pattern.compile(SIMPLE_NAME_STRING);
+ public static final Pattern INDEXED_NAME = Pattern.compile(INDEXED_NAME_STRING);
+ public static final Pattern QUALIFIED_NAME = Pattern.compile(QUALIFIED_NAME_STRING);
+ public static final Pattern refPattern = Pattern.compile("\\$\\{([^\\}]+)\\}");
+ public static final Pattern intPattern = Pattern.compile("-?(0|[1-9][0-9]*)");
+ public static final Pattern floatPattern = Pattern.compile("-?[0-9]*(\\.[0-9]*)?([eE]-?[0-9]+)?");
+
+
+ private Map nameMap;
+ private Map propertyMap;
+
+ /** Creates a new instance of NameContext */
+ NameContext() {
+ nameMap = new HashMap();
+ propertyMap = new HashMap();
+ }
+
+ /** Associates a value with a name in this context. The name
+ * parameter must being with a letter and can only consist of alphanumeric
+ * characters and '_'.
+ * @param name the name for the value to be associated with
+ * @param value the value being named
+ */
+ public void put(String name, Object value) throws DasNameException {
+ Matcher m = SIMPLE_NAME.matcher(name);
+ if (m.matches()) {
+ nameMap.put(name, new WeakReference( value ) );
+ }
+ else {
+ throw new DasNameException(name + " must match " + SIMPLE_NAME_STRING);
+ }
+ }
+
+ public Object get(String name) throws DasPropertyException, InvocationTargetException {
+ if (name == null) {
+ throw new NullPointerException("name");
+ }
+ Matcher m = SIMPLE_NAME.matcher(name);
+ if (m.matches()) {
+ return ((WeakReference)nameMap.get(name)).get();
+ }
+ int index = name.lastIndexOf('.');
+ Object obj = get(name.substring(0, index));
+ String property = name.substring(index + 1);
+ m = INDEXED_NAME.matcher(property);
+ if (m.matches()) {
+ property = m.group(1);
+ index = Integer.parseInt(m.group(2));
+ return getIndexedPropertyValue(obj, property, index);
+ }
+ else {
+ return getPropertyValue(obj, property);
+ }
+ }
+
+ public void set(String name, Object value) throws InvocationTargetException, ParsedExpressionException, DasPropertyException, DasNameException {
+ if (name == null) {
+ throw new NullPointerException("name");
+ }
+ Matcher m = SIMPLE_NAME.matcher(name);
+ if (m.matches()) {
+ put(name, value);
+ }
+ int index = name.lastIndexOf('.');
+ Object obj = get(name.substring(0, index));
+ String property = name.substring(index + 1);
+ m = INDEXED_NAME.matcher(property);
+ if (m.matches()) {
+ property = m.group(1);
+ index = Integer.parseInt(m.group(2));
+ setIndexedPropertyValue(obj, property, index, value);
+ }
+ else {
+ setPropertyValue(obj, property, value);
+ }
+ }
+
+ public Object getPropertyValue(Object obj, String property) throws DasPropertyException, InvocationTargetException {
+ try {
+ Class type = obj.getClass();
+ maybeLoadPropertiesForClass(type);
+ Map map = (Map)propertyMap.get(type);
+ PropertyDescriptor pd = (PropertyDescriptor)map.get(property);
+ if (pd == null) {
+ throw new DasPropertyException(DasPropertyException.NOT_DEFINED, null, property);
+ }
+ Method readMethod = pd.getReadMethod();
+ return readMethod.invoke(obj);
+ }
+ catch (IllegalAccessException iae) {
+ throw new RuntimeException(iae);
+ }
+ }
+
+ public Object getIndexedPropertyValue(Object obj, String property, int index) throws DasPropertyException, InvocationTargetException {
+ try {
+ Class type = obj.getClass();
+ maybeLoadPropertiesForClass(type);
+ Map map = (Map)propertyMap.get(type);
+ PropertyDescriptor pd = (PropertyDescriptor)map.get(property);
+ if (pd == null) {
+ throw new DasPropertyException(DasPropertyException.NOT_DEFINED, null, property);
+ }
+ if (!(pd instanceof IndexedPropertyDescriptor)) {
+ throw new DasPropertyException(DasPropertyException.NOT_INDEXED, null, property);
+ }
+ IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor)pd;
+ Method readMethod = ipd.getIndexedReadMethod();
+ return readMethod.invoke(obj, new Object[] { new Integer(index) });
+ }
+ catch (IllegalAccessException iae) {
+ throw new RuntimeException(iae);
+ }
+ }
+
+ public void setPropertyValue(Object obj, String property, Object value) throws InvocationTargetException, ParsedExpressionException, DasPropertyException {
+ try {
+ Class type = obj.getClass();
+ maybeLoadPropertiesForClass(type);
+ Map map = (Map)propertyMap.get(type);
+ PropertyDescriptor pd = (PropertyDescriptor)map.get(property);
+ if (pd == null) {
+ throw new DasPropertyException(DasPropertyException.NOT_DEFINED, null, property);
+ }
+ Method writeMethod = pd.getWriteMethod();
+ if (writeMethod == null) {
+ throw new DasPropertyException(DasPropertyException.READ_ONLY, null, property);
+ }
+ Class propertyType = pd.getPropertyType();
+ if (value instanceof String) {
+ value = parseValue((String)value, propertyType);
+ }
+ if (!propertyType.isInstance(value)
+ && !(propertyType == boolean.class && value instanceof Boolean)
+ && !(propertyType == char.class && value instanceof Character)
+ && !(propertyType == double.class && value instanceof Double)
+ && !(propertyType == short.class && value instanceof Short)
+ && !(propertyType == int.class && value instanceof Integer)
+ && !(propertyType == float.class && value instanceof Float)
+ && !(propertyType == byte.class && value instanceof Byte)
+ && !(propertyType == long.class && value instanceof Long)) {
+ throw new DasPropertyException(DasPropertyException.TYPE_MISMATCH, null, property);
+ }
+ writeMethod.invoke(obj, new Object[] { value } );
+ }
+ catch (IllegalAccessException iae) {
+ throw new RuntimeException(iae);
+ }
+ }
+
+ public void setIndexedPropertyValue(Object obj, String property, int index, Object value) throws InvocationTargetException, ParsedExpressionException, DasPropertyException {
+ try {
+ Class type = obj.getClass();
+ maybeLoadPropertiesForClass(type);
+ Map map = (Map)propertyMap.get(type);
+ PropertyDescriptor pd = (PropertyDescriptor)map.get(property);
+ if (pd == null) {
+ throw new DasPropertyException(DasPropertyException.NOT_DEFINED, null, property);
+ }
+ if (!(pd instanceof IndexedPropertyDescriptor)) {
+ throw new DasPropertyException(DasPropertyException.NOT_INDEXED, null, property);
+ }
+ IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor)pd;
+ Method writeMethod = ipd.getIndexedWriteMethod();
+ if (writeMethod == null) {
+ throw new DasPropertyException(DasPropertyException.READ_ONLY, null, property);
+ }
+ Class propertyType = pd.getPropertyType();
+ if (value instanceof String) {
+ value = parseValue((String)value, propertyType);
+ }
+ if (!propertyType.isInstance(value)
+ && !(propertyType == boolean.class && value instanceof Boolean)
+ && !(propertyType == char.class && value instanceof Character)
+ && !(propertyType == double.class && value instanceof Double)
+ && !(propertyType == short.class && value instanceof Short)
+ && !(propertyType == int.class && value instanceof Integer)
+ && !(propertyType == float.class && value instanceof Float)
+ && !(propertyType == byte.class && value instanceof Byte)
+ && !(propertyType == long.class && value instanceof Long)) {
+ throw new DasPropertyException(DasPropertyException.TYPE_MISMATCH, null, property);
+ }
+ writeMethod.invoke(obj, new Object[] { new Integer(index), value });
+ }
+ catch (IllegalAccessException iae) {
+ throw new RuntimeException(iae);
+ }
+ }
+
+ private void maybeLoadPropertiesForClass(Class cl) {
+ try {
+ if (propertyMap.get(cl) == null) {
+ BeanInfo info = BeansUtil.getBeanInfo(cl);
+ HashMap map = new HashMap();
+ PropertyDescriptor[] properties = info.getPropertyDescriptors();
+ for (int i = 0; i < properties.length; i++) {
+ if (properties[i].getReadMethod() == null) {
+ continue;
+ }
+ if (properties[i] instanceof IndexedPropertyDescriptor) {
+ IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor)properties[i];
+ if (ipd.getIndexedReadMethod() == null) {
+ continue;
+ }
+ }
+ map.put(properties[i].getName(), properties[i]);
+ }
+ propertyMap.put(cl, map);
+ }
+ }
+ catch (IntrospectionException ie) {
+ }
+ }
+
+ public void remove(String name) {
+ nameMap.remove(name);
+ }
+
+ /**
+ * Parses the given String object in an attempt to
+ * produce the an object of the given type.
+ *
+ * @param valueString the given String
+ * @param type the given type
+ */
+ public Object parseValue(String valueString, Class type) throws org.das2.dasml.ParsedExpressionException, InvocationTargetException, DasPropertyException {
+ Object parsedValue;
+ valueString = replaceReferences(valueString);
+ if (type == String.class) {
+ return valueString;
+ }
+ else if (type == boolean.class || type == Boolean.class) {
+ if (valueString.equals("true")) return Boolean.TRUE;
+ if (valueString.equals("false")) return Boolean.FALSE;
+ ParsedExpression exp = new ParsedExpression(valueString);
+ Object o = exp.evaluate(this);
+ if (!(o instanceof Boolean)) throw new ParsedExpressionException("'" + valueString + "' does not evaluate to a boolean value");
+ return o;
+ }
+ else if (type == int.class || type == Integer.class) {
+ if (intPattern.matcher(valueString).matches()) {
+ return new Integer(valueString);
+ }
+ ParsedExpression exp = new ParsedExpression(valueString);
+ Object o = exp.evaluate(this);
+ if (!(o instanceof Number)) throw new ParsedExpressionException("'" + valueString + "' does not evaluate to a numeric value");
+ return (o instanceof Integer ? (Integer)o : new Integer(((Number)o).intValue()));
+ }
+ else if (type == long.class || type == Long.class) {
+ if (intPattern.matcher(valueString).matches()) {
+ parsedValue = new Long(valueString);
+ }
+ ParsedExpression exp = new ParsedExpression(valueString);
+ Object o = exp.evaluate(this);
+ if (!(o instanceof Number)) throw new ParsedExpressionException("'" + valueString + "' does not evaluate to a numeric value");
+ return new Long(((Number)o).longValue());
+ }
+ else if (type == float.class || type == Float.class) {
+ if (floatPattern.matcher(valueString).matches()) {
+ parsedValue = new Float(valueString);
+ }
+ ParsedExpression exp = new ParsedExpression(valueString);
+ Object o = exp.evaluate(this);
+ if (!(o instanceof Number)) throw new ParsedExpressionException("'" + valueString + "' does not evaluate to a numeric value");
+ return new Float(((Number)o).floatValue());
+ }
+ else if (type == double.class || type == Double.class) {
+ if (floatPattern.matcher(valueString).matches()) {
+ parsedValue = new Double(valueString);
+ }
+ ParsedExpression exp = new ParsedExpression(valueString);
+ Object o = exp.evaluate(this);
+ if (!(o instanceof Number)) throw new ParsedExpressionException("'" + valueString + "' does not evaluate to a numeric value");
+ return (o instanceof Double ? (Double)o : new Double(((Number)o).doubleValue()));
+ }
+ else if (type == Datum.class) {
+ try {
+ return TimeUtil.create(valueString);
+ }
+ catch ( java.text.ParseException ex ) {
+ try {
+ return Datum.create(Double.parseDouble(valueString));
+ }
+ catch (NumberFormatException iae) {
+ throw new ParsedExpressionException(valueString + " cannot be parsed as a Datum");
+ }
+ }
+
+ }
+ else {
+ throw new IllegalStateException(type.getName() + " is not a recognized type");
+ }
+ }
+
+ protected String replaceReferences(String str) throws DasPropertyException, InvocationTargetException {
+ Matcher matcher = refPattern.matcher(str);
+ while (matcher.find()) {
+ String name = matcher.group(1).trim();
+ Object value = get(name);
+ str = matcher.replaceFirst(value.toString());
+ matcher.reset(str);
+ }
+ return str;
+ }
+
+ public String toString() {
+ return getClass().getName() + nameMap.keySet().toString();
+ }
+}
diff --git a/dasCore/src/main/java/org/das2/apiProblems.txt b/dasCore/src/main/java/org/das2/apiProblems.txt
new file mode 100644
index 000000000..b958202f4
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/apiProblems.txt
@@ -0,0 +1,18 @@
+1. event package
+ 1. mouse events / drag renderers / mouse modules
+ 1. difficult to reuse existing objects because a lack of composition.
+ 2. too much typeness in drag renderers, should let composing code enforce typeness.
+ 3. poor definition of the role of each class.
+ 4. need definition of how key strokes can be used, which are used by the DMIA which
+ can the mousemodule use.
+
+2. system/das package
+ 1. DasApplication
+ 1. DasApplication.getDefaultApplication() does not allow for multiple applications to
+ run within the same java context, as in a web applications server.
+ 2. Perhaps the application object should be explicitly created, then canvases and JPanels attached to
+ it. An implicit application object, perhaps the legacy DasApplication.getDefaultApplication()
+ could be used as well.
+
+
+
\ No newline at end of file
diff --git a/dasCore/src/main/java/org/das2/beans/AccessLevelBeanInfo.java b/dasCore/src/main/java/org/das2/beans/AccessLevelBeanInfo.java
new file mode 100644
index 000000000..d048e1f38
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/beans/AccessLevelBeanInfo.java
@@ -0,0 +1,347 @@
+/* File: AccessLevelBeanInfo.java
+ * Copyright (C) 2002-2003 The University of Iowa
+ * Created by: Jeremy Faden properties array must be of the type
+ * Object[] with the following format:
+ * { propertyName, accessorMethod, mutatorMethod, accessLevel}
+ * where the elements have the following meaning.
+ * propertyName - A String naming the property being specified.accessorMethod - A String specifying the name of the read method
+ * for this property.mutatorMethod - A String specifying the name of the write method
+ * for this propertyaccessLevel - A org.das2.beans.AccessLevelBeanInfo.AccessLevel instance specifying
+ * the access level for this property.Provides BeanInfos that wrap das2 objects to control the properties +that are exposed. When the PropertyEditor is used to edit an object, it +uses java bean conventions for identifying its properties. Properties of +objects that do not have a corresponding BeanInfo are discovered using the +java beans convention of looking for methods +of the form getX() and setX() where X is the property name.
+The BeanInfos also provide a mechanism where the writable property set can be +reduced depending on the role of the person using the application. For example, +application developers would have the ability to freely adjust all parameters, +such as layout, datasets and rendering methods, while end users would only be +able to control the timeaxis. This mechanism has never been used, but it's worth +mentioning since the implementing code is in there. +
+Also a utility class, BeansUtil, provides methods for discovering object properties. + +Note that this package might be removed in a future version of das2. We +plan to make everything more beany, and the BeanInfos may be moved into the same directory +as the Bean objects. Also, we expect that Java 5 annotations might be used to implement the +access levels and other property metadata. Also, XMLEncoder might be used to encode +the beans, instead of SerializeUtil.
+ \ No newline at end of file diff --git a/dasCore/src/main/java/org/das2/beans/scratchpad.txt b/dasCore/src/main/java/org/das2/beans/scratchpad.txt new file mode 100644 index 000000000..5a54ad42b --- /dev/null +++ b/dasCore/src/main/java/org/das2/beans/scratchpad.txt @@ -0,0 +1,43 @@ +Definition of a property. A property is an adjustable parameter of an object. A property may be read-only and used to peek +at the status of an object. A property may be another object. A property may be an array of objects. This is all beany. + +1. Attributes of Properties. + 1. Security model + 1. that allows us to restrict which properties may be adjusted by the end-user. + 2. that allows us to restrict the properties which may be stored persistently. + 2. Properties should be editable and serializable "for free," meaning that no effort is required to get these features for new objects. + 3. Properties of new objects should be discovered in a reasonable and safe way. + +2. Example uses. + 1. application development + 1. layout, labels, colorbar, etc are set interactively by the application developer. + 2. satisfied, the developer releases the application, but limiting adjustable properties to the time axis range. + 2. non-persistent properties + 1. the developer wishes to add a new parameter for testing which is used interactively + 2. this parameter should not be serialized to persistent storage, however, since its meaning may change. + +3. discovery of properties. + 1. a "BeanInfo" object for the object class identifies the properties explicitly + 2. or the java beans convention for getX/setX is used to identify implicit properties. + +4. Access Levels--not implemented + 1. ALL -- the property may be adjusted freely, no restrictions + 2. DEVELOPER -- adjustable by the application developer ( This is the default for implicit properties. ) + 3. END_USER -- adjustable by the end-user. + +5. Persistence. + 1. none -- the property should never be used as a part of the state. Including within session. + 2. transient -- the property is only persistent on a per-session basis. For example, undo/redo should include this. + 3. persistent -- the property may be serialized and stored. + +6. Arbitary xml to application + 1. bean requirements + 1. no-argument constructor + 2. properties adjusted in any order--this is a bean requirement because of property editor as well. + 3. must be named + 2. update messages + 1. propertyChanged messages used to implement bean inter-dependence. + 2. "listens to" notation needed. + 3. message-coalescing mechanism needs to be preserved. + 3. missing objects + 1. some sort of canvas layout manager that manages rows diff --git a/dasCore/src/main/java/org/das2/client/AccessDeniedException.java b/dasCore/src/main/java/org/das2/client/AccessDeniedException.java new file mode 100644 index 000000000..f1b8087fb --- /dev/null +++ b/dasCore/src/main/java/org/das2/client/AccessDeniedException.java @@ -0,0 +1,37 @@ +/* File: AccessDeniedException.java + * Copyright (C) 2002-2003 The University of Iowa + * Created by: Jeremy FadenDasServerNotFoundException without detail message.
+ */
+ public DasServerNotFoundException() {
+ }
+
+
+ /**
+ * Constructs an instance of DasServerNotFoundException with the specified detail message.
+ * @param msg the detail message.
+ */
+ public DasServerNotFoundException(String msg) {
+ super(msg);
+ }
+}
diff --git a/dasCore/src/main/java/org/das2/client/DataSetDescriptorNotAvailableException.java b/dasCore/src/main/java/org/das2/client/DataSetDescriptorNotAvailableException.java
new file mode 100644
index 000000000..f7cff06b9
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/client/DataSetDescriptorNotAvailableException.java
@@ -0,0 +1,42 @@
+/* File: DataSetDescriptorNotAvailableException.java
+ * Copyright (C) 2002-2003 The University of Iowa
+ * Created by: Jeremy Faden DataSetDescriptionNotAvailableException without detail message.
+ */
+
+ /**
+ * Constructs an instance of DataSetDescriptionNotAvailableException with the specified detail message.
+ * @param msg the detail message.
+ */
+ public DataSetDescriptorNotAvailableException(String msg) {
+ super(msg);
+ }
+}
diff --git a/dasCore/src/main/java/org/das2/client/DataSetStreamHandler.java b/dasCore/src/main/java/org/das2/client/DataSetStreamHandler.java
new file mode 100755
index 000000000..f7194cf53
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/client/DataSetStreamHandler.java
@@ -0,0 +1,403 @@
+/* File: DataSetStreamHandler.java
+ * Copyright (C) 2002-2003 The University of Iowa
+ *
+ * Created on February 11, 2004, 4:26 PM
+ * by Edward E. West NoSuchDataSet without detail message.
+ */
+ public NoSuchDataSetException() {
+ }
+
+
+ /**
+ * Constructs an instance of NoSuchDataSet with the specified detail message.
+ * @param msg the detail message.
+ */
+ public NoSuchDataSetException(String msg) {
+ super(msg);
+ }
+}
diff --git a/dasCore/src/main/java/org/das2/client/StandardDataStreamSource.java b/dasCore/src/main/java/org/das2/client/StandardDataStreamSource.java
new file mode 100644
index 000000000..645c949bb
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/client/StandardDataStreamSource.java
@@ -0,0 +1,40 @@
+/* File: StandardDataStreamSource.java
+ * Copyright (C) 2002-2003 The University of Iowa
+ * Created by: Jeremy Faden StreamDataSetDescriptor
+ * from the specified file
+ */
+ protected StreamDataSetDescriptor(Map properties) {
+ setProperties(properties);
+ }
+
+ protected StreamDataSetDescriptor(Map properties, boolean legacy) {
+ setProperties(properties, legacy);
+ }
+
+ public StreamDataSetDescriptor(StreamDescriptor sd, StandardDataStreamSource sdss) {
+ this(sd.getProperties(), "true".equals(sd.getProperty("legacy")));
+ this.standardDataStreamSource = sdss;
+ }
+
+ public void setStandardDataStreamSource(StandardDataStreamSource sdss) {
+ this.standardDataStreamSource= sdss;
+ }
+
+ public StandardDataStreamSource getStandardDataStreamSource() {
+ return this.standardDataStreamSource;
+ }
+
+ protected void setProperties(Map properties, boolean legacy) {
+ super.setProperties(properties);
+ if (properties.containsKey("form") && properties.get("form").equals("x_multi_y")
+ && properties.containsKey("items")) {
+ setDefaultCaching(false);
+ }
+ if (legacy) {
+ defaultPacketDescriptor = PacketDescriptor.createLegacyPacketDescriptor(properties);
+ }
+ }
+
+ @Override
+ protected void setProperties( Map properties ) {
+ setProperties(properties, false);
+ }
+
+ private ByteBuffer getByteBuffer(InputStream in) throws DasException {
+ byte[] data = readBytes(in);
+ ByteBuffer buffer = ByteBuffer.wrap(data);
+ return buffer;
+ }
+
+ /**
+ * Auxiliary method used by readDoubles(InputStream, Object, Datum, Datum);
+ *
+ * Read data for the given start and end dates and returns an array of bytes
+ *
+ * @author eew
+ * @throws java.io.IOException If there is an error getting data from the reader, and IOException is thrown
+ */
+ protected byte[] readBytes(InputStream in) throws DasException {
+ LinkedList list = new LinkedList();
+ byte[] data = new byte[4096];
+ int bytesRead=0;
+ int totalBytesRead=0;
+ int lastBytesRead = -1;
+ int offset=0;
+ long time = System.currentTimeMillis();
+
+ try {
+ bytesRead= in.read(data,offset,4096-offset);
+ while (bytesRead != -1) {
+ int bytesSoFar = totalBytesRead;
+ offset+=bytesRead;
+ lastBytesRead= offset;
+ if (offset==4096) {
+ list.addLast(data);
+ data = new byte[4096];
+ offset=0;
+ }
+ totalBytesRead+= bytesRead;
+ bytesRead= in.read(data,offset,4096-offset);
+ }
+ } catch ( IOException e ) {
+ throw new DasIOException(e);
+ }
+
+ if (lastBytesRead>=0 && lastBytesRead<4096) {
+ list.addLast(data);
+ }
+
+ if (list.size()== 0) {
+ throw new DasIOException("Error reading data: no data available");
+ }
+ int dataLength = (list.size()-1)*4096 + lastBytesRead;
+ data = new byte[dataLength];
+ Iterator iterator = list.iterator();
+ for (int i = 0; i < list.size()-1; i++) {
+ System.arraycopy(list.get(i), 0, data, i*4096, 4096);
+ }
+ System.arraycopy(list.get(list.size()-1), 0, data, (list.size() - 1)*4096, lastBytesRead);
+ return data;
+ }
+
+ @Override
+ public String toString() {
+ return "dsd "+getDataSetID();
+ }
+
+ @Override
+ protected DataSet getDataSetImpl( Datum start, Datum end, Datum resolution, ProgressMonitor monitor ) throws DasException {
+ if ( resolution != null && !resolution.isFinite() ) throw new IllegalArgumentException( "resolution is not finite" );
+ InputStream in;
+ DataSet result;
+ if ( serverSideReduction ) {
+ logger.fine("getting stream from standard data stream source");
+ in= standardDataStreamSource.getReducedInputStream( this, start, end, resolution);
+ } else {
+ in= standardDataStreamSource.getInputStream( this, start, end );
+ }
+
+ logger.fine("reading stream");
+ result = getDataSetFromStream( in, start, end, monitor );
+ return result;
+ }
+
+ protected DataSet getDataSetFromStream(InputStream in, Datum start, Datum end, ProgressMonitor monitor ) throws DasException {
+ if ( monitor==null ) monitor= new NullProgressMonitor();
+
+ PushbackInputStream pin = new PushbackInputStream(in, 4096);
+ try {
+ byte[] four = new byte[4];
+ int bytesRead= pin.read(four);
+ logger.finer("read first four bytes bytesRead="+bytesRead);
+ if ( bytesRead!=4 ) {
+ logger.fine("no data returned from server");
+ throw new DasIOException( "No data returned from server" );
+ }
+
+ if (new String(four).equals("[00]")) {
+ logger.finer("got stream header [00]");
+ pin.unread(four);
+
+ if ( monitor.isCancelled() ) {
+ pin.close();
+ throw new InterruptedIOException("Operation cancelled");
+ }
+
+ final DasProgressMonitorInputStream mpin = new DasProgressMonitorInputStream(pin, monitor);
+ //InputStream mpin = pin;
+
+ logger.finer("creating Channel");
+ ReadableByteChannel channel = Channels.newChannel(mpin);
+
+ DataSetStreamHandler handler = new DataSetStreamHandler( properties, monitor ) {
+ public void streamDescriptor(StreamDescriptor sd) throws StreamException {
+ super.streamDescriptor( sd );
+ if ( super.taskSize!=-1 ) {
+ mpin.setEnableProgressPosition(false);
+ }
+ }
+ };
+
+ logger.finer("using StreamTool to read the stream");
+ StreamTool.readStream(channel, handler);
+ return handler.getDataSet();
+ }
+ else {
+ pin.unread(four);
+
+ if ( monitor.isCancelled() ) {
+ pin.close();
+ throw new InterruptedIOException("Operation cancelled");
+ }
+
+ monitor.started();
+
+ InputStream mpin = new DasProgressMonitorInputStream(pin, monitor);
+
+ if (getProperty("form").equals("x_tagged_y_scan")) {
+ return getLegacyTableDataSet(mpin, start);
+ }
+ else if (getProperty("form").equals("x_multi_y")) {
+ return getLegacyVectorDataSet(mpin, start);
+ }
+ else {
+ throw new IllegalStateException("Unrecognized data set type: " + getProperty("form"));
+ }
+ }
+ }
+ catch (UnsupportedEncodingException uee) {
+ //UTF-8 should be supported by all JVM's
+ throw new RuntimeException(uee);
+ }
+ catch (IOException ioe) {
+ throw new DasIOException(ioe);
+ }
+ catch ( StreamException se ) {
+ /* kludge for when an InterruptedIOException is caused by the user's cancel.
+ * TODO: This is danger code, because it masks the condition where the
+ * interruption happened for some other reason the user isn't aware of.
+ */
+ if ( se.getCause() instanceof InterruptedIOException ) {
+ DasException e= new CancelledOperationException();
+ e.initCause(se);
+ throw e;
+ } else {
+ throw se;
+ }
+ }
+ finally {
+ try { pin.close(); } catch (IOException ioe) {}
+ }
+ }
+
+ private static String getPacketID(byte[] four) throws DasException {
+ if ((four[0] == (byte)'[' && four[3] == (byte)']') || (four[0] == (byte)':' && four[3] == (byte)':')) {
+ return new String(new char[]{(char)four[1], (char)four[2]});
+ }
+ else {
+ throw new DasException("Invalid stream, expecting 4 byte header, encountered '" + new String(four) + "'");
+ }
+ }
+
+ private DataSet getLegacyVectorDataSet(InputStream in0, Datum start) throws DasException {
+ try {
+ PushbackInputStream in = new PushbackInputStream(in0, 50);
+ PacketDescriptor sd = getPacketDescriptor(in);
+ VectorDataSetBuilder builder = new VectorDataSetBuilder(start.getUnits(),Units.dimensionless); // Units will be set when "" is encountered
+ for (Iterator i = sd.getYDescriptors().iterator(); i.hasNext();) {
+ Object o = i.next();
+ if (o instanceof StreamMultiYDescriptor) {
+ StreamMultiYDescriptor y = (StreamMultiYDescriptor)o;
+ String name = y.getName();
+ if (name != null && !name.equals("")) {
+ builder.addPlane(name,y.getUnits());
+ } else if ( "".equals(name) ) {
+ builder.setYUnits(y.getUnits());
+ }
+ }
+ else {
+ throw new DasIOException("Invalid Stream Header: Non-Y-descriptor encountered");
+ }
+ }
+ StreamMultiYDescriptor[] yDescriptors = (StreamMultiYDescriptor[])sd.getYDescriptors().toArray(new StreamMultiYDescriptor[0]);
+ int planeCount = yDescriptors.length - 1;
+ String[] planeIDs = new String[planeCount];
+ int recordSize = sd.getXDescriptor().getSizeBytes() + yDescriptors[0].getSizeBytes();
+ for (int planeIndex = 0; planeIndex < planeCount; planeIndex++) {
+ planeIDs[planeIndex] = yDescriptors[planeIndex+1].getName();
+ recordSize += yDescriptors[planeIndex+1].getSizeBytes();
+ }
+ ByteBuffer data = getByteBuffer(in);
+ double timeBaseValue = start.doubleValue(start.getUnits());
+ Units offsetUnits = start.getUnits().getOffsetUnits();
+ UnitsConverter uc = sd.getXDescriptor().getUnits().getConverter(offsetUnits);
+ while (data.remaining() > recordSize) {
+ DatumVector vector = sd.getXDescriptor().read(data);
+ double xTag = timeBaseValue + vector.doubleValue(0, offsetUnits);
+ vector = yDescriptors[0].read(data);
+ double yValue = vector.doubleValue(0, yDescriptors[0].getUnits());
+ builder.insertY(xTag, yValue);
+ for (int planeIndex = 0; planeIndex < planeCount; planeIndex++) {
+ vector = yDescriptors[planeIndex + 1].read(data);
+ yValue = vector.doubleValue(0, yDescriptors[planeIndex + 1].getUnits());
+ builder.insertY(xTag, yValue, yDescriptors[planeIndex + 1].getName());
+ }
+ }
+
+ if ( properties.containsKey("x_sample_width") ) {
+ properties.put( "xTagWidth", Datum.create( ((Double)properties.get("x_sample_width")).doubleValue(),
+ Units.seconds ) );
+ }
+
+ builder.addProperties(properties);
+ VectorDataSet result = builder.toVectorDataSet();
+ return result;
+ }
+ catch (DasException de) {
+ de.printStackTrace();
+ throw de;
+ }
+ }
+
+ private DataSet getLegacyTableDataSet(InputStream in0, Datum start) throws DasException {
+ PushbackInputStream in= new PushbackInputStream(in0,50);
+ PacketDescriptor sd = getPacketDescriptor(in);
+ TableDataSetBuilder builder = new TableDataSetBuilder(start.getUnits(),Units.dimensionless,Units.dimensionless);
+ Units yUnits = Units.dimensionless;
+ Units zUnits= Units.dimensionless;
+
+ for (Iterator i = sd.getYDescriptors().iterator(); i.hasNext();) {
+ Object o = i.next();
+ if (o instanceof StreamYScanDescriptor) {
+ StreamYScanDescriptor scan = (StreamYScanDescriptor)o;
+ String name = scan.getName();
+ if (name != null && !name.equals("")) {
+ builder.addPlane(name,scan.getZUnits());
+ }
+ }
+ else {
+ throw new DasIOException("Invalid Stream Header: Non-yScan descriptor encountered");
+ }
+ }
+ StreamYScanDescriptor[] yScans = (StreamYScanDescriptor[])sd.getYDescriptors().toArray(new StreamYScanDescriptor[0]);
+ final int planeCount = yScans.length;
+ String[] planeIDs = new String[planeCount];
+ int recordSize = sd.getXDescriptor().getSizeBytes();
+ for (int planeIndex = 0; planeIndex < planeCount; planeIndex++) {
+ planeIDs[planeIndex] = yScans[planeIndex].getName();
+ recordSize += yScans[planeIndex].getSizeBytes();
+ }
+ ByteBuffer data = getByteBuffer(in);
+ double timeBaseValue= start.doubleValue(start.getUnits());
+ Units offsetUnits = start.getUnits().getOffsetUnits();
+ Units xdescUnits= sd.getXDescriptor().getUnits();
+ if ( xdescUnits==null ) xdescUnits= Units.seconds;
+ //UnitsConverter uc = xdescUnits.getConverter(offsetUnits);
+ double[] yCoordinates = yScans[0].getYTags();
+ DatumVector y = DatumVector.newDatumVector(yCoordinates, yUnits);
+
+ while (data.remaining() > recordSize) {
+ DatumVector vector = sd.getXDescriptor().read(data);
+ Datum xTag = start.add(vector.get(0));
+ DatumVector[] z = new DatumVector[planeCount];
+ for (int planeIndex = 0; planeIndex < planeCount; planeIndex++) {
+ z[planeIndex]= yScans[planeIndex].read(data);
+ }
+ builder.insertYScan(xTag, y, z, planeIDs);
+ }
+
+ if ( properties.containsKey("x_sample_width") ) {
+ properties.put( "xTagWidth", Datum.create( ((Double)properties.get("x_sample_width")).doubleValue(),
+ Units.seconds ) );
+ }
+
+ builder.addProperties(properties);
+ TableDataSet result = builder.toTableDataSet();
+ return result;
+ }
+
+ private static final byte[] HEADER = { (byte)'d', (byte)'a', (byte)'s', (byte)'2', (byte)0177, (byte)0177 };
+
+ private PacketDescriptor getPacketDescriptor(PushbackInputStream in)
+ throws DasIOException, StreamException
+ {
+ try {
+ byte[] four = new byte[HEADER.length];
+
+ int bytesRead = 0;
+ int totalBytesRead = 0;
+ do {
+ bytesRead = in.read(four, totalBytesRead, HEADER.length - totalBytesRead);
+ if (bytesRead != -1) totalBytesRead += bytesRead;
+ } while (totalBytesRead < HEADER.length && bytesRead != -1);
+ if (Arrays.equals(four, HEADER)) {
+ byte[] header = StreamTool.advanceTo(in, "\177\177".getBytes());
+ ByteArrayInputStream source = new ByteArrayInputStream(header);
+ DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ Document document = builder.parse(source);
+ Element docNode= document.getDocumentElement();
+ PacketDescriptor packetDescriptor= new PacketDescriptor(docNode);
+ return packetDescriptor;
+ }
+ else {
+ in.unread(four, 0, totalBytesRead);
+ return defaultPacketDescriptor;
+ }
+ }
+ catch ( ParserConfigurationException ex ) {
+ throw new IllegalStateException(ex.getMessage());
+ }
+ catch ( StreamTool.DelimeterNotFoundException dnfe) {
+ DasIOException dioe = new DasIOException(dnfe.getMessage());
+ dioe.initCause(dioe);
+ throw dioe;
+ }
+ catch ( SAXException ex ) {
+ DasIOException e= new DasIOException(ex.getMessage());
+ e.initCause(ex);
+ throw e;
+ }
+ catch ( IOException ex) {
+ throw new DasIOException(ex);
+ }
+ }
+
+ public boolean isRestrictedAccess() {
+ boolean result;
+ if (getProperty("groupAccess") != null) {
+ result= !("".equals(getProperty("groupAccess")));
+ } else {
+ result= false;
+ }
+ return result;
+ }
+
+ public void setServerSideReduction(boolean x) {
+ serverSideReduction= x;
+ }
+
+ public boolean isServerSideReduction() {
+ return serverSideReduction;
+ }
+
+ public PacketDescriptor getDefaultPacketDescriptor() {
+ return defaultPacketDescriptor;
+ }
+
+}
diff --git a/dasCore/src/main/java/org/das2/client/WebStandardDataStreamSource.java b/dasCore/src/main/java/org/das2/client/WebStandardDataStreamSource.java
new file mode 100755
index 000000000..e8eb94b07
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/client/WebStandardDataStreamSource.java
@@ -0,0 +1,483 @@
+/* File: WebStandardDataStreamSource.java
+ * Copyright (C) 2002-2003 The University of Iowa
+ * Created by: Jeremy Faden Provides classes for interacting with a das2Server, such as data set queries, +authorization, and server identity.
+Also support for reading Das2Streams and legacy +streams is found here. These classes should probably be moved to the stream package.
+ \ No newline at end of file diff --git a/dasCore/src/main/java/org/das2/components/AngleSpectrogramSlicer.java b/dasCore/src/main/java/org/das2/components/AngleSpectrogramSlicer.java new file mode 100644 index 000000000..2c83e5b5a --- /dev/null +++ b/dasCore/src/main/java/org/das2/components/AngleSpectrogramSlicer.java @@ -0,0 +1,248 @@ +/* File: HorizontalSpectrogramSlicer.java + * Copyright (C) 2002-2008 The University of Iowa + * Created by: Jeremy Fadenthis
+ */
+ public Component getCustomEditor() {
+ maybeInitGui();
+ return panel;
+ }
+
+ /**
+ * This PropertyEditor implementation does not support generating java
+ * code.
+ * @return The string "???"
+ */
+ public String getJavaInitializationString() {
+ return "???";
+ }
+
+ /**
+ * This PropertyEditor implementation does not support enumerated
+ * values.
+ * @return null
+ */
+ public String[] getTags() {
+ return null;
+ }
+
+ /** @see java.beans.PropertyEditor#isPaintable()
+ * @return false
+ */
+ public boolean isPaintable() {
+ return false;
+ }
+
+ /** Does nothing.
+ * @param g
+ * @param r
+ */
+ public void paintValue(Graphics g, Rectangle r) {
+ }
+
+ /* CellEditor stuff */
+ public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
+ setValue(value);
+ maybeInitGui();
+ return panel;
+ }
+
+ /**
+ */
+ public void addCellEditorListener(CellEditorListener l) {
+ if (listeners == null) {
+ listeners = new EventListenerList();
+ }
+ listeners.add(CellEditorListener.class, l);
+ }
+
+ /**
+ */
+ public void removeCellEditorListener(CellEditorListener l) {
+ if (listeners != null) {
+ listeners.remove(CellEditorListener.class, l);
+ }
+ }
+
+ /** @see javax.swing.CellEditor#isCellEditable(java.util.EventObject)
+ * @return true
+ */
+ public boolean isCellEditable(EventObject anEvent) {
+ return true;
+ }
+
+ /** @see javax.swing.CellEditor#shouldSelectCell(java.util.EventObject)
+ * @return true
+ */
+ public boolean shouldSelectCell(EventObject anEvent) {
+ return true;
+ }
+
+ /** Returns the value stored in this editor.
+ * @return the current value being edited
+ */
+ public Object getCellEditorValue() {
+ return getDatum();
+ }
+
+ public boolean stopCellEditing() {
+ if (getDatum() == null) {
+ return false;
+ }
+ fireEditingStopped();
+ return true;
+ }
+
+ public void cancelCellEditing() {
+ fireEditingCanceled();
+ }
+ private ChangeEvent evt;
+
+ private void fireEditingStopped() {
+ Object[] l = listeners.getListenerList();
+ for (int i = 0; i < l.length; i += 2) {
+ if (l[i] == CellEditorListener.class) {
+ CellEditorListener cel = (CellEditorListener) l[i + 1];
+ if (evt == null) {
+ evt = new ChangeEvent(this);
+ }
+ cel.editingStopped(evt);
+ }
+ }
+ }
+
+ private void fireEditingCanceled() {
+ Object[] l = listeners.getListenerList();
+ for (int i = 0; i < l.length; i += 2) {
+ if (l[i] == CellEditorListener.class) {
+ CellEditorListener cel = (CellEditorListener) l[i + 1];
+ if (evt == null) {
+ evt = new ChangeEvent(this);
+ }
+ cel.editingCanceled(evt);
+ }
+ }
+ }
+}
diff --git a/dasCore/src/main/java/org/das2/components/DatumRangeEditor.java b/dasCore/src/main/java/org/das2/components/DatumRangeEditor.java
new file mode 100644
index 000000000..0c2d8c0e0
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/components/DatumRangeEditor.java
@@ -0,0 +1,388 @@
+/* File: DatumEditor.java
+ * Copyright (C) 2002-2003 The University of Iowa
+ *
+ * Created on October 1, 2003, 9:20 AM
+ * by Edward West this
+ */
+ public Component getCustomEditor() {
+ return this;
+ }
+
+ /**
+ * This PropertyEditor implementation does not support generating java
+ * code.
+ * @return The string "???"
+ */
+ public String getJavaInitializationString() {
+ return "???";
+ }
+
+ /**
+ * This PropertyEditor implementation does not support enumerated
+ * values.
+ * @return null
+ */
+ public String[] getTags() { return null; }
+
+ /** @see java.beans.PropertyEditor#isPaintable()
+ * @return false
+ */
+ public boolean isPaintable() {
+ return false;
+ }
+
+ /** Does nothing.
+ * @param g
+ * @param r
+ */
+ public void paintValue(Graphics g, Rectangle r) {}
+
+ /* CellEditor stuff */
+
+ public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
+ setValue(value);
+ return this;
+ }
+
+ /**
+ */
+ public void addCellEditorListener(CellEditorListener l) {
+ if (listeners == null) {
+ listeners = new EventListenerList();
+ }
+ listeners.add(CellEditorListener.class, l);
+ }
+
+ /**
+ */
+ public void removeCellEditorListener(CellEditorListener l) {
+ if (listeners != null) {
+ listeners.remove(CellEditorListener.class, l);
+ }
+ }
+
+ /** @see javax.swing.CellEditor#isCellEditable(java.util.EventObject)
+ * @return true
+ */
+ public boolean isCellEditable(EventObject anEvent) {
+ return true;
+ }
+
+ /** @see javax.swing.CellEditor#shouldSelectCell(java.util.EventObject)
+ * @return true
+ */
+ public boolean shouldSelectCell(EventObject anEvent) {
+ return true;
+ }
+
+ /** Returns the value stored in this editor.
+ * @return the current value being edited
+ */
+ public Object getCellEditorValue() {
+ return getDatumRange();
+ }
+
+ public boolean stopCellEditing() {
+ if (getDatumRange() == null) {
+ return false;
+ }
+ fireEditingStopped();
+ return true;
+ }
+
+ public void cancelCellEditing() {
+ fireEditingCanceled();
+ }
+
+ private ChangeEvent evt;
+
+ private void fireEditingStopped() {
+ Object[] l = listeners.getListenerList();
+ for (int i = 0; i < l.length; i+=2) {
+ if (l[i] == CellEditorListener.class) {
+ CellEditorListener cel = (CellEditorListener)l[i+1];
+ if (evt == null) { evt = new ChangeEvent(this); }
+ cel.editingStopped(evt);
+ }
+ }
+ }
+
+ private void fireEditingCanceled() {
+ Object[] l = listeners.getListenerList();
+ for (int i = 0; i < l.length; i+=2) {
+ if (l[i] == CellEditorListener.class) {
+ CellEditorListener cel = (CellEditorListener)l[i+1];
+ if (evt == null) { evt = new ChangeEvent(this); }
+ cel.editingCanceled(evt);
+ }
+ }
+ }
+}
diff --git a/dasCore/src/main/java/org/das2/components/FavoritesSelector.java b/dasCore/src/main/java/org/das2/components/FavoritesSelector.java
new file mode 100644
index 000000000..2b07b39af
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/components/FavoritesSelector.java
@@ -0,0 +1,188 @@
+/*
+ * FavoritesSelector.java
+ *
+ * Created on March 18, 2004, 5:33 PM
+ */
+
+package org.das2.components;
+
+import java.util.*;
+import java.util.prefs.*;
+import javax.swing.*;
+import java.awt.event.*;
+import java.text.*;
+
+/**
+ *
+ * @author Jeremy
+ */
+public class FavoritesSelector {
+
+ java.util.List favoritesList;
+ String favoritesType;
+ FavoritesListener listener=null;
+ ActionListener actionListener;
+ JPopupMenu popupMenu;
+ boolean nextSelectionDeletes= false;
+
+ /** Creates a new instance of FavoritesSelector */
+ private FavoritesSelector( String _favoritesType) {
+ favoritesList= new ArrayList();
+ this.favoritesType= _favoritesType;
+ this.readFromPersistentPrefs();
+ }
+
+ public interface FavoritesListener extends EventListener {
+ void itemSelected( Object o );
+ Object addFavoriteSelected();
+ }
+
+ public void addFavoritesListener( FavoritesListener _listener ) {
+ if ( this.listener!=null ) {
+ throw new IllegalArgumentException( "only one listener supported" );
+ }
+ this.listener= _listener;
+ }
+
+ public ActionListener getActionListener() {
+ if ( this.actionListener==null ) {
+ this.actionListener= new ActionListener() {
+ public void actionPerformed( ActionEvent ev ) {
+ try {
+ String cmd= ev.getActionCommand();
+ System.out.println(cmd);
+ if ( cmd.equals("delete") ) {
+ FavoritesSelector.this.popupMenu.setVisible(true);
+ FavoritesSelector.this.nextSelectionDeletes= true;
+ } else if ( cmd.equals("add") ) {
+ if ( listener!=null ) {
+ Object o= FavoritesSelector.this.listener.addFavoriteSelected();
+ if ( o!=null ) {
+ addFavorite(o);
+ }
+ }
+ } else {
+ if ( FavoritesSelector.this.nextSelectionDeletes ) {
+ removeFavorite( favoritesList.get( Integer.parseInt(cmd) ) );
+ FavoritesSelector.this.nextSelectionDeletes= false;
+ } else {
+ FavoritesSelector.this.listener.itemSelected( favoritesList.get( Integer.parseInt(cmd) ) );
+ }
+ }
+ } catch ( NumberFormatException e ) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ }
+ return this.actionListener;
+ }
+
+ private void resetPopupMenu() {
+ JPopupMenu pm= getMenu();
+
+ JMenuItem item;
+ item= popupMenu.add("Add to favorites");
+ item.setActionCommand("add");
+ item.addActionListener(getActionListener());
+ for ( int i= 0; iDragGestureRecognizer has detected
+ * a platform-dependent drag initiating gesture and
+ * is notifying this listener
+ * in order for it to initiate the action for the user.
+ *
+ * @param dge the DragGestureEvent describing
+ * the gesture that has just occurred
+ */
+ public void dragGestureRecognized(DragGestureEvent dge) {
+ ToolComponent tc = (ToolComponent)dge.getComponent();
+ int index = tc.selectedIndex;
+ if (index >= 0) {
+ Cursor dragCursor = tc.cursors[index];
+ Transferable t = createTransferable(tc.ids[index]);
+ dge.startDrag(dragCursor, t, this);
+ }
+ }
+
+ /** This method is invoked to signify that the Drag and Drop
+ * operation is complete. The getDropSuccess() method of
+ * the DragSourceDropEvent can be used to
+ * determine the termination state. The getDropAction() method
+ * returns the operation that the drop site selected
+ * to apply to the Drop operation. Once this method is complete, the
+ * current DragSourceContext and
+ * associated resources become invalid.
+ *
+ * @param dsde the DragSourceDropEvent
+ */
+ public void dragDropEnd(DragSourceDropEvent dsde) {
+ }
+
+ /** Called as the cursor's hotspot enters a platform-dependent drop site.
+ * This method is invoked when all the following conditions are true:
+ *
DragSourceDragEvent
+ */
+ public void dragEnter(DragSourceDragEvent dsde) {
+ }
+
+ /** Called as the cursor's hotspot exits a platform-dependent drop site.
+ * This method is invoked when any of the following conditions are true:
+ * DragSourceEvent
+ */
+ public void dragExit(DragSourceEvent dse) {
+ }
+
+ /** Called as the cursor's hotspot moves over a platform-dependent drop site.
+ * This method is invoked when all the following conditions are true:
+ * DragSourceDragEvent
+ */
+ public void dragOver(DragSourceDragEvent dsde) {
+ }
+
+ /** Called when the user has modified the drop gesture.
+ * This method is invoked when the state of the input
+ * device(s) that the user is interacting with changes.
+ * Such devices are typically the mouse buttons or keyboard
+ * modifiers that the user is interacting with.
+ *
+ * @param dsde the DragSourceDragEvent
+ */
+ public void dropActionChanged(DragSourceDragEvent dsde) {
+ }
+
+ }
+
+
+
+ /** Displays a group of icons for the Toolbox component. */
+ private static class ToolComponent extends JComponent {
+
+ /** array of icons for this group */
+ private Icon[] icons;
+
+
+
+ /** array of ids for this group */
+ private String[] ids;
+
+
+
+ /** array of drag cursors for this group */
+ private Cursor[] cursors;
+
+
+
+
+ /** maximum number of icons per row */
+ private int width;
+
+
+
+
+ /** number of rows of icons */
+ private int height;
+
+
+
+
+ /** The index of the last icon that that was the recipient of a
+ * mousePressed event
+ */
+ private int selectedIndex = -1;
+
+
+
+ /** Create a new ToolComponent */
+ private ToolComponent(String[] ids, Icon [] icons, int w) {
+ this.ids = ids;
+ this.icons = icons;
+ this.cursors = getCursors(ids, icons);
+ this.width = w;
+ this.height = (int)Math.ceil((double)icons.length / (double)w);
+ setBackground(Color.WHITE);
+ setForeground(Color.BLACK);
+ setTransferHandler(null);
+ DragSource dragSource = DragSource.getDefaultDragSource();
+ dragSource.createDefaultDragGestureRecognizer(this,
+ DnDConstants.ACTION_COPY, new ToolboxDragGestureListener());
+ addMouseListener(new InputListener());
+ ToolTipManager.sharedInstance().registerComponent(this);
+ }//public ToolComponent
+
+ protected void paintComponent(Graphics g){
+ Rectangle clip = g.getClipBounds();
+ g.setColor(getBackground());
+ if (clip == null) {
+ g.fillRect(0, 0, getWidth(), getHeight());
+ }
+ else {
+ g.fillRect(clip.x, clip.y, clip.width, clip.height);
+ }
+ g.setColor(getForeground());
+ for(int index = 0; index < icons.length; index++) {
+ int i = index % width;
+ int j = index / width;
+ int x = i * 32 + 7;
+ int y = j * 32 + 7;
+ icons[index].paintIcon(this,g, x, y);
+ g.drawRect(x - 1, y - 1, 24, 24);
+ }
+ }//public void paintComponent(Graphics g)
+
+ public Dimension getPreferredSize() {
+ int w = width * 32 + 6;
+ int h = height * 32 + 6;
+ return new Dimension(w, h);
+ }
+
+ public Dimension getMinimumSize() {
+ return getPreferredSize();
+ }
+
+ public Dimension getMaximumSize() {
+ return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
+ }
+
+ private int positionToIndex(int x, int y) {
+ for (int index = 0; index < icons.length; index++) {
+ int i = index % width;
+ int j = index / width;
+ int xi = i * 32 + 7;
+ int yi = j * 32 + 7;
+ if (x >= xi && x < xi + 24 && y >= yi && y < yi + 24) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ public String getToolTipText(MouseEvent event) {
+ int index = positionToIndex(event.getX(), event.getY());
+ if (index == -1) {
+ return null;
+ }
+ else {
+ return ids[index];
+ }
+ }
+
+ }
+
+ /** A listener to listen for mousePressed events on a ToolComponent */
+ private static class InputListener extends MouseInputAdapter {
+ public void mousePressed(MouseEvent e) {
+ ToolComponent tc = (ToolComponent)e.getComponent();
+ tc.selectedIndex = tc.positionToIndex(e.getX(), e.getY());
+ }
+ }
+
+ public static void main(String[] args) {
+ JFrame frame = new JFrame();
+ frame.getContentPane().add(new Toolbox(), "Center");
+ frame.getContentPane().add(new JTextArea(10, 10), "West");
+ frame.pack();
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.setVisible(true);
+ }
+
+}
diff --git a/dasCore/src/main/java/org/das2/components/VerticalSpectrogramAverager.java b/dasCore/src/main/java/org/das2/components/VerticalSpectrogramAverager.java
new file mode 100755
index 000000000..2d275dfb4
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/components/VerticalSpectrogramAverager.java
@@ -0,0 +1,195 @@
+/* File: VerticalSpectrogramAverager.java
+ * Copyright (C) 2002-2003 The University of Iowa
+ * Created by: Jeremy Faden String that will help the user
+ * identify this item when choosing from a list.
+ */
+ String getListLabel();
+
+ /** An icon can be provided that will be shown in a list
+ * along with the textual description of the element.
+ * This method should return null if there
+ * is no icon available.
+ *
+ */
+ Icon getListIcon();
+
+}
+
diff --git a/dasCore/src/main/java/org/das2/components/propertyeditor/Editable.java b/dasCore/src/main/java/org/das2/components/propertyeditor/Editable.java
new file mode 100644
index 000000000..d22dda6b1
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/components/propertyeditor/Editable.java
@@ -0,0 +1,11 @@
+package org.das2.components.propertyeditor;
+
+/** Objects that are instances of classes that implement
+ * this interface can be expanded in a PropertyEditor
+ * property list.
+ *
+ */
+public interface Editable {
+
+}
+
diff --git a/dasCore/src/main/java/org/das2/components/propertyeditor/Enumeration.java b/dasCore/src/main/java/org/das2/components/propertyeditor/Enumeration.java
new file mode 100644
index 000000000..163b99143
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/components/propertyeditor/Enumeration.java
@@ -0,0 +1,30 @@
+package org.das2.components.propertyeditor;
+
+import javax.swing.Icon;
+
+/** Type-safe enumerations that are used as property types
+ * that are editable with a PropertyEditor should
+ * implement this interface.
+ *
+ */
+public interface Enumeration {
+
+ /** Type-safe Enumerations implementing this interface
+ * should override the toString() method to return a
+ * String that will be helpful to the user
+ * when choosing this as an option from a list.
+ *
+ */
+ String toString();
+ //TODO: getListLabel() better, because toString should be reserved for programmers.
+
+ /** An icon can be provided that will be shown in a list
+ * along with the textual description of the element.
+ * This method should return null if there
+ * is no icon available.
+ *
+ */
+ Icon getListIcon();
+
+}
+
diff --git a/dasCore/src/main/java/org/das2/components/propertyeditor/EnumerationEditor.java b/dasCore/src/main/java/org/das2/components/propertyeditor/EnumerationEditor.java
new file mode 100644
index 000000000..be9f7cd50
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/components/propertyeditor/EnumerationEditor.java
@@ -0,0 +1,338 @@
+/*
+ * EnumerationEditor.java
+ *
+ * Created on April 14, 2005, 9:18 AM
+ */
+package org.das2.components.propertyeditor;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EventObject;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.swing.AbstractListModel;
+import javax.swing.ComboBoxModel;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.JComboBox;
+import javax.swing.JList;
+import javax.swing.JTable;
+import javax.swing.event.CellEditorListener;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.EventListenerList;
+import javax.swing.table.TableCellEditor;
+
+/**
+ *
+ * @author eew
+ */
+public class EnumerationEditor implements java.beans.PropertyEditor, TableCellEditor {
+
+ private JComboBox editor;
+ private Model model;
+ private Object selected;
+ private Class type;
+ private boolean guessType;
+ private PropertyChangeSupport pcSupport;
+ private EventListenerList listeners = new EventListenerList();
+ private Map valueMap;
+ private Map nameMap;
+ private Map toStringMap;
+
+ /** Creates a new instance of EnumerationEditor */
+ public EnumerationEditor() {
+ guessType = true;
+ pcSupport = new PropertyChangeSupport(this);
+ }
+
+ protected EnumerationEditor(Class c) {
+ setClass(c);
+ guessType = false;
+ }
+
+ private void initEditor() {
+ if (editor == null) {
+ model = new Model();
+ editor = new JComboBox(model) {
+
+ public void setBounds(int x, int y, int width, int height) {
+ Dimension preferred = getPreferredSize();
+ super.setBounds(x, y, width, preferred.height);
+ }
+ };
+ editor.setRenderer(new Renderer());
+ editor.setSelectedItem(selected);
+ }
+ }
+ private static final int PUBLIC_STATIC_FINAL = Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL;
+
+ private void setClass(Class c) {
+ type = c;
+ Map valueM = new HashMap();
+ Map nameM = new IdentityHashMap();
+ Map toStringM = new HashMap();
+
+ if (c.isEnum()) {
+ Object[] vals = c.getEnumConstants();
+ for (Object o : vals) {
+ Enum e = (Enum) o;
+ nameM.put(e.name(), e);
+ toStringM.put(e.toString(), e);
+ valueM.put(e, e.name());
+ }
+
+ } else {
+
+ Field[] fields = type.getDeclaredFields();
+ Set psf = new HashSet();
+ for (int i = 0; i < fields.length; i++) {
+ int modifiers = fields[i].getModifiers();
+ if ((modifiers & PUBLIC_STATIC_FINAL) == PUBLIC_STATIC_FINAL) {
+ psf.add(fields[i]);
+ }
+ }
+ for (Iterator i = psf.iterator(); i.hasNext();) {
+ try {
+ Field f = (Field) i.next();
+ String name = f.getName();
+ Object value = f.get(null);
+ nameM.put(name, value);
+ toStringM.put(value.toString(), value);
+ valueM.put(value, name);
+ } catch (IllegalAccessException iae) {
+ IllegalAccessError err = new IllegalAccessError(iae.getMessage());
+ err.initCause(iae);
+ throw err;
+ }
+ }
+ }
+ nameMap = nameM;
+ valueMap = valueM;
+ toStringMap = toStringM;
+ }
+
+ public String getAsText() {
+ return selected.toString();
+ }
+
+ public Object getValue() {
+ return selected;
+ }
+
+ public void setAsText(String str) throws IllegalArgumentException {
+ Object oldValue;
+ Object value = nameMap.get(str);
+ if (value == null) {
+ value = toStringMap.get(str);
+ }
+ if (value == null) {
+ throw new IllegalArgumentException(str);
+ }
+ if (selected != value) {
+ oldValue = selected;
+ selected = value;
+ if ( editor!=null ) {
+ editor.setSelectedItem(selected);
+ editor.repaint();
+ }
+ pcSupport.firePropertyChange("value", oldValue, selected);
+ }
+ }
+
+ public void setValue(Object obj) {
+ Class c = getTypeClass(obj);
+ if (type != c) {
+ int size = 0;
+ if (model != null) {
+ size = model.getSize();
+ }
+ setClass(c);
+ if (model != null) {
+ model.fireIntervalRemoved(model, 0, size - 1);
+ model.fireIntervalAdded(model, 0, model.getSize() - 1);
+ }
+ }
+ Object oldValue = selected;
+ selected = obj;
+ if (oldValue != obj) {
+ pcSupport.firePropertyChange("value", oldValue, selected);
+ if ( editor!=null ) {
+ editor.setSelectedItem(selected);
+ editor.repaint();
+ }
+ }
+ }
+
+ private Class getTypeClass(Object obj) {
+ Class c = obj.getClass();
+ String name = c.getName();
+ if (name.matches(".+?\\$\\d+")) {
+ c = c.getSuperclass();
+ }
+ return c;
+ }
+
+ public boolean supportsCustomEditor() {
+ return true;
+ }
+
+ public Component getCustomEditor() {
+ initEditor();
+ return editor;
+ }
+
+ public String getJavaInitializationString() {
+ return "???";
+ }
+
+ public String[] getTags() {
+ return null;
+ }
+
+ public boolean isPaintable() {
+ return false;
+ }
+
+ public void paintValue(Graphics g, Rectangle r) {
+ }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {
+ pcSupport.addPropertyChangeListener(l);
+ }
+
+ public void removePropertyChangeListener(PropertyChangeListener l) {
+ pcSupport.removePropertyChangeListener(l);
+ }
+
+ /*TableCellEditor stuff*/
+ public Object getCellEditorValue() {
+ return selected;
+ }
+
+ public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
+ initEditor();
+ editor.setForeground(table.getForeground());
+ editor.setBackground(table.getBackground());
+ setValue(value);
+ return editor;
+ }
+
+ public boolean isCellEditable(EventObject evt) {
+ return true;
+ }
+
+ public boolean shouldSelectCell(EventObject evt) {
+ return true;
+ }
+
+ public boolean stopCellEditing() {
+ fireEditingStopped();
+ return true;
+ }
+
+ public void cancelCellEditing() {
+ fireEditingCanceled();
+ }
+
+ public void addCellEditorListener(CellEditorListener l) {
+ listeners.add(CellEditorListener.class, l);
+ }
+
+ public void removeCellEditorListener(CellEditorListener l) {
+ listeners.add(CellEditorListener.class, l);
+ }
+ private ChangeEvent evt;
+
+ private void fireEditingStopped() {
+ Object[] l = listeners.getListenerList();
+ for (int i = 0; i < l.length; i += 2) {
+ if (l[i] == CellEditorListener.class) {
+ CellEditorListener cel = (CellEditorListener) l[i + 1];
+ if (evt == null) {
+ evt = new ChangeEvent(this);
+ }
+ cel.editingStopped(evt);
+ }
+ }
+ }
+
+ private void fireEditingCanceled() {
+ Object[] l = listeners.getListenerList();
+ for (int i = 0; i < l.length; i += 2) {
+ if (l[i] == CellEditorListener.class) {
+ CellEditorListener cel = (CellEditorListener) l[i + 1];
+ if (evt == null) {
+ evt = new ChangeEvent(this);
+ }
+ cel.editingCanceled(evt);
+ }
+ }
+ }
+
+ private class Renderer extends DefaultListCellRenderer {
+
+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean hasFocus) {
+ String s = (String) valueMap.get(value);
+ super.getListCellRendererComponent(list, s, index, isSelected, hasFocus);
+ if (value instanceof Enumeration) {
+ setText(value.toString());
+ setIcon(((Enumeration) value).getListIcon());
+ }
+ return this;
+ }
+ }
+
+ private class Model extends AbstractListModel implements ComboBoxModel {
+
+ private List list;
+
+ private Model() {
+ list = new ArrayList(nameMap.keySet());
+ Collections.sort(list, String.CASE_INSENSITIVE_ORDER);
+ }
+
+ public Object getSelectedItem() {
+ return selected;
+ }
+
+ public void setSelectedItem(Object o) {
+ setValue(o);
+ stopCellEditing();
+ }
+
+ public Object getElementAt(int index) {
+ return nameMap.get(list.get(index));
+ }
+
+ public int getSize() {
+ return list.size();
+ }
+
+ //TODO: remove?
+ protected void fireIntervalRemoved(Object source, int index0, int index1) {
+ super.fireIntervalRemoved(source, index0, index1);
+ }
+
+ //TODO: remove?
+ protected void fireIntervalAdded(Object source, int index0, int index1) {
+ super.fireIntervalAdded(source, index0, index1);
+ }
+
+ //TODO: remove?
+ protected void fireContentsChanged(Object source, int index0, int index1) {
+ super.fireContentsChanged(source, index0, index1);
+ }
+ }
+}
diff --git a/dasCore/src/main/java/org/das2/components/propertyeditor/FloatingPointDocumentFilter.java b/dasCore/src/main/java/org/das2/components/propertyeditor/FloatingPointDocumentFilter.java
new file mode 100644
index 000000000..129452a01
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/components/propertyeditor/FloatingPointDocumentFilter.java
@@ -0,0 +1,70 @@
+package org.das2.components.propertyeditor;
+
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.DocumentFilter;
+import javax.swing.text.DocumentFilter.FilterBypass;
+
+class FloatingPointDocumentFilter extends DocumentFilter {
+
+ public void insertString(FilterBypass fb, int offset, String text, AttributeSet atts) throws BadLocationException {
+ if (text.length() == 1) {
+ if (text.charAt(0) == '-') {
+ String content = fb.getDocument().getText(0, fb.getDocument().getLength());
+ int eIndex = Math.max(content.indexOf('e'), content.indexOf('E'));
+ if (content.length() == 0) {
+ super.insertString(fb, 0, text, atts);
+ }
+ else if (eIndex < 0 || offset <= eIndex) {
+ if (content.charAt(0) == '-') {
+ super.remove(fb, 0, 1);
+ }
+ else {
+ super.insertString(fb, 0, text, atts);
+ }
+ }
+ else {
+ if (content.length() == eIndex+1) {
+ super.insertString(fb, eIndex+1, text, atts);
+ }
+ else if (content.charAt(eIndex+1) == '-') {
+ super.remove(fb, eIndex+1, 1);
+ }
+ else {
+ super.insertString(fb, eIndex+1, text, atts);
+ }
+ }
+ }
+ else if (text.charAt(0) == '.') {
+ String content = fb.getDocument().getText(0, fb.getDocument().getLength());
+ int dotIndex = content.indexOf('.');
+ if (offset <= dotIndex) {
+ super.replace(fb, offset, dotIndex-offset+1, text, atts);
+ }
+ else if (dotIndex < 0) {
+ super.insertString(fb, offset, text, atts);
+ }
+ }
+ else if (text.charAt(0) == 'e' || text.charAt(0) == 'E') {
+ String content = fb.getDocument().getText(0, fb.getDocument().getLength());
+ int eIndex = Math.max(content.indexOf('e'), content.indexOf('E'));
+ if (offset <= eIndex) {
+ super.replace(fb, offset, eIndex-offset+1, text, atts);
+ }
+ else if (eIndex < 0) {
+ super.insertString(fb, offset, text, atts);
+ }
+ }
+ else if (Character.isDigit(text.charAt(0))) {
+ super.insertString(fb, offset, text, atts);
+ }
+ }
+ }
+
+ public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet atts) throws BadLocationException {
+ remove(fb, offset, length);
+ insertString(fb, offset, text, atts);
+ }
+
+}
+
diff --git a/dasCore/src/main/java/org/das2/components/propertyeditor/FloatingPointFormatter.java b/dasCore/src/main/java/org/das2/components/propertyeditor/FloatingPointFormatter.java
new file mode 100644
index 000000000..a2a8594c9
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/components/propertyeditor/FloatingPointFormatter.java
@@ -0,0 +1,52 @@
+package org.das2.components.propertyeditor;
+
+import java.text.ParseException;
+import javax.swing.JFormattedTextField;
+import javax.swing.text.DocumentFilter;
+
+class FloatingPointFormatter extends JFormattedTextField.AbstractFormatter {
+
+ /** Parses text returning an arbitrary Object. Some
+ * formatters may return null.
+ *
+ * @throws ParseException if there is an error in the conversion
+ * @param text String to convert
+ * @return Object representation of text
+ *
+ */
+ public Object stringToValue(String text) throws ParseException {
+ try {
+ Double d = new Double(text);
+ if (d.doubleValue() == Double.NEGATIVE_INFINITY ||
+ d.doubleValue() == Double.POSITIVE_INFINITY ||
+ d.doubleValue() == Double.NaN) {
+ throw new ParseException("+/-infinity and NaN are not allowed", 0);
+ }
+ return d;
+ }
+ catch (NumberFormatException nfe) {
+ throw new ParseException(nfe.getMessage(), 0);
+ }
+ }
+
+ /** Returns the string value to display for value.
+ *
+ * @throws ParseException if there is an error in the conversion
+ * @param value Value to convert
+ * @return String representation of value
+ *
+ */
+ public String valueToString(Object value) throws ParseException {
+ if (value instanceof Number) {
+ double doubleValue = ((Number)value).doubleValue();
+ return value.toString();
+ }
+ else throw new ParseException("value must be of type Number", 0);
+ }
+
+ protected DocumentFilter getDocumentFilter() {
+ return new FloatingPointDocumentFilter();
+ }
+
+}
+
diff --git a/dasCore/src/main/java/org/das2/components/propertyeditor/IndexedPropertyItemTreeNode.java b/dasCore/src/main/java/org/das2/components/propertyeditor/IndexedPropertyItemTreeNode.java
new file mode 100644
index 000000000..c7ec149ea
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/components/propertyeditor/IndexedPropertyItemTreeNode.java
@@ -0,0 +1,87 @@
+package org.das2.components.propertyeditor;
+import org.das2.util.DasExceptionHandler;
+import java.beans.IndexedPropertyDescriptor;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.*;
+
+class IndexedPropertyItemTreeNode extends PropertyTreeNode {
+
+ private IndexedPropertyDescriptor indexedPropertyDescriptor;
+
+ private int index;
+
+ IndexedPropertyItemTreeNode(PropertyTreeNode parent, IndexedPropertyDescriptor indexedPropertyDescriptor, int index) {
+ super(Array.get(parent.value, index));
+ setTreeModel(parent.treeModel);
+ this.index = index;
+ this.parent = parent;
+ this.propertyDescriptor = indexedPropertyDescriptor;
+ this.indexedPropertyDescriptor = indexedPropertyDescriptor;
+ }
+
+ public boolean getAllowsChildren() {
+ return indexedPropertyDescriptor.getPropertyEditorClass() == null;
+ }
+
+ public String getDisplayName() {
+ return propertyDescriptor.getName() + "[" + index + "]";
+ }
+
+ public void flush() {
+ try {
+ if (dirty) {
+ Method writeMethod = indexedPropertyDescriptor.getIndexedWriteMethod();
+ writeMethod.invoke(parent.parent.value, new Object[]{new Integer(index), value} );
+ dirty = false;
+ }
+ if (childDirty) {
+ for (Iterator i = children.iterator(); i.hasNext(); ) {
+ PropertyTreeNode child = (PropertyTreeNode)i.next();
+ child.flush();
+ }
+ childDirty = false;
+ }
+ } catch (IllegalAccessException iae) {
+ throw new RuntimeException(iae);
+ } catch ( InvocationTargetException e ) {
+ DasExceptionHandler.handle(e);
+ }
+ }
+
+ protected Object read() {
+ Object[] parentValue= (Object[])parent.read();
+ return parentValue[this.index];
+ }
+
+ public void refresh( ) {
+ Object newValue = read();
+ boolean foldMe= false;
+ if ( newValue!=value ) {
+ boolean allowsChildren= getAllowsChildren();
+ if ( allowsChildren ) {
+ foldMe= true;
+ }
+ }
+ if (newValue != value && newValue != null && !newValue.equals(value)) {
+ value = newValue;
+ }
+ if ( foldMe ) {
+ children= null;
+ treeModel.nodeStructureChanged( this );
+ } else {
+ if (getAllowsChildren()) {
+ if (children != null) {
+ for (Iterator i = children.iterator(); i.hasNext();) {
+ PropertyTreeNode child = (PropertyTreeNode)i.next();
+ child.refresh( );
+ }
+ }
+ }
+ }
+
+ }
+
+}
+
diff --git a/dasCore/src/main/java/org/das2/components/propertyeditor/IndexedPropertyTreeNode.java b/dasCore/src/main/java/org/das2/components/propertyeditor/IndexedPropertyTreeNode.java
new file mode 100644
index 000000000..c32f9330a
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/components/propertyeditor/IndexedPropertyTreeNode.java
@@ -0,0 +1,109 @@
+package org.das2.components.propertyeditor;
+import java.beans.IndexedPropertyDescriptor;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.*;
+import javax.swing.event.TreeModelEvent;
+import javax.swing.event.TreeModelListener;
+import javax.swing.tree.MutableTreeNode;
+
+class IndexedPropertyTreeNode extends PropertyTreeNode {
+
+ private IndexedPropertyDescriptor indexedPropertyDescriptor;
+
+ IndexedPropertyTreeNode(PropertyTreeNode parent, IndexedPropertyDescriptor indexedPropertyDescriptor) throws InvocationTargetException {
+ super(parent, indexedPropertyDescriptor );
+ this.indexedPropertyDescriptor = indexedPropertyDescriptor;
+ }
+
+ public boolean getAllowsChildren() {
+ return true;
+ }
+
+ protected void maybeLoadChildren() {
+ if (children == null) {
+ children = new ArrayList();
+ int childCount = Array.getLength(value);
+ for (int i = 0; i < childCount; i++) {
+ children.add(new IndexedPropertyItemTreeNode(this, indexedPropertyDescriptor, i));
+ }
+ }
+ }
+
+ public String getDisplayName() {
+ return propertyDescriptor.getName() + "[]";
+ }
+
+ @Override
+ public Object getDisplayValue() {
+ return ""+ getChildCount() + " element" + ( getChildCount()!=1 ? "s" : "" );
+ }
+
+
+ public void flush() {
+ if (childDirty) {
+ for (Iterator i = children.iterator(); i.hasNext(); ) {
+ PropertyTreeNode child = (PropertyTreeNode)i.next();
+ child.flush();
+ }
+ childDirty = false;
+ }
+ }
+
+ protected Object read() {
+ if (propertyDescriptor == null) {
+ return value;
+ } else {
+ Method readMethod = propertyDescriptor.getReadMethod();
+ if (readMethod == null) {
+ String pName = propertyDescriptor.getName();
+ String pId = value.getClass().getName() + "#" + pName;
+ throw new IllegalStateException(
+ "Null read method for: " + pId);
+ }
+ try {
+ return readMethod.invoke(parent.value);
+ } catch (IllegalAccessException iae) {
+ Error err = new IllegalAccessError(iae.getMessage());
+ err.initCause(iae);
+ throw err;
+ } catch (InvocationTargetException ite) {
+ Throwable cause = ite.getCause();
+ if (cause instanceof Error) {
+ throw (Error)cause;
+ } else if (cause instanceof RuntimeException) {
+ throw (RuntimeException)cause;
+ } else {
+ throw new RuntimeException(cause);
+ }
+ }
+ }
+ }
+ public boolean isCellEditable(int column) {
+ return false;
+ }
+
+ public void refresh( ) {
+ Object newValue = read();
+
+ value= newValue;
+ if ( children!=null ) {
+ if ( children.size()<((Object[])newValue).length ) {
+ children=null;
+ treeModel.nodeStructureChanged(this);
+ } else if ( children.size()>((Object[])newValue).length ) {
+ children= null;
+ treeModel.nodeStructureChanged(this);
+ }
+ }
+ if (children != null) {
+ for (Iterator i = children.iterator(); i.hasNext();) {
+ PropertyTreeNode child = (PropertyTreeNode)i.next();
+ child.refresh( );
+ }
+ }
+
+ }
+}
+
diff --git a/dasCore/src/main/java/org/das2/components/propertyeditor/MapEditor.java b/dasCore/src/main/java/org/das2/components/propertyeditor/MapEditor.java
new file mode 100644
index 000000000..15bc183d5
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/components/propertyeditor/MapEditor.java
@@ -0,0 +1,73 @@
+/*
+ * MapEditor.java
+ *
+ * Created on September 27, 2005, 1:37 PM
+ *
+ *
+ */
+
+package org.das2.components.propertyeditor;
+
+import java.util.Iterator;
+import java.util.Map;
+import javax.swing.JTextArea;
+
+/**
+ *
+ * @author Jeremy
+ */
+public class MapEditor implements java.beans.PropertyEditor {
+ Map value;
+
+ public void addPropertyChangeListener(java.beans.PropertyChangeListener propertyChangeListener) {
+ }
+
+ public String getAsText() {
+ return "lookup";
+ }
+
+ public java.awt.Component getCustomEditor() {
+ JTextArea result= new JTextArea(20,6);
+ for ( Iterator i= value.keySet().iterator(); i.hasNext(); ) {
+ Object key= i.next();
+ Object value= i.next();
+ result.append(""+key+"=\t"+value+"\n");
+ }
+ return result;
+ }
+
+ public String getJavaInitializationString() {
+ return "lookup";
+ }
+
+ public String[] getTags() {
+ return null;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public boolean isPaintable() {
+ return false;
+ }
+
+ public void paintValue(java.awt.Graphics graphics, java.awt.Rectangle rectangle) {
+
+ }
+
+ public void removePropertyChangeListener(java.beans.PropertyChangeListener propertyChangeListener) {
+ }
+
+ public void setAsText(String str) throws IllegalArgumentException {
+ }
+
+ public void setValue(Object obj) {
+ this.value= (Map)obj;
+ }
+
+ public boolean supportsCustomEditor() {
+ return true;
+ }
+
+}
diff --git a/dasCore/src/main/java/org/das2/components/propertyeditor/PeerPropertyTreeNode.java b/dasCore/src/main/java/org/das2/components/propertyeditor/PeerPropertyTreeNode.java
new file mode 100644
index 000000000..998a1d3ed
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/components/propertyeditor/PeerPropertyTreeNode.java
@@ -0,0 +1,167 @@
+/*
+ * PeerPropertyTreeNode.java
+ *
+ * Created on December 20, 2005, 11:15 AM
+ *
+ *
+ */
+
+package org.das2.components.propertyeditor;
+
+import java.beans.PropertyDescriptor;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeNode;
+
+/**
+ *
+ * @author Jeremy
+ */
+public class PeerPropertyTreeNode implements PropertyTreeNodeInterface {
+ PeerPropertyTreeNode parent;
+ PropertyTreeNode leader;
+ PropertyTreeNode[] peers;
+
+ public PeerPropertyTreeNode( PeerPropertyTreeNode parent, PropertyTreeNode leader, PropertyTreeNode[] peers ) {
+ this.parent= parent;
+ this.leader= leader;
+ this.peers= peers;
+ }
+
+ public java.util.Enumeration children() {
+ return new java.util.Enumeration() {
+ int index=0;
+ public boolean hasMoreElements() {
+ return indexpaint method is then called to
+ * "render" the cell. If it is necessary to compute the dimensions
+ * of a list because the list cells do not have a fixed size, this method
+ * is called to generate a component on which getPreferredSize
+ * can be invoked.
+ *
+ * @param list The JList we're painting.
+ * @param value The value returned by list.getModel().getElementAt(index).
+ * @param index The cells index.
+ * @param isSelected True if the specified cell was selected.
+ * @param cellHasFocus True if the specified cell has the focus.
+ * @return A component whose paint() method will render the specified value.
+ *
+ * @see JList
+ * @see ListSelectionModel
+ * @see ListModel
+ *
+ */
+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+ if (value instanceof Displayable ) {
+ Displayable enm = (Displayable)value;
+ setIcon(enm.getListIcon());
+ setText(enm.getListLabel());
+ } else {
+ setIcon(null);
+ setText(String.valueOf(value));
+ }
+ setOpaque(true);
+ setBackground(isSelected ? Color.gray : Color.lightGray);
+ return this;
+ }
+
+}
+
diff --git a/dasCore/src/main/java/org/das2/components/propertyeditor/PropertyEditor.java b/dasCore/src/main/java/org/das2/components/propertyeditor/PropertyEditor.java
new file mode 100644
index 000000000..400a31291
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/components/propertyeditor/PropertyEditor.java
@@ -0,0 +1,493 @@
+/* File: PropertyEditor.java
+ * Copyright (C) 2002-2003 The University of Iowa
+ * Created by: Jeremy Faden Returns null if the value can't be expressed as an editable string. + *
If a non-null value is returned, then the PropertyEditor should + * be prepared to parse that string back in setAsText(). + */ + public String getAsText() { + return "dflkjd"; + } + + /** A PropertyEditor may choose to make available a full custom Component + * that edits its property value. It is the responsibility of the + * PropertyEditor to hook itself up to its editor Component itself and + * to report property value changes by firing a PropertyChange event. + *
+ * The higher-level code that calls getCustomEditor may either embed + * the Component in some larger property sheet, or it may put it in + * its own individual dialog, or ... + * + * @return A java.awt.Component that will allow a human to directly + * edit the current property value. May be null if this is + * not supported. + */ + public java.awt.Component getCustomEditor() { + return this; + } + + /** This method is intended for use when generating Java code to set + * the value of the property. It should return a fragment of Java code + * that can be used to initialize a variable with the current property + * value. + *
+ * Example results are "2", "new Color(127,127,34)", "Color.orange", etc. + * + * @return A fragment of Java code representing an initializer for the + * current value. + */ + public String getJavaInitializationString() { + return "???"; + } + + /** If the property value must be one of a set of known tagged values, + * then this method should return an array of the tags. This can + * be used to represent (for example) enum values. If a PropertyEditor + * supports tags, then it should support the use of setAsText with + * a tag value as a way of setting the value and the use of getAsText + * to identify the current value. + * + * @return The tag values for this property. May be null if this + * property cannot be represented as a tagged value. + * + */ + public String[] getTags() { + return null; + } + + /** Gets the property value. + * + * @return The value of the property. Primitive types such as "int" will + * be wrapped as the corresponding object type such as "java.lang.Integer". + */ + public Object getValue() { + return commandBlock; + } + + /** Determines whether this property editor is paintable. + * + * @return True if the class will honor the paintValue method. + */ + public boolean isPaintable() { + return false; + } + + /** Paint a representation of the value into a given area of screen + * real estate. Note that the propertyEditor is responsible for doing + * its own clipping so that it fits into the given rectangle. + *
+ * If the PropertyEditor doesn't honor paint requests (see isPaintable) + * this method should be a silent noop. + *
+ * The given Graphics object will have the default font, color, etc of
+ * the parent container. The PropertyEditor may change graphics attributes
+ * such as font and color and doesn't need to restore the old values.
+ *
+ * @param gfx Graphics object to paint into.
+ * @param box Rectangle within graphics object into which we should paint.
+ */
+ public void paintValue(java.awt.Graphics gfx, java.awt.Rectangle box) {
+ }
+
+ /** Set the property value by parsing a given String. May raise
+ * java.lang.IllegalArgumentException if either the String is
+ * badly formatted or if this kind of property can't be expressed
+ * as text.
+ * @param text The string to be parsed.
+ */
+ public void setAsText(String text) throws java.lang.IllegalArgumentException {
+ }
+
+ /** Set (or change) the object that is to be edited. Primitive types such
+ * as "int" must be wrapped as the corresponding object type such as
+ * "java.lang.Integer".
+ *
+ * @param value The new target object to be edited. Note that this
+ * object should not be modified by the PropertyEditor, rather
+ * the PropertyEditor should create a new object to hold any
+ * modified value.
+ */
+ public void setValue(Object value) {
+ setCommandBlock((CommandBlock)value);
+ }
+
+ /** Determines whether this property editor supports a custom editor.
+ *
+ * @return True if the propertyEditor can provide a custom editor.
+ */
+ public boolean supportsCustomEditor() {
+ return true;
+ }
+
+ private static class CommandBlockTreeModel implements TreeModel {
+
+ private EventListenerList eventListenerList;
+ private CommandBlock root;
+
+ CommandBlockTreeModel(CommandBlock root) {
+ this.root = root;
+ }
+
+ /** Adds a listener for the
+ * If you override this in a subclass you should not make permanent
+ * changes to the passed in
+ * This method is responsible for undertaking
+ * the transfer of the data associated with the
+ * gesture. The
+ * From this method, the
+ * Subsequent to acceptDrop(), but not before,
+ *
+ * At the completion of a drop, an implementation
+ * of this method is required to signal the success/failure
+ * of the drop by passing an appropriate
+ *
+ * Note: The data transfer should be completed before the call to the
+ *
+ * @param dtde the
+ * @param dtde the TreeModelEvent
+ * posted after the tree changes.
+ *
+ * @param l the listener to add
+ * @see #removeTreeModelListener
+ */
+ public void addTreeModelListener(TreeModelListener l) {
+ if (eventListenerList == null) {
+ eventListenerList = new EventListenerList();
+ }
+ eventListenerList.add(TreeModelListener.class, l);
+ }
+
+ /** Returns the child of parent at index index
+ * in the parent's
+ * child array. parent must be a node previously obtained
+ * from this data source. This should not return null
+ * if index
+ * is a valid index for parent (that is index >= 0 &&
+ * index < getChildCount(parent)).
+ *
+ * @param parent a node in the tree, obtained from this data source
+ * @return the child of parent at index index
+ */
+ public Object getChild(Object parent, int index) {
+ if (parent instanceof CommandBlock) {
+ return ((CommandBlock)parent).commandList.get(index);
+ }
+ else {
+ return null;
+ }
+ }
+
+ /** Returns the number of children of parent.
+ * Returns 0 if the node
+ * is a leaf or if it has no children. parent must be a node
+ * previously obtained from this data source.
+ *
+ * @param parent a node in the tree, obtained from this data source
+ * @return the number of children of the node parent
+ */
+ public int getChildCount(Object parent) {
+ if (parent instanceof CommandBlock) {
+ return ((CommandBlock)parent).commandList.size();
+ }
+ else {
+ return 0;
+ }
+ }
+
+ /** Returns the index of child in parent. If parent
+ * is null or child is null,
+ * returns -1.
+ *
+ * @param parent a note in the tree, obtained from this data source
+ * @param child the node we are interested in
+ * @return the index of the child in the parent, or -1 if either
+ * child or parent are null
+ */
+ public int getIndexOfChild(Object parent, Object child) {
+ if (parent instanceof CommandBlock) {
+ return ((CommandBlock)parent).commandList.indexOf(child);
+ }
+ return -1;
+ }
+
+ /** Returns the root of the tree. Returns null
+ * only if the tree has no nodes.
+ *
+ * @return the root of the tree
+ */
+ public Object getRoot() {
+ return root;
+ }
+
+ /** Returns true if node is a leaf.
+ * It is possible for this method to return false
+ * even if node has no children.
+ * A directory in a filesystem, for example,
+ * may contain no files; the node representing
+ * the directory is not a leaf, but it also has no children.
+ *
+ * @param node a node in the tree, obtained from this data source
+ * @return true if node is a leaf
+ */
+ public boolean isLeaf(Object node) {
+ return !(node instanceof CommandBlock);
+ }
+
+ /** Removes a listener previously added with
+ * addTreeModelListener.
+ *
+ * @see #addTreeModelListener
+ * @param l the listener to remove
+ */
+ public void removeTreeModelListener(TreeModelListener l) {
+ if (eventListenerList != null) {
+ eventListenerList.remove(TreeModelListener.class, l);
+ }
+ }
+
+ protected void fireTreeChanged() {
+ TreeModelEvent evt = null;
+ Object[] listeners = eventListenerList.getListenerList();
+ for (int i = listeners.length - 2; i >= 0; i-=2) {
+ if (listeners[i] == TreeModelListener.class) {
+ if (evt == null) {
+ evt = new TreeModelEvent(this, new Object[]{root});
+ }
+ ((TreeModelListener)listeners[i+1]).treeStructureChanged(evt);
+ }
+ }
+ }
+
+ protected void fireTreeNodesChanged(Object[] path, int index, Object child) {
+ TreeModelEvent evt = null;
+ Object[] listeners = eventListenerList.getListenerList();
+ for (int i = listeners.length - 2; i >= 0; i-=2) {
+ if (listeners[i] == TreeModelListener.class) {
+ if (evt == null) {
+ evt = new TreeModelEvent(this, path, new int[]{index}, new Object[]{child});
+ }
+ ((TreeModelListener)listeners[i+1]).treeNodesChanged(evt);
+ }
+ }
+ }
+
+ protected void fireTreeNodeInserted(Object[] path, int index, Object child) {
+ TreeModelEvent evt = null;
+ Object[] listeners = eventListenerList.getListenerList();
+ for (int i = listeners.length - 2; i >= 0; i-=2) {
+ if (listeners[i] == TreeModelListener.class) {
+ if (evt == null) {
+ evt = new TreeModelEvent(this, path, new int[]{index}, new Object[]{child});
+ }
+ ((TreeModelListener)listeners[i+1]).treeNodesInserted(evt);
+ }
+ }
+ }
+
+ protected void fireTreeNodesRemoved(TreePath parent, int[] indices, Object[] children) {
+ TreeModelEvent evt = null;
+ Object[] listeners = eventListenerList.getListenerList();
+ for (int i = listeners.length - 2; i >= 0; i-=2) {
+ if (listeners[i] == TreeModelListener.class) {
+ if (evt == null) {
+ evt = new TreeModelEvent(this, parent, indices, children);
+ }
+ ((TreeModelListener)listeners[i+1]).treeNodesRemoved(evt);
+ }
+ }
+ }
+
+ protected void fireTreeStructureChanged(Object[] path) {
+ TreeModelEvent evt = null;
+ Object[] listeners = eventListenerList.getListenerList();
+ for (int i = listeners.length - 2; i >= 0; i-=2) {
+ if (listeners[i] == TreeModelListener.class) {
+ if (evt == null) {
+ evt = new TreeModelEvent(this, path);
+ }
+ ((TreeModelListener)listeners[i+1]).treeStructureChanged(evt);
+ }
+ }
+ }
+
+ Object[] getPathToNode(Object node) {
+ if (!(node instanceof CommandBlock.Command)) {
+ return new Object[]{node};
+ }
+ else {
+ CommandBlock.Command command = (CommandBlock.Command)node;
+ CommandBlock parent = command.getParent();
+ int count = 2;
+ while (parent instanceof CommandBlock.Command) {
+ parent = ((CommandBlock.Command)parent).getParent();
+ count ++;
+ }
+ Object[] path = new Object[count];
+ parent = command.getParent();
+ path[count - 1] = node;
+ path[count - 2] = parent;
+ int index = count - 2;
+ while (parent instanceof CommandBlock.Command) {
+ index --;
+ parent = ((CommandBlock.Command)parent).getParent();
+ path[index] = parent;
+ }
+ System.out.println(Arrays.asList(path));
+ return path;
+ }
+ }
+
+ /** Messaged when the user has altered the value for the item identified
+ * by path to newValue.
+ * If newValue signifies a truly new value
+ * the model should post a treeNodesChanged event.
+ *
+ * @param path path to the node that the user has altered
+ * @param newValue the new value from the TreeCellEditor
+ */
+ public void valueForPathChanged(TreePath path, Object newValue) {
+ }
+
+ }
+
+ private static class CommandRenderer extends JLabel implements TreeCellRenderer {
+
+ Color textForeground;
+
+ Color textBackground;
+
+ Color selectionForeground;
+
+ Color selectionBackground;
+
+ Border focusedBorder;
+
+ Border unfocusedBorder;
+
+ CommandRenderer() {
+ setOpaque(true);
+ textForeground = UIManager.getColor("Tree.textForeground");
+ textBackground = UIManager.getColor("Tree.textBackground");
+ selectionForeground = UIManager.getColor("Tree.selectionForeground");
+ selectionBackground = UIManager.getColor("Tree.selectionBackground");
+ focusedBorder = new LineBorder(UIManager.getColor("Tree.selectionBorderColor"));
+ unfocusedBorder = new LineBorder(textBackground);
+ }
+
+ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
+ setForeground(selected ? selectionForeground : textForeground);
+ setBackground(selected ? selectionBackground : textBackground);
+ setBorder(hasFocus ? focusedBorder : unfocusedBorder);
+ if (!(value instanceof CommandBlock.Command)) {
+ setText("[Command Block]");
+ }
+ else {
+ setText(value.toString());
+ }
+ setEnabled(tree.isEnabled());
+ return this;
+ }
+
+ }
+}
diff --git a/dasCore/src/main/java/org/das2/dasml/DOMBuilder.java b/dasCore/src/main/java/org/das2/dasml/DOMBuilder.java
new file mode 100644
index 000000000..d7bafcf68
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/dasml/DOMBuilder.java
@@ -0,0 +1,210 @@
+/*
+ * Serializer.java
+ *
+ * Created on April 28, 2006, 4:49 PM
+ *
+ * To change this template, choose Tools | Template Manager
+ * and open the template in the editor.
+ */
+
+package org.das2.dasml;
+
+import org.das2.graph.DasCanvasComponent;
+import org.das2.DasApplication;
+import org.das2.NameContext;
+import org.das2.beans.AccessLevelBeanInfo;
+import org.das2.beans.BeansUtil;
+import org.das2.system.DasLogger;
+import org.das2.util.monitor.ProgressMonitor;
+import org.das2.util.monitor.NullProgressMonitor;
+import java.beans.*;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.logging.*;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * New stateful serialize utility that uses names when available.
+ * @author Jeremy
+ */
+public class DOMBuilder {
+
+ Object bean;
+ HashMap serializedObjects;
+ NameContext nameContext;
+
+ /** Creates a new instance of Serializer */
+ public DOMBuilder( Object bean ) {
+ this.bean= bean;
+ }
+
+ /**
+ * returns name or null.
+ */
+ private String getBeanName( Object bean ) {
+ try {
+ PropertyDescriptor[] pds= BeansUtil.getPropertyDescriptors(bean.getClass());
+ for ( int i=0; i<action> element.
+ *
+ * @param element The DOM tree node that represents the element
+ */
+ private CommandBlock processActionElement(Element element) {
+ return new CommandBlock(element, this);
+ }
+
+ /** Process a <glue> element.
+ *
+ * @param element The DOM tree node that represents the element
+ */
+ Component processGlueElement(Element element) {
+ String direction = element.getAttribute("direction");
+ if (direction.equals("horizontal"))
+ return Box.createHorizontalGlue();
+ else return Box.createVerticalGlue();
+ }
+
+ private CommandBlock processInitElement(Element element) throws SAXException {
+ return new CommandBlock(element, this);
+ }
+
+
+
+ /**
+ * Writes the XML representation of this form to the specified
+ * byte stream
+ *
+ * @param out the specified byte stream
+ */
+ public void serialize(OutputStream out) throws IOException {
+ try {
+ DocumentBuilder builder = domFactory.newDocumentBuilder();
+ Document document = builder.newDocument();
+ document.appendChild(getDOMElement(document));
+
+ DOMImplementationLS ls = (DOMImplementationLS)
+ document.getImplementation().getFeature("LS", "3.0");
+ LSOutput output = ls.createLSOutput();
+ output.setEncoding("UTF-8");
+ output.setByteStream(out);
+ ls.createLSSerializer().write(document, output);
+ out.close();
+
+ /*
+ String method = org.apache.xml.serialize.Method.XML;
+ OutputFormat format = new OutputFormat(method, "UTF-8", true);
+ format.setLineWidth(0);
+ XMLSerializer serializer = new XMLSerializer(out, format);
+ serializer.serialize(document);
+ */
+ }
+ catch (ParserConfigurationException pce) {
+ IOException ioe = new IOException(pce.getMessage());
+ ioe.initCause(pce);
+ throw ioe;
+ }
+ }
+
+ private boolean isValidType(Class type) {
+ return type.isPrimitive()
+ || type == String.class
+ || type == Datum.class
+ || org.das2.datum.Datum.class.isAssignableFrom(type)
+ || Number.class.isAssignableFrom(type);
+ }
+
+
+ public Object checkValue(String name, Class type, String tag) throws org.das2.DasPropertyException, org.das2.DasNameException {
+ try {
+ Object obj = application.getNameContext().get(name);
+ if (obj == null) {
+ throw new org.das2.DasNameException(name + " must be defined before it is used");
+ }
+ if (!type.isInstance(obj)) {
+ throw new org.das2.DasPropertyException(org.das2.DasPropertyException.TYPE_MISMATCH, name, null);
+ }
+ return obj;
+ }
+ catch (InvocationTargetException ite) {
+ throw new RuntimeException(ite);
+ }
+ }
+
+ public Object invoke(String name, String[] args) throws org.das2.DasPropertyException, DataFormatException, ParsedExpressionException, InvocationTargetException {
+ int lastDot = name.lastIndexOf('.');
+ if (lastDot == -1) throw new DataFormatException("No object associated with method name" + name);
+ String objectName = name.substring(0, lastDot);
+ String methodName = name.substring(lastDot+1);
+ org.das2.util.DasDie.println("object name: " + objectName);
+ org.das2.util.DasDie.println("method name: " + methodName);
+ Object o = application.getNameContext().get(objectName);
+ Method method = null;
+ try {
+ BeanInfo info = BeansUtil.getBeanInfo(o.getClass());
+ MethodDescriptor[] methodDescriptors = info.getMethodDescriptors();
+ for (int i = 0; i <= methodDescriptors.length; i++) {
+ if (i == methodDescriptors.length)
+ throw new org.das2.DasPropertyException(org.das2.DasPropertyException.NOT_DEFINED, methodName, objectName);
+ if (!methodDescriptors[i].getName().equals(methodName)) continue;
+ //if (methodDescriptors[i].getMethod().getParameterTypes().length != args.length) continue;
+ method = methodDescriptors[i].getMethod();
+ break;
+ }
+ Class[] parameterTypes = method.getParameterTypes();
+ Object[] argValues = new Object[args.length];
+ for (int i = 0; i < parameterTypes.length; i++) {
+ argValues[i] = application.getNameContext().parseValue(args[i], parameterTypes[i]);
+ }
+ return method.invoke(o, argValues);
+ }
+ catch (IntrospectionException ie) {
+ throw new DataFormatException(ie.getMessage());
+ }
+ catch (InvocationTargetException ite) {
+ throw new DataFormatException(ite.getTargetException().getMessage());
+ }
+ catch (IllegalAccessException iae) {
+ throw new DataFormatException(iae.getMessage());
+ }
+ }
+
+
+ public boolean getEditingMode() {
+ return editable;
+ }
+
+ public void setEditingMode(boolean b) {
+ if (editable != b) {
+ editable = b;
+ int componentCount = getComponentCount();
+ for (int i = 0; i < componentCount; i++) {
+ Component c = getComponent(i);
+ if (c instanceof FormTab) {
+ ((FormTab)c).setEditingMode(b);
+ }
+ }
+ if (windowList.size() > 0) {
+ if (b) {
+ if (desktop == null) {
+ desktop = new JDesktopPane();
+ }
+ add(desktop, "Windows");
+ }
+ else {
+ remove(desktop);
+ }
+ for (Iterator i = windowList.iterator(); i.hasNext();) {
+ FormWindow window = (FormWindow)i.next();
+ window.setEditingMode(b);
+ if (b) {
+ window.pack();
+ JInternalFrame it = window.getInternalFrame();
+ if (it.getParent() != desktop) {
+ desktop.add(it);
+ }
+ }
+ }
+ }
+ revalidate();
+ repaint();
+ if (b) {
+ firePropertyChange("editable", Boolean.FALSE, Boolean.TRUE);
+ }
+ else {
+ firePropertyChange("editable", Boolean.TRUE, Boolean.FALSE);
+ }
+ }
+ }
+
+ public FormBase getForm() {
+ return this;
+ }
+
+ public Element getDOMElement(Document document) {
+ Element element = document.createElement("das2");
+ for (int index = 0; index < getComponentCount(); index++) {
+ FormComponent child = (FormComponent)getComponent(index);
+ element.appendChild(child.getDOMElement(document));
+ }
+ if (!editable) {
+ for (Iterator i = windowList.iterator(); i.hasNext();) {
+ FormComponent child = (FormComponent)i.next();
+ element.appendChild(child.getDOMElement(document));
+ }
+ }
+ return element;
+ }
+
+ /** Paints the component's border.
+ * Graphics. For example, you
+ * should not alter the clip Rectangle or modify the
+ * transform. If you need to do these operations you may find it
+ * easier to create a new Graphics from the passed in
+ * Graphics and manipulate it.
+ *
+ * @param g the Graphics context in which to paint
+ *
+ * @see #paint
+ * @see #setBorder
+ */
+ protected void paintBorder(Graphics g) {
+ super.paintBorder(g);
+ if (onHover) {
+ Graphics2D g2 = (Graphics2D)g.create();
+ Stroke thick = new BasicStroke(3.0f);
+ g2.setStroke(thick);
+ g2.setColor(Color.GRAY);
+ g2.drawRect(1, 1, getWidth() - 2, getHeight() - 2);
+ g2.dispose();
+ }
+ }
+
+ public org.das2.util.DnDSupport getDnDSupport() {
+ return null;
+ }
+
+ public boolean startDrag(int x, int y, int action, java.awt.event.MouseEvent evt) {
+ return false;
+ }
+
+ public String getDasName() {
+ return null;
+ }
+
+ public List getWindowList() {
+ return Collections.unmodifiableList(windowList);
+ }
+
+ public void setDasName(String name) throws org.das2.DasNameException {
+ throw new org.das2.DasNameException();
+ }
+
+ public void deregisterComponent() {
+ for (int index = 0; index < getComponentCount(); index++) {
+ Component c = getComponent(index);
+ if (c instanceof FormComponent) {
+ ((FormComponent)c).deregisterComponent();
+ }
+ }
+ for (Iterator i = windowList.iterator(); i.hasNext();) {
+ FormWindow w = (FormWindow)i.next();
+ w.deregisterComponent();
+ }
+ }
+
+ public org.das2.DasApplication getDasApplication() {
+ return application;
+ }
+
+ public void registerComponent() throws org.das2.DasException {
+ for (int index = 0; index < getComponentCount(); index++) {
+ Component c = getComponent(index);
+ if (c instanceof FormComponent) {
+ ((FormComponent)c).registerComponent();
+ }
+ }
+ for (Iterator i = windowList.iterator(); i.hasNext();) {
+ FormWindow w = (FormWindow)i.next();
+ w.registerComponent();
+ }
+ }
+
+ private class DnDSupport implements DropTargetListener {
+
+ private final Set acceptableFlavors = new HashSet(Arrays.asList(new DataFlavor[] {
+ TransferableFormComponent.TAB_FLAVOR,
+ TransferableFormComponent.WINDOW_FLAVOR
+ }));
+
+ /** Called while a drag operation is ongoing, when the mouse pointer enters
+ * the operable part of the drop site for the DropTarget
+ * registered with this listener.
+ *
+ * @param dtde the DropTargetDragEvent
+ */
+ public void dragEnter(DropTargetDragEvent dtde) {
+ if (canAccept(dtde.getCurrentDataFlavors())) {
+ dtde.acceptDrag(dtde.getSourceActions());
+ onHover = true;
+ repaint();
+ }
+ }
+
+ /** Called while a drag operation is ongoing, when the mouse pointer has
+ * exited the operable part of the drop site for the
+ * DropTarget registered with this listener.
+ *
+ * @param dte the DropTargetEvent
+ */
+ public void dragExit(DropTargetEvent dte) {
+ onHover = false;
+ repaint();
+ }
+
+ /** Called when a drag operation is ongoing, while the mouse pointer is still
+ * over the operable part of the drop site for the DropTarget
+ * registered with this listener.
+ *
+ * @param dtde the DropTargetDragEvent
+ */
+ public void dragOver(DropTargetDragEvent dtde) {
+ }
+
+ /** Called when the drag operation has terminated with a drop on
+ * the operable part of the drop site for the DropTarget
+ * registered with this listener.
+ * DropTargetDropEvent
+ * provides a means to obtain a Transferable
+ * object that represents the data object(s) to
+ * be transfered.DropTargetListener
+ * shall accept or reject the drop via the
+ * acceptDrop(int dropAction) or rejectDrop() methods of the
+ * DropTargetDropEvent parameter.
+ * DropTargetDropEvent's getTransferable()
+ * method may be invoked, and data transfer may be
+ * performed via the returned Transferable's
+ * getTransferData() method.
+ * boolean to the DropTargetDropEvent's
+ * dropComplete(boolean success) method.
+ * DropTargetDropEvent's dropComplete(boolean success) method.
+ * After that, a call to the getTransferData() method of the
+ * Transferable returned by
+ * DropTargetDropEvent.getTransferable() is guaranteed to
+ * succeed only if the data transfer is local; that is, only if
+ * DropTargetDropEvent.isLocalTransfer() returns
+ * true. Otherwise, the behavior of the call is
+ * implementation-dependent.
+ * DropTargetDropEvent
+ */
+ public void drop(DropTargetDropEvent dtde) {
+ boolean success = false;
+ if (canAccept(dtde.getCurrentDataFlavors())) {
+ Transferable t = dtde.getTransferable();
+ if (t.isDataFlavorSupported(TransferableFormComponent.COMPONENT_FLAVOR)) {
+ dtde.acceptDrop(dtde.getDropAction());
+ success = acceptComponent(t);
+ }
+ else if (t.isDataFlavorSupported(TransferableFormComponent.DASML_FRAGMENT_FLAVOR)) {
+ dtde.acceptDrop(DnDConstants.ACTION_COPY);
+ success = acceptFragment(t);
+ }
+ dtde.dropComplete(success);
+ }
+ else {
+ dtde.rejectDrop();
+ }
+ onHover = false;
+ repaint();
+ }
+
+ private boolean acceptFragment(Transferable t) {
+ boolean success = false;
+ try {
+ String data = (String)t.getTransferData(TransferableFormComponent.DASML_FRAGMENT_FLAVOR);
+ Document document = FormBase.parseDasML(new StringReader(data), null);
+ Element root = document.getDocumentElement();
+ if (root.getTagName().equals("form")) {
+ FormTab tab = new FormTab(root, FormBase.this);
+ addForm(tab);
+ success = true;
+ revalidate();
+ }
+ else if (root.getTagName().equals("window")) {
+ FormWindow window = new FormWindow(root, FormBase.this);
+ addWindow(window);
+ success = true;
+ revalidate();
+ }
+ }
+ catch (org.das2.dasml.ParsedExpressionException pee) {
+ pee.printStackTrace();
+ }
+
+ catch (org.das2.DasException de) {
+ de.printStackTrace();
+ } catch (UnsupportedFlavorException ufe) {
+ //Allow to fall through.
+ //exception is handled by allowing success to remain false
+ }
+ catch (IOException ioe) {
+ DasExceptionHandler.handle(ioe);
+ //Allow to fall through.
+ //exception is handled by allowing success to remain false
+ }
+ catch (ParserConfigurationException pce) {
+ DasExceptionHandler.handle(pce);
+ //Allow to fall through.
+ //exception is handled by allowing success to remain false
+ }
+ catch (SAXException se) {
+ DasExceptionHandler.handle(se);
+ //Allow to fall through.
+ //exception is handled by allowing success to remain false
+ }
+ return success;
+ }
+
+ private boolean acceptComponent(Transferable t) {
+ boolean success = false;
+ try {
+ Component c = (Component)t.getTransferData(TransferableFormComponent.COMPONENT_FLAVOR);
+ if (c instanceof FormTab) {
+ addForm((FormTab)c);
+ success = true;
+ revalidate();
+ }
+ else if (c instanceof FormWindow) {
+ addWindow((FormWindow)c);
+ success = true;
+ revalidate();
+ }
+ else {
+ System.out.println(c);
+ }
+ }
+ catch (UnsupportedFlavorException ufe) {
+ //Allow to fall through.
+ //exception is handled by allowing success to remain false
+ }
+ catch (IOException ioe) {
+ //Allow to fall through.
+ //exception is handled by allowing success to remain false
+ }
+ return success;
+ }
+
+ /** Called if the user has modified
+ * the current drop gesture.
+ * DropTargetDragEvent
+ */
+ public void dropActionChanged(DropTargetDragEvent dtde) {
+ if (onHover) {
+ dtde.acceptDrag(dtde.getDropAction());
+ }
+ }
+
+ private boolean canAccept(DataFlavor[] flavors) {
+ for (int i = 0; i < flavors.length; i++) {
+ if (acceptableFlavors.contains(flavors[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ }
+
+}
diff --git a/dasCore/src/main/java/org/das2/dasml/FormButton.java b/dasCore/src/main/java/org/das2/dasml/FormButton.java
new file mode 100644
index 000000000..1503fdf08
--- /dev/null
+++ b/dasCore/src/main/java/org/das2/dasml/FormButton.java
@@ -0,0 +1,228 @@
+/* File: FormButton.java
+ * Copyright (C) 2002-2003 The University of Iowa
+ * Created by: Jeremy Faden