android: AndrOBD library vendored (no submodule, no git link)
This commit is contained in:
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* (C) Copyright 2015 by fr3ts0n <erwin.scheuch-heilig@gmx.at>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.fr3ts0n.pvs;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* generic Handler interface for mapped Data
|
||||
*
|
||||
* @author $Author: erwin $
|
||||
*/
|
||||
interface DataMapHandler
|
||||
{
|
||||
/**
|
||||
* handle a set/map of data attributes
|
||||
*
|
||||
* @param data Map of new data attributes to handle
|
||||
* @return previous value of corresponding data item
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
Object handleData(Map data);
|
||||
}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* (C) Copyright 2015 by fr3ts0n <erwin.scheuch-heilig@gmx.at>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.fr3ts0n.pvs;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.util.Vector;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* Database backed process variable
|
||||
*
|
||||
* @author erwin
|
||||
*/
|
||||
public class DbProcessVar extends IndexedProcessVar
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1080116313924821619L;
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
private static final Vector<String> fields = new Vector();
|
||||
/**
|
||||
* Holds value of property dbConnection.
|
||||
*/
|
||||
private Connection dbConnection;
|
||||
/**
|
||||
* Holds value of property tableName.
|
||||
*/
|
||||
private String tableName;
|
||||
|
||||
/** Creates a new instance of DbProcessVar */
|
||||
private DbProcessVar()
|
||||
{
|
||||
}
|
||||
|
||||
public DbProcessVar(Connection dbConn)
|
||||
{
|
||||
this();
|
||||
setDbConnection(dbConn);
|
||||
}
|
||||
|
||||
public DbProcessVar(Connection dbConn, String tableName)
|
||||
{
|
||||
this();
|
||||
setDbConnection(dbConn);
|
||||
setTableName(tableName);
|
||||
}
|
||||
|
||||
/**
|
||||
* return all available field names
|
||||
*/
|
||||
public String[] getFields()
|
||||
{
|
||||
return ((String[]) fields.toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for property dbConnection.
|
||||
*
|
||||
* @return Value of property dbConnection.
|
||||
*/
|
||||
public Connection getDbConnection()
|
||||
{
|
||||
|
||||
return this.dbConnection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for property dbConnection.
|
||||
*
|
||||
* @param dbConnection New value of property dbConnection.
|
||||
*/
|
||||
private void setDbConnection(Connection dbConnection)
|
||||
{
|
||||
|
||||
this.dbConnection = dbConnection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for property tableName.
|
||||
*
|
||||
* @return Value of property tableName.
|
||||
*/
|
||||
public String getTableName()
|
||||
{
|
||||
return this.tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for property tableName.
|
||||
*
|
||||
* @param tableName New value of property tableName.
|
||||
*/
|
||||
private void setTableName(String tableName)
|
||||
{
|
||||
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
protected String getSelectSQL()
|
||||
{
|
||||
return ("SELECT * from " + tableName);
|
||||
}
|
||||
|
||||
protected ResultSet getResultSet(String sqlQuery)
|
||||
{
|
||||
ResultSet set = null;
|
||||
ResultSetMetaData rsMd;
|
||||
try
|
||||
{
|
||||
set = dbConnection.createStatement().executeQuery(sqlQuery);
|
||||
rsMd = set.getMetaData();
|
||||
for (int i = 0; i < rsMd.getColumnCount(); i++)
|
||||
{
|
||||
fields.add(i, rsMd.getColumnName(i));
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
log.log(Level.SEVERE, e.toString(), e);
|
||||
}
|
||||
return (set);
|
||||
}
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* (C) Copyright 2015 by fr3ts0n <erwin.scheuch-heilig@gmx.at>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.fr3ts0n.pvs;
|
||||
|
||||
/**
|
||||
* Process variable @see ProcessVar which allows indexed access
|
||||
* to attribute fields
|
||||
*
|
||||
* @author $Author: erwin $
|
||||
*/
|
||||
public abstract class IndexedProcessVar extends ProcessVar
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 8478458496218575203L;
|
||||
|
||||
/** return all available field names */
|
||||
public abstract String[] getFields();
|
||||
|
||||
protected IndexedProcessVar()
|
||||
{
|
||||
String flds[] = getFields();
|
||||
for (int i = 0; i < flds.length; i++)
|
||||
{
|
||||
put(flds[i], null);
|
||||
}
|
||||
}
|
||||
|
||||
/** indexed get for specified field id */
|
||||
public Object get(int fieldID)
|
||||
{
|
||||
return (get(getFields()[fieldID]));
|
||||
}
|
||||
|
||||
/** indexed put for specified field id */
|
||||
public void put(int fieldID, Object newValue)
|
||||
{
|
||||
put(getFields()[fieldID], newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* get attribute of selected key
|
||||
* overridden method to allow synchronized access
|
||||
*
|
||||
* @param fieldIndex index to key of attribute
|
||||
* @return value of attribute
|
||||
*/
|
||||
public int getAsInt(int fieldIndex)
|
||||
{
|
||||
return (getAsInt(getFields()[fieldIndex]));
|
||||
}
|
||||
|
||||
/**
|
||||
* set attribute of selected key to selected value
|
||||
* overridden method to allow notification of process var changes
|
||||
*
|
||||
* @param fieldIndex index to key of attribute
|
||||
* @param value value of attribute
|
||||
*/
|
||||
public void putAsInt(int fieldIndex, int value)
|
||||
{
|
||||
putAsInt(getFields()[fieldIndex], value);
|
||||
}
|
||||
|
||||
/** indexed put for specified field id */
|
||||
public Object remove(int fieldID)
|
||||
{
|
||||
return (remove(getFields()[fieldID]));
|
||||
}
|
||||
}
|
||||
+466
@@ -0,0 +1,466 @@
|
||||
/*
|
||||
* (C) Copyright 2015 by fr3ts0n <erwin.scheuch-heilig@gmx.at>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.fr3ts0n.pvs;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
// For logging ...
|
||||
|
||||
/**
|
||||
* single Process variable containing all attributes of a process object
|
||||
*
|
||||
* @author $Author: erwin $
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class ProcessVar
|
||||
extends HashMap
|
||||
implements PvChangeListener, Serializable
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 7072161686290674442L;
|
||||
/** name of key attribute */
|
||||
private Object KeyAttribute = null;
|
||||
/** default key attribute name */
|
||||
static final String DEF_KEYNAME = "key";
|
||||
/** time of last change * */
|
||||
private long lastChange = 0;
|
||||
/** type of last change * */
|
||||
private int lastChangeType = PvChangeEvent.PV_ADDED;
|
||||
/** default change action */
|
||||
int defaultAction = PvChangeEvent.PV_NOACTION;
|
||||
/** flag if to allow ChangeEvents to be fired */
|
||||
boolean allowEvents = false;
|
||||
/** list of process var change listeners */
|
||||
private transient Map<PvChangeListener, Integer> PvChangeListeners =
|
||||
Collections.synchronizedMap(new HashMap<PvChangeListener, Integer>());
|
||||
/** Map of attribute changes */
|
||||
private final Map<Object, PvChangeEvent> changes =
|
||||
Collections.synchronizedMap(new HashMap<Object, PvChangeEvent>());
|
||||
/** The logger object */
|
||||
public static final Logger log = Logger.getLogger(ProcessVar.class.getPackage().getName());
|
||||
|
||||
public ProcessVar()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
public ProcessVar(int initialSize)
|
||||
{
|
||||
super(initialSize);
|
||||
clear();
|
||||
}
|
||||
|
||||
/** construct with a existing Map */
|
||||
public ProcessVar(Map map)
|
||||
{
|
||||
if (map != null)
|
||||
{
|
||||
putAll(map);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* put all attributes from map into current ProcessVar
|
||||
* - use action for all notifications
|
||||
*
|
||||
* @param map data map to put into ProcessVar
|
||||
* @param action Action code to be used for notifications
|
||||
* @param allowChildEvents are child events (for each attribute) allowed?
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public synchronized void putAll(Map map, int action, boolean allowChildEvents)
|
||||
{
|
||||
// remember flag for event creation
|
||||
boolean oldAllowEvents = allowEvents;
|
||||
// disable event creation for each map field
|
||||
// (we want to send one single event after the full map is handled)
|
||||
allowEvents = allowChildEvents;
|
||||
// remember old default action
|
||||
int oldAction = defaultAction;
|
||||
// set new action as the default action for all fields
|
||||
defaultAction = action;
|
||||
// put all fields to hashmap (using default action)
|
||||
super.putAll(map);
|
||||
// restore old default action
|
||||
defaultAction = oldAction;
|
||||
// enable event creation again
|
||||
allowEvents = oldAllowEvents;
|
||||
// now fire the one and only event for this map change
|
||||
firePvChanged(new PvChangeEvent(this, getKeyAttribute(), map.values().toArray(), action));
|
||||
}
|
||||
|
||||
/**
|
||||
* put all attributes from map into current ProcessVar
|
||||
* - use action for all notifications
|
||||
*
|
||||
* @param map data map to put into ProcessVar
|
||||
* @param action Action code to be used for notifications
|
||||
*/
|
||||
private synchronized void putAll(Map map, int action)
|
||||
{
|
||||
putAll(map, action, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* put all attributes from map into current ProcessVar
|
||||
* - use default action for all notifications
|
||||
*
|
||||
* @param map data map to put into ProcessVar
|
||||
*/
|
||||
@Override
|
||||
public synchronized void putAll(Map map)
|
||||
{
|
||||
putAll(map, defaultAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* handler for process variable changes
|
||||
* forwarding of child process variables to current handler
|
||||
*/
|
||||
public synchronized void pvChanged(PvChangeEvent event)
|
||||
{
|
||||
log.finer(toString() + ":Child PvChange:" + event.toString());
|
||||
firePvChanged(new PvChangeEvent(this,
|
||||
((ProcessVar) event.getSource()).getKeyValue(),
|
||||
event.getSource(),
|
||||
event.getType() | PvChangeEvent.PV_CHILDCHANGE));
|
||||
}
|
||||
|
||||
/** return String representation */
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return (getClass().getName() + "[" + getKeyValue() + "]");
|
||||
}
|
||||
|
||||
/**
|
||||
* set attribute of selected key to selected value
|
||||
* overridden method to allow notification of process var changes
|
||||
*
|
||||
* @param key key of attribute
|
||||
* @param value value of attribute
|
||||
* @param action type of action event @see PvChangeEvent
|
||||
* @return previous value of attribute
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public synchronized Object put(Object key, Object value, int action)
|
||||
{
|
||||
Object oldvalue;
|
||||
|
||||
// if new value is a child process variable, try to re-use previous one ...
|
||||
if (value instanceof ProcessVar)
|
||||
{
|
||||
// get previous PV
|
||||
oldvalue = get(key);
|
||||
if (oldvalue instanceof ProcessVar)
|
||||
{
|
||||
// PV is existing
|
||||
((HashMap) oldvalue).putAll((Map) value);
|
||||
} else
|
||||
{
|
||||
// this will be a new child PV
|
||||
oldvalue = super.put(key, value);
|
||||
}
|
||||
} else
|
||||
{
|
||||
// NON child PV
|
||||
oldvalue = super.put(key, value);
|
||||
}
|
||||
|
||||
if (oldvalue == null)
|
||||
{
|
||||
// new attribute -> PV_ADDED
|
||||
if (value != null)
|
||||
{
|
||||
action |= PvChangeEvent.PV_ADDED;
|
||||
// if we add a new child process variable, add listener for child
|
||||
if (value instanceof ProcessVar)
|
||||
{
|
||||
((ProcessVar) value).addPvChangeListener(this);
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
// Attribute has changed -> PV_MODIFIED
|
||||
if (!oldvalue.equals(value))
|
||||
{
|
||||
action |= PvChangeEvent.PV_MODIFIED;
|
||||
} else
|
||||
{
|
||||
// Attribute MANUAL_MOD confirmed -> PV_CONFIRMED
|
||||
PvChangeEvent lstChange = changes.get(key);
|
||||
if (lstChange != null && (lstChange.getType() & PvChangeEvent.PV_MANUAL_MOD) != 0)
|
||||
{
|
||||
action |= PvChangeEvent.PV_CONFIRMED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
firePvChanged(new PvChangeEvent(this, key, value, action));
|
||||
|
||||
// .. and return
|
||||
return (oldvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* set attribute of selected key to selected value
|
||||
* overridden method to allow notification of process var changes
|
||||
*
|
||||
* @param key key of attribute
|
||||
* @param value value of attribute
|
||||
* @return previous value of attribute
|
||||
*/
|
||||
@Override
|
||||
public synchronized Object put(Object key, Object value)
|
||||
{
|
||||
// find out the type of the action
|
||||
int action = containsKey(key) ? defaultAction : PvChangeEvent.PV_ADDED;
|
||||
// and perform the put operation
|
||||
return (put(key, value, action));
|
||||
}
|
||||
|
||||
/**
|
||||
* get attribute of selected key
|
||||
* overridden method to allow synchronized access
|
||||
*
|
||||
* @param key key of attribute
|
||||
* @return value of attribute
|
||||
*/
|
||||
@Override
|
||||
public synchronized Object get(Object key)
|
||||
{
|
||||
return (super.get(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* get attribute of selected key as int value
|
||||
* overridden method to allow synchronized access
|
||||
*
|
||||
* @param key key of attribute
|
||||
* @return value of attribute
|
||||
*/
|
||||
synchronized int getAsInt(Object key)
|
||||
{
|
||||
int result = 0;
|
||||
Object val = get(key);
|
||||
try
|
||||
{
|
||||
if (val != null)
|
||||
{
|
||||
result = Integer.valueOf(val.toString()).intValue();
|
||||
}
|
||||
} catch (NumberFormatException e)
|
||||
{
|
||||
// Intentionally do nothing
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
* set attribute of selected key to selected value
|
||||
* overridden method to allow notification of process var changes
|
||||
*
|
||||
* @param key key of attribute
|
||||
* @param value value of attribute
|
||||
*/
|
||||
synchronized void putAsInt(Object key, int value)
|
||||
{
|
||||
put(key, Integer.valueOf(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* remove attribute with selected key
|
||||
* overridden method to allow notification of process var changes
|
||||
*
|
||||
* @param key key of attribute
|
||||
* @return previous value of attribute
|
||||
*/
|
||||
@Override
|
||||
public synchronized Object remove(Object key)
|
||||
{
|
||||
Object result = super.remove(key);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
firePvChanged(new PvChangeEvent(this, key, null, PvChangeEvent.PV_DELETED));
|
||||
}
|
||||
|
||||
// if old object was a process variable, we need to remove change listener
|
||||
if (result instanceof ProcessVar)
|
||||
{
|
||||
((ProcessVar) result).removePvChangeListener(this);
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
* remove all attributes from process var
|
||||
* overridden clear method to allow notification of process var changes
|
||||
*/
|
||||
@Override
|
||||
public synchronized void clear()
|
||||
{
|
||||
// now really clear the hashmap
|
||||
super.clear();
|
||||
// notify listeners of removal
|
||||
firePvChanged(new PvChangeEvent(this, null, null, PvChangeEvent.PV_CLEARED));
|
||||
}
|
||||
|
||||
/** get object/name of key attribute */
|
||||
public Object getKeyAttribute()
|
||||
{
|
||||
return (KeyAttribute != null ? KeyAttribute : DEF_KEYNAME);
|
||||
}
|
||||
|
||||
/** set object/name of key attribute */
|
||||
public void setKeyAttribute(Object newKeyAttribute)
|
||||
{
|
||||
KeyAttribute = newKeyAttribute;
|
||||
}
|
||||
|
||||
/** get value of key attribute */
|
||||
public Object getKeyValue()
|
||||
{
|
||||
return (get(getKeyAttribute()));
|
||||
}
|
||||
|
||||
/** set value of key attribute */
|
||||
public void setKeyValue(Object newKeyValue)
|
||||
{
|
||||
put(getKeyAttribute(), newKeyValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* ensure there is a list of PvChangeListeners
|
||||
* * it may be null, if PV has been de-serialized
|
||||
*/
|
||||
private void ensurePvChangeListeners()
|
||||
{
|
||||
if (PvChangeListeners == null)
|
||||
PvChangeListeners = new HashMap<PvChangeListener, Integer>();
|
||||
}
|
||||
/**
|
||||
* Handling for list of PvChangeListeners
|
||||
*/
|
||||
/** remove listener for Pv changes */
|
||||
public synchronized void removePvChangeListener(PvChangeListener l)
|
||||
{
|
||||
ensurePvChangeListeners();
|
||||
PvChangeListeners.remove(l);
|
||||
allowEvents = !PvChangeListeners.isEmpty();
|
||||
log.finer("-PvListener:" + toString() + "->" + String.valueOf(l));
|
||||
}
|
||||
|
||||
/**
|
||||
* add listener for Pv changes with specified change events
|
||||
*
|
||||
* @param l event listener to be registered
|
||||
* @param eventMask events the listener wants to be notified about
|
||||
*/
|
||||
public synchronized void addPvChangeListener(PvChangeListener l, int eventMask)
|
||||
{
|
||||
ensurePvChangeListeners();
|
||||
PvChangeListeners.put(l, Integer.valueOf(eventMask));
|
||||
allowEvents = true;
|
||||
log.finer("+PvListener:" + toString() + "->" + String.valueOf(l));
|
||||
}
|
||||
|
||||
/**
|
||||
* add listener for Pv changes
|
||||
*
|
||||
* @param l event listener to be registered
|
||||
*/
|
||||
public synchronized void addPvChangeListener(PvChangeListener l)
|
||||
{
|
||||
addPvChangeListener(l, PvChangeEvent.PV_ALLEVENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* fire a Pv Change event
|
||||
*
|
||||
* @param e the event to be fired
|
||||
*/
|
||||
public synchronized void firePvChanged(PvChangeEvent e)
|
||||
{
|
||||
if (allowEvents && e.getType() != PvChangeEvent.PV_NOACTION)
|
||||
{
|
||||
log.finer("PvChange:" + e.toString());
|
||||
|
||||
Integer evtMask;
|
||||
Map.Entry curr;
|
||||
|
||||
ensurePvChangeListeners();
|
||||
// loop through all registered listeners ...
|
||||
Set entries = PvChangeListeners.entrySet();
|
||||
Iterator it = entries.iterator();
|
||||
|
||||
while (it.hasNext())
|
||||
{
|
||||
curr = (Map.Entry) it.next();
|
||||
|
||||
if (curr.getKey() != null && curr.getKey() != this)
|
||||
{
|
||||
// check if listener wants to be notified by this event
|
||||
evtMask = (Integer) curr.getValue();
|
||||
|
||||
if ((evtMask.intValue() & e.getType()) != 0)
|
||||
{
|
||||
log.finer("Notify:" + curr);
|
||||
((PvChangeListener) curr.getKey()).pvChanged(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
// set time and type of last change
|
||||
lastChange = e.getTime();
|
||||
lastChangeType = e.getType();
|
||||
changes.put(e.getKey(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for property values.
|
||||
*
|
||||
* @return Value of property values.
|
||||
*/
|
||||
public Map getValueMap()
|
||||
{
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for property values.
|
||||
*
|
||||
* @param values New value of property values.
|
||||
*/
|
||||
public void setValueMap(Map values)
|
||||
{
|
||||
putAll(values);
|
||||
}
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* (C) Copyright 2015 by fr3ts0n <erwin.scheuch-heilig@gmx.at>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.fr3ts0n.pvs;
|
||||
|
||||
import java.util.EventObject;
|
||||
|
||||
/**
|
||||
* Event to notify about changes to a process variable
|
||||
*
|
||||
* @author $Author: erwin $
|
||||
*/
|
||||
public class PvChangeEvent extends EventObject
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 4378855847270229897L;
|
||||
public static final int PV_NOACTION = 0x00; /**< NO specified PV action */
|
||||
public static final int PV_ADDED = 0x01; /**< new Process var was added */
|
||||
public static final int PV_DELETED = 0x02; /**< process var was deleted */
|
||||
public static final int PV_MODIFIED = 0x04; /**< process var was modified */
|
||||
public static final int PV_CONFIRMED = 0x08; /**< process var was confirmed */
|
||||
public static final int PV_MANUAL_MOD = 0x10; /**< process var was modified manually */
|
||||
public static final int PV_CLEARED = 0x20; /**< process var was cleared */
|
||||
public static final int PV_ERROR = 0x40; /**< process var has an error */
|
||||
public static final int PV_ELIMINATED = 0x80; /**< process var got eliminated */
|
||||
public static final int PV_CHILDCHANGE = 0x8000000; /**< child process var change */
|
||||
private static final int PV_ALLACTIONS = ~PV_CHILDCHANGE; /**< mask for all actions */
|
||||
public static final int PV_ALLEVENTS = 0xFFFFFFFF; /**< mask for all change types */
|
||||
private int type = PV_MODIFIED;
|
||||
private Object key = ProcessVar.DEF_KEYNAME;
|
||||
private Object value = ProcessVar.DEF_KEYNAME;
|
||||
private long time = System.currentTimeMillis();
|
||||
|
||||
public PvChangeEvent(Object source, Object Key, Object Value, int Type)
|
||||
{
|
||||
super(source);
|
||||
setType(Type);
|
||||
setKey(Key);
|
||||
setValue(Value);
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return (type & PV_ALLACTIONS);
|
||||
}
|
||||
|
||||
public boolean isChildEvent()
|
||||
{
|
||||
return (type & PV_CHILDCHANGE) != 0;
|
||||
}
|
||||
|
||||
private void setType(int newType)
|
||||
{
|
||||
type = newType;
|
||||
}
|
||||
|
||||
private void setKey(Object newKey)
|
||||
{
|
||||
key = newKey;
|
||||
}
|
||||
|
||||
public Object getKey()
|
||||
{
|
||||
return (key);
|
||||
}
|
||||
|
||||
private void setValue(Object newValue)
|
||||
{
|
||||
value = newValue;
|
||||
}
|
||||
|
||||
public Object getValue()
|
||||
{
|
||||
return (value);
|
||||
}
|
||||
|
||||
/** return String Representation of Event */
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return (String.valueOf(getType()) + ":" + getKey() + "=" + getValue());
|
||||
}
|
||||
|
||||
public long getTime()
|
||||
{
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(long time)
|
||||
{
|
||||
this.time = time;
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* (C) Copyright 2015 by fr3ts0n <erwin.scheuch-heilig@gmx.at>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.fr3ts0n.pvs;
|
||||
|
||||
import java.util.EventListener;
|
||||
|
||||
/**
|
||||
* Listener interface for notification of process variable changes
|
||||
*
|
||||
* @author $Author: erwin $
|
||||
*/
|
||||
public interface PvChangeListener extends EventListener
|
||||
{
|
||||
|
||||
/**
|
||||
* handler for process variable changes
|
||||
*/
|
||||
void pvChanged(PvChangeEvent event);
|
||||
|
||||
}
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* (C) Copyright 2015 by fr3ts0n <erwin.scheuch-heilig@gmx.at>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.fr3ts0n.pvs;
|
||||
|
||||
/**
|
||||
* Range check to allow checking a process var to be within certain range
|
||||
*
|
||||
* @author erwin
|
||||
*/
|
||||
public class PvLimits
|
||||
{
|
||||
/** result codes */
|
||||
/** value is within specified range */
|
||||
private static final byte RC_WITHIN_RANGE = 0x00;
|
||||
/** value is above specified range */
|
||||
private static final byte RC_ABOVE_RANGE = 0x01;
|
||||
/** value is below specified range */
|
||||
private static final byte RC_BELOW_RANGE = 0x02;
|
||||
|
||||
/** minimum limit for range check */
|
||||
@SuppressWarnings("rawtypes")
|
||||
private Comparable minValue;
|
||||
/** maximum limit for range check */
|
||||
@SuppressWarnings("rawtypes")
|
||||
private Comparable maxValue;
|
||||
|
||||
/**
|
||||
* Creates a new instance of PvLimits
|
||||
*/
|
||||
public PvLimits()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of PvLimits
|
||||
*
|
||||
* @param minVal minimum Limit for range check. Setting this value to NULL disables
|
||||
* the check for value above limit
|
||||
* @param maxVal maximum Limit for range check. Setting this value to NULL disables
|
||||
* the check for value below limit
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public PvLimits(Comparable minVal, Comparable maxVal)
|
||||
{
|
||||
minValue = minVal;
|
||||
maxValue = maxVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for property minValue.
|
||||
*
|
||||
* @return Value of property minValue.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Comparable getMinValue()
|
||||
{
|
||||
return this.minValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for property minValue.
|
||||
*
|
||||
* @param minValue New value of property minValue.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void setMinValue(Comparable minValue)
|
||||
{
|
||||
this.minValue = minValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for property maxValue.
|
||||
*
|
||||
* @return Value of property maxValue.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Comparable getMaxValue()
|
||||
{
|
||||
return this.maxValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for property maxValue.
|
||||
*
|
||||
* @param maxValue New value of property maxValue.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void setMaxValue(Comparable maxValue)
|
||||
{
|
||||
this.maxValue = maxValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* check a value against defined range This method may be called from a static
|
||||
* context
|
||||
*
|
||||
* @param value the value to be checked
|
||||
* @param minLimit minimum Limit for range check.
|
||||
* @param maxLimit maximum Limit for range check.
|
||||
* @return bitmasked check result
|
||||
* @see PvLimits#RC_WITHIN_RANGE
|
||||
* @see PvLimits#RC_ABOVE_RANGE
|
||||
* @see PvLimits#RC_BELOW_RANGE
|
||||
*/
|
||||
private static byte checkRange(Object value, Comparable<Object> minLimit,
|
||||
Comparable<Object> maxLimit)
|
||||
{
|
||||
byte retVal = RC_WITHIN_RANGE;
|
||||
// check Range Minimum
|
||||
if (minLimit != null && minLimit.compareTo(value) > 0)
|
||||
retVal |= RC_BELOW_RANGE;
|
||||
// check Range Maximum
|
||||
if (maxLimit != null && maxLimit.compareTo(value) < 0)
|
||||
retVal |= RC_ABOVE_RANGE;
|
||||
return (retVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* check a value against range defined within class instance
|
||||
*
|
||||
* @param value the value to be checked
|
||||
* @return bitmasked check result
|
||||
* @see PvLimits#RC_WITHIN_RANGE
|
||||
* @see PvLimits#RC_ABOVE_RANGE
|
||||
* @see PvLimits#RC_BELOW_RANGE
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public byte checkRange(Object value)
|
||||
{
|
||||
return (checkRange(value, minValue, maxValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* return value limited against range defined within class instance
|
||||
*
|
||||
* @param value the value to be checked
|
||||
* @return value limited to limits
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object limitedValue(Object value)
|
||||
{
|
||||
Object result;
|
||||
switch (checkRange(value, minValue, maxValue))
|
||||
{
|
||||
case RC_BELOW_RANGE:
|
||||
result = minValue;
|
||||
break;
|
||||
|
||||
case RC_ABOVE_RANGE:
|
||||
result = maxValue;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Executable
+105
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* (C) Copyright 2015 by fr3ts0n <erwin.scheuch-heilig@gmx.at>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.fr3ts0n.pvs;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* List of multiple Process vars of the same type<br>
|
||||
* all the process variables are stored/identified by their key value
|
||||
*
|
||||
* @author $Author: erwin $
|
||||
*/
|
||||
public class PvList extends ProcessVar
|
||||
implements DataMapHandler
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -4024558082429586661L;
|
||||
|
||||
public PvList()
|
||||
{
|
||||
}
|
||||
|
||||
public PvList(Object key)
|
||||
{
|
||||
super.setKeyAttribute(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* handle a set/map of data attributes with specified notification action
|
||||
*
|
||||
* @param data Map of new data attributes to handle
|
||||
* @param action PvChangeEvent-Action code to be used for notifications
|
||||
* @param allowChildEvents are child events (for each attribute) allowed?
|
||||
* @return previous value of corresponding data item
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
private synchronized Object handleData(Map data, int action, boolean allowChildEvents)
|
||||
{
|
||||
Object result = null;
|
||||
|
||||
|
||||
if (data.containsKey(getKeyAttribute()))
|
||||
{
|
||||
// remember flag for event creation
|
||||
boolean oldAllowEvents = allowEvents;
|
||||
// set flag for event creation
|
||||
allowEvents = allowChildEvents;
|
||||
ProcessVar dataset = (ProcessVar) get(data.get(getKeyAttribute()));
|
||||
if (dataset == null)
|
||||
{
|
||||
dataset = new ProcessVar();
|
||||
dataset.setKeyAttribute(getKeyAttribute());
|
||||
}
|
||||
dataset.putAll(data, action, allowChildEvents);
|
||||
// restore flag for event creation
|
||||
allowEvents = oldAllowEvents;
|
||||
result = put(dataset.getKeyValue(), dataset, action);
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
* handle a set/map of data attributes with specified notification action
|
||||
*
|
||||
* @param data Map of new data attributes to handle
|
||||
* @param action PvChangeEvent-Action code to be used for notifications
|
||||
* @return previous value of corresponding data item
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
private synchronized Object handleData(Map data, int action)
|
||||
{
|
||||
return (handleData(data, action, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* handle a set/map of data attributes with default notification action
|
||||
*
|
||||
* @param data Map of new data attributes to handle
|
||||
* @return previous value of corresponding data item
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public synchronized Object handleData(Map data)
|
||||
{
|
||||
return (handleData(data, defaultAction));
|
||||
}
|
||||
}
|
||||
+275
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* (C) Copyright 2015 by fr3ts0n <erwin.scheuch-heilig@gmx.at>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.fr3ts0n.pvs.gui;
|
||||
|
||||
import com.fr3ts0n.pvs.ProcessVar;
|
||||
|
||||
import java.beans.BeanDescriptor;
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.EventSetDescriptor;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.MethodDescriptor;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.beans.SimpleBeanInfo;
|
||||
|
||||
/**
|
||||
* @author esh
|
||||
*/
|
||||
class ProcessVarBeanInfo extends SimpleBeanInfo
|
||||
{
|
||||
|
||||
// Bean descriptor//GEN-FIRST:BeanDescriptor
|
||||
/*lazy BeanDescriptor*/
|
||||
private static BeanDescriptor getBdescriptor()
|
||||
{
|
||||
|
||||
// Here you can add code for customizing the BeanDescriptor.
|
||||
|
||||
return new BeanDescriptor(ProcessVar.class, PvDetailPanel.class);
|
||||
}//GEN-LAST:BeanDescriptor
|
||||
|
||||
// Property identifiers//GEN-FIRST:Properties
|
||||
private static final int PROPERTY_empty = 0;
|
||||
private static final int PROPERTY_keyAttribute = 1;
|
||||
private static final int PROPERTY_keyValue = 2;
|
||||
private static final int PROPERTY_valueMap = 3;
|
||||
|
||||
// Property array
|
||||
/*lazy PropertyDescriptor*/
|
||||
private static PropertyDescriptor[] getPdescriptor()
|
||||
{
|
||||
PropertyDescriptor[] properties = new PropertyDescriptor[4];
|
||||
|
||||
try
|
||||
{
|
||||
properties[PROPERTY_empty] = new PropertyDescriptor("empty", ProcessVar.class, "isEmpty", null);
|
||||
properties[PROPERTY_keyAttribute] = new PropertyDescriptor("keyAttribute", ProcessVar.class, "getKeyAttribute", "setKeyAttribute");
|
||||
properties[PROPERTY_keyValue] = new PropertyDescriptor("keyValue", ProcessVar.class, "getKeyValue", "setKeyValue");
|
||||
properties[PROPERTY_valueMap] = new PropertyDescriptor("valueMap", ProcessVar.class, "getValueMap", "setValueMap");
|
||||
properties[PROPERTY_valueMap].setPropertyEditorClass(PvDetailPanel.class);
|
||||
} catch (IntrospectionException ignored)
|
||||
{
|
||||
}//GEN-HEADEREND:Properties
|
||||
|
||||
// Here you can add code for customizing the properties array.
|
||||
|
||||
return properties;
|
||||
}//GEN-LAST:Properties
|
||||
|
||||
// EventSet identifiers//GEN-FIRST:Events
|
||||
private static final int EVENT_pvChangeListener = 0;
|
||||
|
||||
// EventSet array
|
||||
/*lazy EventSetDescriptor*/
|
||||
private static EventSetDescriptor[] getEdescriptor()
|
||||
{
|
||||
EventSetDescriptor[] eventSets = new EventSetDescriptor[1];
|
||||
|
||||
try
|
||||
{
|
||||
eventSets[EVENT_pvChangeListener] = new EventSetDescriptor(com.fr3ts0n.pvs.ProcessVar.class, "pvChangeListener", com.fr3ts0n.pvs.PvChangeListener.class, new String[]{"pvChanged"}, "addPvChangeListener", "removePvChangeListener");
|
||||
} catch (IntrospectionException ignored)
|
||||
{
|
||||
}//GEN-HEADEREND:Events
|
||||
|
||||
// Here you can add code for customizing the event sets array.
|
||||
|
||||
return eventSets;
|
||||
}//GEN-LAST:Events
|
||||
|
||||
// Method identifiers//GEN-FIRST:Methods
|
||||
private static final int METHOD_addPvChangeListener0 = 0;
|
||||
private static final int METHOD_clear1 = 1;
|
||||
private static final int METHOD_clone2 = 2;
|
||||
private static final int METHOD_containsKey3 = 3;
|
||||
private static final int METHOD_containsValue4 = 4;
|
||||
private static final int METHOD_entrySet5 = 5;
|
||||
private static final int METHOD_equals6 = 6;
|
||||
private static final int METHOD_get7 = 7;
|
||||
private static final int METHOD_hashCode8 = 8;
|
||||
private static final int METHOD_keySet9 = 9;
|
||||
private static final int METHOD_put10 = 10;
|
||||
private static final int METHOD_putAll11 = 11;
|
||||
private static final int METHOD_pvChanged12 = 12;
|
||||
private static final int METHOD_remove13 = 13;
|
||||
private static final int METHOD_size14 = 14;
|
||||
private static final int METHOD_toString15 = 15;
|
||||
private static final int METHOD_values16 = 16;
|
||||
|
||||
// Method array
|
||||
/*lazy MethodDescriptor*/
|
||||
private static MethodDescriptor[] getMdescriptor()
|
||||
{
|
||||
MethodDescriptor[] methods = new MethodDescriptor[17];
|
||||
|
||||
try
|
||||
{
|
||||
methods[METHOD_addPvChangeListener0] = new MethodDescriptor(com.fr3ts0n.pvs.ProcessVar.class.getMethod("addPvChangeListener",
|
||||
com.fr3ts0n.pvs.PvChangeListener.class, Integer.TYPE));
|
||||
methods[METHOD_addPvChangeListener0].setDisplayName("");
|
||||
methods[METHOD_clear1] = new MethodDescriptor(com.fr3ts0n.pvs.ProcessVar.class.getMethod("clear"));
|
||||
methods[METHOD_clear1].setDisplayName("");
|
||||
methods[METHOD_clone2] = new MethodDescriptor(com.fr3ts0n.pvs.ProcessVar.class.getMethod("clone"));
|
||||
methods[METHOD_clone2].setDisplayName("");
|
||||
methods[METHOD_containsKey3] = new MethodDescriptor(com.fr3ts0n.pvs.ProcessVar.class.getMethod("containsKey",
|
||||
Object.class));
|
||||
methods[METHOD_containsKey3].setDisplayName("");
|
||||
methods[METHOD_containsValue4] = new MethodDescriptor(com.fr3ts0n.pvs.ProcessVar.class.getMethod("containsValue",
|
||||
Object.class));
|
||||
methods[METHOD_containsValue4].setDisplayName("");
|
||||
methods[METHOD_entrySet5] = new MethodDescriptor(com.fr3ts0n.pvs.ProcessVar.class.getMethod("entrySet"));
|
||||
methods[METHOD_entrySet5].setDisplayName("");
|
||||
methods[METHOD_equals6] = new MethodDescriptor(com.fr3ts0n.pvs.ProcessVar.class.getMethod("equals",
|
||||
Object.class));
|
||||
methods[METHOD_equals6].setDisplayName("");
|
||||
methods[METHOD_get7] = new MethodDescriptor(com.fr3ts0n.pvs.ProcessVar.class.getMethod("get",
|
||||
Object.class));
|
||||
methods[METHOD_get7].setDisplayName("");
|
||||
methods[METHOD_hashCode8] = new MethodDescriptor(com.fr3ts0n.pvs.ProcessVar.class.getMethod("hashCode"));
|
||||
methods[METHOD_hashCode8].setDisplayName("");
|
||||
methods[METHOD_keySet9] = new MethodDescriptor(com.fr3ts0n.pvs.ProcessVar.class.getMethod("keySet"));
|
||||
methods[METHOD_keySet9].setDisplayName("");
|
||||
methods[METHOD_put10] = new MethodDescriptor(com.fr3ts0n.pvs.ProcessVar.class.getMethod("put",
|
||||
Object.class, Object.class, Integer.TYPE));
|
||||
methods[METHOD_put10].setDisplayName("");
|
||||
methods[METHOD_putAll11] = new MethodDescriptor(com.fr3ts0n.pvs.ProcessVar.class.getMethod("putAll",
|
||||
java.util.Map.class, Integer.TYPE, Boolean.TYPE));
|
||||
methods[METHOD_putAll11].setDisplayName("");
|
||||
methods[METHOD_pvChanged12] = new MethodDescriptor(com.fr3ts0n.pvs.ProcessVar.class.getMethod("pvChanged",
|
||||
com.fr3ts0n.pvs.PvChangeEvent.class));
|
||||
methods[METHOD_pvChanged12].setDisplayName("");
|
||||
methods[METHOD_remove13] = new MethodDescriptor(com.fr3ts0n.pvs.ProcessVar.class.getMethod("remove",
|
||||
Object.class));
|
||||
methods[METHOD_remove13].setDisplayName("");
|
||||
methods[METHOD_size14] = new MethodDescriptor(com.fr3ts0n.pvs.ProcessVar.class.getMethod("size"));
|
||||
methods[METHOD_size14].setDisplayName("");
|
||||
methods[METHOD_toString15] = new MethodDescriptor(com.fr3ts0n.pvs.ProcessVar.class.getMethod("toString"));
|
||||
methods[METHOD_toString15].setDisplayName("");
|
||||
methods[METHOD_values16] = new MethodDescriptor(com.fr3ts0n.pvs.ProcessVar.class.getMethod("values"));
|
||||
methods[METHOD_values16].setDisplayName("");
|
||||
} catch (Exception ignored)
|
||||
{
|
||||
}//GEN-HEADEREND:Methods
|
||||
|
||||
// Here you can add code for customizing the methods array.
|
||||
|
||||
return methods;
|
||||
}//GEN-LAST:Methods
|
||||
|
||||
private static final int defaultPropertyIndex = -1;//GEN-BEGIN:Idx
|
||||
private static final int defaultEventIndex = -1;//GEN-END:Idx
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public BeanInfo[] getAdditionalBeanInfo()
|
||||
{//GEN-FIRST:Superclass
|
||||
Class superclass = ProcessVar.class.getSuperclass();
|
||||
BeanInfo sbi = null;
|
||||
try
|
||||
{
|
||||
sbi = Introspector.getBeanInfo(superclass);//GEN-HEADEREND:Superclass
|
||||
|
||||
// Here you can add code for customizing the Superclass BeanInfo.
|
||||
|
||||
} catch (IntrospectionException ignored)
|
||||
{
|
||||
}
|
||||
return new BeanInfo[]{sbi};
|
||||
}//GEN-LAST:Superclass
|
||||
|
||||
/**
|
||||
* Gets the bean's <code>BeanDescriptor</code>s.
|
||||
*
|
||||
* @return BeanDescriptor describing the editable
|
||||
* properties of this bean. May return null if the
|
||||
* information should be obtained by automatic analysis.
|
||||
*/
|
||||
public BeanDescriptor getBeanDescriptor()
|
||||
{
|
||||
return getBdescriptor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bean's <code>PropertyDescriptor</code>s.
|
||||
*
|
||||
* @return An array of PropertyDescriptors describing the editable
|
||||
* properties supported by this bean. May return null if the
|
||||
* information should be obtained by automatic analysis.
|
||||
* If a property is indexed, then its entry in the result array will
|
||||
* belong to the IndexedPropertyDescriptor subclass of PropertyDescriptor.
|
||||
* A client of getPropertyDescriptors can use "instanceof" to check
|
||||
* if a given PropertyDescriptor is an IndexedPropertyDescriptor.
|
||||
*/
|
||||
public PropertyDescriptor[] getPropertyDescriptors()
|
||||
{
|
||||
return getPdescriptor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bean's <code>EventSetDescriptor</code>s.
|
||||
*
|
||||
* @return An array of EventSetDescriptors describing the kinds of
|
||||
* events fired by this bean. May return null if the information
|
||||
* should be obtained by automatic analysis.
|
||||
*/
|
||||
public EventSetDescriptor[] getEventSetDescriptors()
|
||||
{
|
||||
return getEdescriptor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bean's <code>MethodDescriptor</code>s.
|
||||
*
|
||||
* @return An array of MethodDescriptors describing the methods
|
||||
* implemented by this bean. May return null if the information
|
||||
* should be obtained by automatic analysis.
|
||||
*/
|
||||
public MethodDescriptor[] getMethodDescriptors()
|
||||
{
|
||||
return getMdescriptor();
|
||||
}
|
||||
|
||||
/**
|
||||
* A bean may have a "default" property that is the property that will
|
||||
* mostly commonly be initially chosen for update by human's who are
|
||||
* customizing the bean.
|
||||
*
|
||||
* @return Index of default property in the PropertyDescriptor array
|
||||
* returned by getPropertyDescriptors.
|
||||
* <P> Returns -1 if there is no default property.
|
||||
*/
|
||||
public int getDefaultPropertyIndex()
|
||||
{
|
||||
return defaultPropertyIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* A bean may have a "default" event that is the event that will
|
||||
* mostly commonly be used by human's when using the bean.
|
||||
*
|
||||
* @return Index of default event in the EventSetDescriptor array
|
||||
* returned by getEventSetDescriptors.
|
||||
* <P> Returns -1 if there is no default event.
|
||||
*/
|
||||
public int getDefaultEventIndex()
|
||||
{
|
||||
return defaultEventIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.fr3ts0n.pvs.gui;
|
||||
|
||||
import com.fr3ts0n.pvs.ProcessVar;
|
||||
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
|
||||
class PvDataFlavor extends DataFlavor
|
||||
{
|
||||
private static final String PV_MIME_TYPE = "application/processvar";
|
||||
|
||||
public PvDataFlavor()
|
||||
{
|
||||
super(ProcessVar.class, PV_MIME_TYPE);
|
||||
}
|
||||
|
||||
public PvDataFlavor(String arg0) throws ClassNotFoundException
|
||||
{
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
public PvDataFlavor(String arg0, String arg1)
|
||||
{
|
||||
super(arg0, arg1);
|
||||
}
|
||||
|
||||
public PvDataFlavor(String arg0, String arg1, ClassLoader arg2)
|
||||
throws ClassNotFoundException
|
||||
{
|
||||
super(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
}
|
||||
+255
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* (C) Copyright 2015 by fr3ts0n <erwin.scheuch-heilig@gmx.at>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.fr3ts0n.pvs.gui;
|
||||
|
||||
import com.fr3ts0n.pvs.ProcessVar;
|
||||
import com.fr3ts0n.pvs.PvChangeEvent;
|
||||
import com.fr3ts0n.pvs.PvChangeListener;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.beans.Customizer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.border.LineBorder;
|
||||
import javax.swing.text.JTextComponent;
|
||||
|
||||
/**
|
||||
* panel class to display / edit a parocess variable and all it's attributes
|
||||
*
|
||||
* @author $Author: erwin $
|
||||
*/
|
||||
public class PvDetailPanel extends JPanel
|
||||
implements ActionListener, PvChangeListener, Customizer
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 740664204205911504L;
|
||||
// field background colors
|
||||
private static final Color unchangedColor = Color.white;
|
||||
private static final Color changedColor = Color.lightGray;
|
||||
private static final Color labelColor = Color.lightGray;
|
||||
private static final LineBorder lineBorder = new LineBorder(Color.BLACK);
|
||||
private final HashMap<Object, JComponent> fields = new HashMap<Object, JComponent>();
|
||||
private ProcessVar dataSource = null;
|
||||
private boolean editable = false;
|
||||
|
||||
public PvDetailPanel()
|
||||
{
|
||||
setLayout(new GridBagLayout());
|
||||
setBackground(labelColor);
|
||||
setBorder(lineBorder);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* create a panel of detailed information on current process variable
|
||||
*/
|
||||
public PvDetailPanel(ProcessVar data)
|
||||
{
|
||||
this();
|
||||
setProcessVar(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* create a panel of detailed information on current process variable
|
||||
*/
|
||||
public PvDetailPanel(ProcessVar data, boolean allowEdit)
|
||||
{
|
||||
this();
|
||||
setEditable(allowEdit);
|
||||
setProcessVar(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* set the process var which is assigned to this editor panel
|
||||
* this creates all corresponding data fields
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private void setProcessVar(ProcessVar data)
|
||||
{
|
||||
if (dataSource == null || !dataSource.equals(data))
|
||||
{
|
||||
// remove all child components, if they have been set already
|
||||
if (dataSource != null && !dataSource.equals(data))
|
||||
{
|
||||
dataSource.removePvChangeListener(this);
|
||||
fields.clear();
|
||||
removeAll();
|
||||
}
|
||||
|
||||
// update data source variable
|
||||
dataSource = data;
|
||||
|
||||
// if data source is anything real ...
|
||||
if (data != null)
|
||||
{
|
||||
Object currKey;
|
||||
Object currVal;
|
||||
JLabel hdrCmp;
|
||||
JComponent dataCmp;
|
||||
|
||||
GridBagConstraints attr = new GridBagConstraints();
|
||||
|
||||
// ... fill content panel with data
|
||||
ArrayList keys = new ArrayList(data.keySet());
|
||||
// sort list alphabetically
|
||||
Collections.sort(keys);
|
||||
Iterator it = keys.iterator();
|
||||
|
||||
// loop through all attributes
|
||||
while (it.hasNext())
|
||||
{
|
||||
/* set default attributes */
|
||||
attr.gridwidth = 1;
|
||||
attr.gridheight = 1;
|
||||
attr.weightx = 0.0;
|
||||
attr.fill = GridBagConstraints.BOTH;
|
||||
|
||||
if ((currKey = it.next()) != null)
|
||||
{
|
||||
hdrCmp = new JLabel(currKey.toString());
|
||||
hdrCmp.setBackground(labelColor);
|
||||
hdrCmp.setBorder(lineBorder);
|
||||
|
||||
// setup data component based on it's value
|
||||
if ((currVal = data.get(currKey)) == null)
|
||||
{
|
||||
dataCmp = new JLabel();
|
||||
} else
|
||||
{
|
||||
if (currVal instanceof ProcessVar)
|
||||
{
|
||||
dataCmp = new PvDetailPanel((ProcessVar) currVal, editable);
|
||||
} else
|
||||
{
|
||||
dataCmp = new JTextField(data.get(currKey).toString());
|
||||
((JTextField) dataCmp).setEditable(editable);
|
||||
((JTextField) dataCmp).addActionListener(this);
|
||||
}
|
||||
}
|
||||
dataCmp.setName(currKey.toString());
|
||||
// add the components
|
||||
add(hdrCmp, attr);
|
||||
attr.gridwidth = GridBagConstraints.REMAINDER;
|
||||
attr.weightx = 1.0;
|
||||
add(dataCmp, attr);
|
||||
// add data component to Hashmap of fields
|
||||
fields.put(currKey, dataCmp);
|
||||
}
|
||||
}
|
||||
// add 'this' panel as PvChangeListener to Process variable
|
||||
data.addPvChangeListener(this, PvChangeEvent.PV_ADDED | PvChangeEvent.PV_MODIFIED);
|
||||
}
|
||||
validate();
|
||||
}
|
||||
}
|
||||
|
||||
/** Implementation of Customizer interface */
|
||||
public void setObject(Object bean)
|
||||
{
|
||||
setEditable(true);
|
||||
setProcessVar((ProcessVar) bean);
|
||||
}
|
||||
|
||||
/** return the process var which is assigned to this editor panel */
|
||||
public ProcessVar getProcessVar()
|
||||
{
|
||||
return (dataSource);
|
||||
}
|
||||
|
||||
/** return if the process this editor panel is editable */
|
||||
public boolean getEditable()
|
||||
{
|
||||
return (editable);
|
||||
}
|
||||
|
||||
/** set this editor panel to be non-/editable */
|
||||
private void setEditable(boolean newEditable)
|
||||
{
|
||||
editable = newEditable;
|
||||
}
|
||||
|
||||
/**
|
||||
* action handler for edit fields within panel
|
||||
* this handler also temporarily changes the color of the edit field to
|
||||
* visibly indicate the update action.
|
||||
*/
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
// find out which field sends the event
|
||||
JTextField edit = (JTextField) e.getSource();
|
||||
// update the corresponding process var
|
||||
dataSource.put(edit.getName(), edit.getText(), PvChangeEvent.PV_MANUAL_MOD);
|
||||
// indicate change by changing field's background color
|
||||
edit.setBackground(changedColor);
|
||||
Toolkit.getDefaultToolkit().beep();
|
||||
}
|
||||
|
||||
protected void finalize() throws Throwable
|
||||
{
|
||||
dataSource.removePvChangeListener(this);
|
||||
fields.clear();
|
||||
removeAll();
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
/**
|
||||
* handler for process variable changes
|
||||
* update dialog element from process variable
|
||||
*/
|
||||
public void pvChanged(PvChangeEvent event)
|
||||
{
|
||||
// only update panel if it is displayable
|
||||
if (isDisplayable())
|
||||
{
|
||||
Component edit = fields.get(event.getKey());
|
||||
Object value = event.getValue();
|
||||
// if we have found the corresponding editor field ...
|
||||
if (edit != null)
|
||||
{
|
||||
// set the value and background for it
|
||||
edit.setBackground(event.getType() == PvChangeEvent.PV_MANUAL_MOD ? changedColor : unchangedColor);
|
||||
if (edit instanceof JTextComponent)
|
||||
{
|
||||
((JTextComponent) edit).setText(value != null ? value.toString() : "");
|
||||
} else if (edit instanceof JLabel)
|
||||
{
|
||||
((JLabel) edit).setText(value != null ? value.toString() : "");
|
||||
} else if (edit instanceof PvDetailPanel)
|
||||
{
|
||||
((PvDetailPanel) edit).setProcessVar((ProcessVar) value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* (C) Copyright 2015 by fr3ts0n <erwin.scheuch-heilig@gmx.at>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.fr3ts0n.pvs.gui;
|
||||
|
||||
import com.fr3ts0n.pvs.ProcessVar;
|
||||
import com.fr3ts0n.pvs.PvList;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.ScrollPane;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
|
||||
import javax.swing.DropMode;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
public class PvExplorer extends JSplitPane implements TreeSelectionListener
|
||||
{
|
||||
/** unique serial version ID */
|
||||
private static final long serialVersionUID = 182596839340890403L;
|
||||
|
||||
/** root process variable for tree and initial table display */
|
||||
ProcessVar pvRoot;
|
||||
/** PV tree display */
|
||||
private final JTree pvTree;
|
||||
/** PV table display */
|
||||
private final PvTable pvTable;
|
||||
/** PV List as container for single process variables to be displayed in table */
|
||||
private final PvList tblList = new PvList();
|
||||
/** PV transfer handler to handle data transfers within explorer */
|
||||
private final PvTransferHandler xferHdlr = new PvTransferHandler();
|
||||
|
||||
public PvExplorer(ProcessVar pv)
|
||||
{
|
||||
setDividerSize(2);
|
||||
setPreferredSize(new Dimension(640, 480));
|
||||
|
||||
pvTree = new JTree(new PvTreeNode(pv));
|
||||
pvTree.getSelectionModel().addTreeSelectionListener(this);
|
||||
pvTree.setDragEnabled(true);
|
||||
pvTree.setDropMode(DropMode.ON_OR_INSERT);
|
||||
pvTree.setTransferHandler(xferHdlr);
|
||||
|
||||
pvTable = new PvTable(pv);
|
||||
pvTable.setDragEnabled(true);
|
||||
pvTable.setDropMode(DropMode.ON_OR_INSERT);
|
||||
pvTable.addMouseListener(tblMouseLstnr);
|
||||
pvTable.setTransferHandler(xferHdlr);
|
||||
|
||||
JScrollPane spPvTree = new JScrollPane(pvTree);
|
||||
add(spPvTree, JSplitPane.LEFT);
|
||||
JScrollPane spPvTable = new JScrollPane(pvTable);
|
||||
add(spPvTable, JSplitPane.RIGHT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void valueChanged(TreeSelectionEvent e)
|
||||
{
|
||||
TreePath selPath = e.getNewLeadSelectionPath();
|
||||
if (selPath == null)
|
||||
return;
|
||||
|
||||
ProcessVar pv = PvTreeNode.getPvFromTreePath(selPath);
|
||||
|
||||
if (pv instanceof PvList)
|
||||
{
|
||||
// if process var is a PV list itself then show it in table
|
||||
pvTable.setProcessVar(pv);
|
||||
} else
|
||||
{
|
||||
// ... otherwise create a list with PV as contained element
|
||||
tblList.clear();
|
||||
tblList.put(pv.getKeyValue(), pv);
|
||||
pvTable.setProcessVar(tblList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for mouse events on table side
|
||||
*/
|
||||
private final MouseListener tblMouseLstnr = new MouseListener()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
if (e.getClickCount() > 1)
|
||||
{
|
||||
// find the process var to selected row ...
|
||||
ProcessVar pv = pvTable.getPvModel().getElementAt(pvTable.getSelectedRow());
|
||||
// and show a detail panel about it ...
|
||||
if (pv != null)
|
||||
{
|
||||
PvDetailPanel panDetail = new PvDetailPanel(pv, true);
|
||||
ScrollPane panScr = new ScrollPane();
|
||||
panScr.setPreferredSize(new Dimension(640, 480));
|
||||
panScr.add(panDetail);
|
||||
JOptionPane.showMessageDialog(null, panScr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e)
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* (C) Copyright 2015 by fr3ts0n <erwin.scheuch-heilig@gmx.at>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.fr3ts0n.pvs.gui;
|
||||
|
||||
import com.fr3ts0n.pvs.ProcessVar;
|
||||
|
||||
import javax.swing.JTable;
|
||||
|
||||
/**
|
||||
* Table GUI object for process variables
|
||||
*
|
||||
* @author erwin
|
||||
*/
|
||||
public class PvTable extends JTable
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 6339359674123198139L;
|
||||
private ProcessVar pv;
|
||||
private PvTableModel pvModel = new PvTableModel();
|
||||
private final PvTableCellRenderer renderer = new PvTableCellRenderer();
|
||||
|
||||
/** Creates a new instance of PvTable */
|
||||
public PvTable()
|
||||
{
|
||||
setRowSelectionAllowed(true);
|
||||
setDefaultRenderer(Object.class, renderer);
|
||||
setModel(new javax.swing.table.DefaultTableModel(
|
||||
new Object[][]{
|
||||
{null, null, null, null},
|
||||
{null, null, null, null},
|
||||
{null, null, null, null},
|
||||
{null, null, null, null}},
|
||||
new String[]{
|
||||
"Title 1", "Title 2", "Title 3", "Title 4"
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of PvTable
|
||||
*
|
||||
* @param list The process var to display in table
|
||||
*/
|
||||
public PvTable(ProcessVar list)
|
||||
{
|
||||
setProcessVar(list);
|
||||
setRowSelectionAllowed(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* set the process var
|
||||
*
|
||||
* @param list The process var to display in table
|
||||
*/
|
||||
public void setProcessVar(ProcessVar list)
|
||||
{
|
||||
pv = list;
|
||||
pvModel.setProcessVar(pv);
|
||||
setModel(pvModel);
|
||||
}
|
||||
|
||||
public PvTableModel getPvModel()
|
||||
{
|
||||
return pvModel;
|
||||
}
|
||||
|
||||
public void setPvModel(PvTableModel pvModel)
|
||||
{
|
||||
this.pvModel = pvModel;
|
||||
}
|
||||
}
|
||||
+1059
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* (C) Copyright 2015 by fr3ts0n <erwin.scheuch-heilig@gmx.at>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.fr3ts0n.pvs.gui;
|
||||
|
||||
import java.awt.Component;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
|
||||
/**
|
||||
* Cell Renderer for PvTable component
|
||||
*
|
||||
* @author erwin
|
||||
*/
|
||||
public class PvTableCellRenderer extends JLabel
|
||||
implements TableCellRenderer
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -7686049090382566048L;
|
||||
private static final EmptyBorder brdr = new EmptyBorder(0, 5, 0, 5);
|
||||
|
||||
/** Creates a new instance of PvTableCellRenderer */
|
||||
public PvTableCellRenderer()
|
||||
{
|
||||
setOpaque(true);
|
||||
setBorder(brdr);
|
||||
}
|
||||
|
||||
/** render a single pv attribute based on location within table */
|
||||
public Component getTableCellRendererComponent(JTable table,
|
||||
Object value,
|
||||
boolean isSelected,
|
||||
boolean hasFocus,
|
||||
int row,
|
||||
int column)
|
||||
{
|
||||
setFont(table.getFont());
|
||||
setHorizontalAlignment(value instanceof Number ? RIGHT : LEFT);
|
||||
setText(String.valueOf(value));
|
||||
setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
|
||||
|
||||
return (this);
|
||||
}
|
||||
}
|
||||
+218
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* (C) Copyright 2015 by fr3ts0n <erwin.scheuch-heilig@gmx.at>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.fr3ts0n.pvs.gui;
|
||||
|
||||
import com.fr3ts0n.pvs.IndexedProcessVar;
|
||||
import com.fr3ts0n.pvs.ProcessVar;
|
||||
import com.fr3ts0n.pvs.PvChangeEvent;
|
||||
import com.fr3ts0n.pvs.PvChangeListener;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
|
||||
/**
|
||||
* Data Model to represent a ProcessVar within a Table object
|
||||
*
|
||||
* @author erwin
|
||||
*/
|
||||
public class PvTableModel extends AbstractTableModel
|
||||
implements PvChangeListener
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -6777148395276846388L;
|
||||
protected ProcessVar pv;
|
||||
protected IndexedProcessVar currRow;
|
||||
protected Object[] keys;
|
||||
private String[] colHeaders = {};
|
||||
|
||||
/** Creates a new instance of PvTableModel */
|
||||
public PvTableModel()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of PvTableModel
|
||||
*
|
||||
* @param pVar the process variable to represent
|
||||
*/
|
||||
public PvTableModel(ProcessVar pVar)
|
||||
{
|
||||
setProcessVar(pVar);
|
||||
}
|
||||
|
||||
/**
|
||||
* update th list of key items for correct location of coordinates
|
||||
*
|
||||
* @param pv Process variable
|
||||
*/
|
||||
private void updateKeys(ProcessVar pv)
|
||||
{
|
||||
keys = pv.keySet().toArray();
|
||||
Arrays.sort(keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* set the process variable to be represented
|
||||
*
|
||||
* @param pVar the process variable to represent
|
||||
*/
|
||||
public synchronized void setProcessVar(ProcessVar pVar)
|
||||
{
|
||||
// set the pv
|
||||
pv = pVar;
|
||||
updateKeys(pVar);
|
||||
if (keys.length > 0)
|
||||
{
|
||||
currRow = (IndexedProcessVar) pv.get(keys[0]);
|
||||
colHeaders = currRow.getFields();
|
||||
fireTableStructureChanged();
|
||||
}
|
||||
pv.addPvChangeListener(this, PvChangeEvent.PV_ALLEVENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* get number of table rows
|
||||
*
|
||||
* @return number of rows to show
|
||||
*/
|
||||
public int getRowCount()
|
||||
{
|
||||
return (keys != null ? keys.length : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* return number of columns
|
||||
*
|
||||
* @return number of columns
|
||||
*/
|
||||
public int getColumnCount()
|
||||
{
|
||||
return (colHeaders.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* get process var for row
|
||||
* @param rowIndex row index
|
||||
* @return process var
|
||||
*/
|
||||
public IndexedProcessVar getElementAt(int rowIndex)
|
||||
{
|
||||
if (rowIndex < getRowCount())
|
||||
currRow = (IndexedProcessVar) pv.get(keys[rowIndex]);
|
||||
|
||||
return currRow;
|
||||
}
|
||||
/**
|
||||
* get the value for table location (x,y)
|
||||
*
|
||||
* @param rowIndex row number
|
||||
* @param columnIndex column number
|
||||
* @return value for table location
|
||||
*/
|
||||
public Object getValueAt(int rowIndex, int columnIndex)
|
||||
{
|
||||
Object result = null;
|
||||
// if the pv is set ...
|
||||
if (pv != null)
|
||||
{
|
||||
// get the column value
|
||||
if((currRow = getElementAt(rowIndex)) != null)
|
||||
{
|
||||
result = currRow.get(columnIndex);
|
||||
}
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
* handle a process variable change
|
||||
*
|
||||
* @param event the change event to be handled
|
||||
*/
|
||||
public synchronized void pvChanged(PvChangeEvent event)
|
||||
{
|
||||
Object key;
|
||||
int rowId;
|
||||
try
|
||||
{
|
||||
if(event.isChildEvent())
|
||||
{
|
||||
key = String.valueOf(event.getValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
key = event.getKey();
|
||||
}
|
||||
rowId = key != null ? Arrays.binarySearch(keys, key) : 0;
|
||||
|
||||
switch (event.getType())
|
||||
{
|
||||
case PvChangeEvent.PV_CONFIRMED:
|
||||
case PvChangeEvent.PV_MODIFIED:
|
||||
case PvChangeEvent.PV_MANUAL_MOD:
|
||||
fireTableRowsUpdated(rowId, rowId);
|
||||
break;
|
||||
|
||||
case PvChangeEvent.PV_ADDED:
|
||||
if (pv.size() == 1)
|
||||
{
|
||||
setProcessVar(pv);
|
||||
} else
|
||||
{
|
||||
updateKeys(pv);
|
||||
fireTableRowsInserted(rowId, rowId);
|
||||
}
|
||||
break;
|
||||
|
||||
case PvChangeEvent.PV_DELETED:
|
||||
updateKeys(pv);
|
||||
fireTableRowsDeleted(rowId, rowId);
|
||||
break;
|
||||
|
||||
case PvChangeEvent.PV_CLEARED:
|
||||
if (keys.length > 0)
|
||||
{
|
||||
updateKeys(pv);
|
||||
}
|
||||
// w/o data there are NO columns available -> structure change
|
||||
fireTableStructureChanged();
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return column name of PID field
|
||||
*
|
||||
* @param column specified column number to get name for ...
|
||||
*/
|
||||
@Override
|
||||
public String getColumnName(int column)
|
||||
{
|
||||
return (colHeaders[column]);
|
||||
}
|
||||
}
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* (C) Copyright 2015 by fr3ts0n <erwin.scheuch-heilig@gmx.at>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.fr3ts0n.pvs.gui;
|
||||
|
||||
import com.fr3ts0n.pvs.ProcessVar;
|
||||
import com.fr3ts0n.pvs.PvChangeEvent;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.awt.datatransfer.UnsupportedFlavorException;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.TransferHandler;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
/**
|
||||
* @author se82wi
|
||||
*/
|
||||
public class PvTransferHandler extends TransferHandler
|
||||
{
|
||||
|
||||
/** Serial Version ID */
|
||||
private static final long serialVersionUID = -3156199604384589468L;
|
||||
private static final PvDataFlavor processVarFlavor = new PvDataFlavor();
|
||||
|
||||
public PvTransferHandler()
|
||||
{
|
||||
super("userObject");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see javax.swing.TransferHandler#getSourceActions(JComponent c)
|
||||
*/
|
||||
@Override
|
||||
public int getSourceActions(JComponent c)
|
||||
{
|
||||
return COPY_OR_MOVE;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see javax.swing.TransferHandler#createTransferable(javax.swing.JComponent)
|
||||
*/
|
||||
@Override
|
||||
protected Transferable createTransferable(JComponent c)
|
||||
{
|
||||
if (c instanceof JTree)
|
||||
{
|
||||
try
|
||||
{
|
||||
JTree tree = (JTree) c;
|
||||
DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getSelectionPath().getLastPathComponent();
|
||||
ProcessVar pv = (ProcessVar) node.getUserObject();
|
||||
return (Transferable) pv;
|
||||
} catch (ClassCastException ex)
|
||||
{
|
||||
ProcessVar.log.severe(this.toString() + ":" + ex.getMessage());
|
||||
}
|
||||
} else if (c instanceof PvTable)
|
||||
{
|
||||
PvTable tab = (PvTable) c;
|
||||
ProcessVar pv = tab.getPvModel().getElementAt(tab.getSelectedRow());
|
||||
return (Transferable) pv;
|
||||
}
|
||||
// anything else is handled by superclass
|
||||
return super.createTransferable(c);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see javax.swing.TransferHandler#exportDone(javax.swing.JComponent, java.awt.datatransfer.Transferable, int)
|
||||
*/
|
||||
@Override
|
||||
protected void exportDone(JComponent c, Transferable t, int action)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (action == MOVE)
|
||||
{
|
||||
ProcessVar pv = (ProcessVar) t.getTransferData(processVarFlavor);
|
||||
pv.firePvChanged(new PvChangeEvent(pv, pv.getKeyAttribute(), pv, PvChangeEvent.PV_ELIMINATED));
|
||||
}
|
||||
} catch (UnsupportedFlavorException e)
|
||||
{
|
||||
ProcessVar.log.severe(this.toString() + ":" + e.getMessage());
|
||||
} catch (IOException e)
|
||||
{
|
||||
ProcessVar.log.severe(this.toString() + ":" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see javax.swing.TransferHandler#importData(javax.swing.TransferHandler.TransferSupport)
|
||||
*/
|
||||
@Override
|
||||
public boolean importData(TransferSupport support)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (support.getComponent() instanceof JTree)
|
||||
{
|
||||
JTree tree = (JTree) support.getComponent();
|
||||
Point dropPoint = support.getDropLocation().getDropPoint();
|
||||
TreePath path = tree.getPathForLocation(dropPoint.x, dropPoint.y);
|
||||
Object node = path.getLastPathComponent();
|
||||
if (support.isDataFlavorSupported(processVarFlavor))
|
||||
{
|
||||
ProcessVar tVar = (ProcessVar) ((PvTreeNode) node).getUserObject();
|
||||
ProcessVar chldPv = (ProcessVar) support.getTransferable().getTransferData(processVarFlavor);
|
||||
|
||||
Object chldKey = chldPv.getKeyValue();
|
||||
tVar.put(chldKey, chldPv, PvChangeEvent.PV_ADDED);
|
||||
DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
|
||||
model.nodeStructureChanged((TreeNode) model.getRoot());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (UnsupportedFlavorException e)
|
||||
{
|
||||
ProcessVar.log.severe(this.toString() + ":" + e.getMessage());
|
||||
} catch (IOException e)
|
||||
{
|
||||
ProcessVar.log.severe(this.toString() + ":" + e.getMessage());
|
||||
}
|
||||
// anything else is handled by superclass
|
||||
return super.importData(support);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see javax.swing.TransferHandler#canImport(javax.swing.TransferHandler.TransferSupport)
|
||||
*/
|
||||
@Override
|
||||
public boolean canImport(TransferSupport support)
|
||||
{
|
||||
return support != null
|
||||
&& support.isDataFlavorSupported(processVarFlavor);
|
||||
}
|
||||
}
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* (C) Copyright 2015 by fr3ts0n <erwin.scheuch-heilig@gmx.at>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.fr3ts0n.pvs.gui;
|
||||
|
||||
import com.fr3ts0n.pvs.ProcessVar;
|
||||
import com.fr3ts0n.pvs.PvChangeEvent;
|
||||
import com.fr3ts0n.pvs.PvChangeListener;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
/**
|
||||
* @author se82wi
|
||||
* Tree node from a process variable
|
||||
*/
|
||||
public class PvTreeNode extends DefaultMutableTreeNode
|
||||
implements PvChangeListener
|
||||
{
|
||||
/**
|
||||
* ProcessVar tree node Renderer
|
||||
*/
|
||||
private static final long serialVersionUID = 8478304706986978587L;
|
||||
|
||||
public PvTreeNode()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public PvTreeNode(Object userObject)
|
||||
{
|
||||
super(userObject);
|
||||
setUserObject(userObject);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* javax.swing.tree.DefaultMutableTreeNode#setUserObject(java.lang.Object)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void setUserObject(Object userObject)
|
||||
{
|
||||
super.setUserObject(userObject);
|
||||
if (userObject instanceof ProcessVar)
|
||||
{
|
||||
Object currVal;
|
||||
ProcessVar pv = (ProcessVar) userObject;
|
||||
// loop through attributes
|
||||
Iterator<Object> it = pv.values().iterator();
|
||||
while (it.hasNext())
|
||||
{
|
||||
currVal = it.next();
|
||||
// if there is a child PV, then add it as a tree node
|
||||
if (currVal instanceof ProcessVar)
|
||||
add(new PvTreeNode(currVal));
|
||||
}
|
||||
pv.addPvChangeListener(this, PvChangeEvent.PV_ADDED
|
||||
| PvChangeEvent.PV_DELETED
|
||||
| PvChangeEvent.PV_CLEARED
|
||||
| PvChangeEvent.PV_ELIMINATED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get process variable from tree node
|
||||
*
|
||||
* @param path tree path to find object for
|
||||
* @return process variable, or null if no process variable found
|
||||
*/
|
||||
public static ProcessVar getPvFromTreePath(TreePath path)
|
||||
{
|
||||
PvTreeNode selNode = (PvTreeNode) path.getLastPathComponent();
|
||||
if (selNode == null)
|
||||
return null;
|
||||
|
||||
Object pvObj = selNode.getUserObject();
|
||||
if (!(pvObj instanceof ProcessVar))
|
||||
return null;
|
||||
|
||||
return (ProcessVar) pvObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find child node containing matching user Object
|
||||
*
|
||||
* @param userObject user object to match
|
||||
* @return matching child node, or
|
||||
* <pre>null</pre> if nothing has been found
|
||||
*/
|
||||
private PvTreeNode findChild(Object userObject)
|
||||
{
|
||||
PvTreeNode currNode;
|
||||
// search through children for matching user object
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterator<PvTreeNode> it = children.iterator();
|
||||
while (it.hasNext())
|
||||
{
|
||||
currNode = it.next();
|
||||
if (userObject == currNode.userObject)
|
||||
return currNode;
|
||||
}
|
||||
// haven't found it -> return NULL
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for PvChangeEvents
|
||||
*/
|
||||
@Override
|
||||
public synchronized void pvChanged(PvChangeEvent pvchangeevent)
|
||||
{
|
||||
Object currVal = pvchangeevent.getValue();
|
||||
if (!(currVal instanceof ProcessVar))
|
||||
return;
|
||||
|
||||
switch (pvchangeevent.getType())
|
||||
{
|
||||
case PvChangeEvent.PV_ADDED:
|
||||
add(new PvTreeNode(currVal));
|
||||
break;
|
||||
|
||||
case PvChangeEvent.PV_CLEARED:
|
||||
removeAllChildren();
|
||||
break;
|
||||
|
||||
case PvChangeEvent.PV_DELETED:
|
||||
PvTreeNode pvNode = findChild(currVal);
|
||||
if (pvNode != null)
|
||||
pvNode.removeFromParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<body>
|
||||
Process variable visualization classes
|
||||
</body>
|
||||
</html>
|
||||
+337
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
* (C) Copyright 2015 by fr3ts0n <erwin.scheuch-heilig@gmx.at>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.fr3ts0n.pvs.io;
|
||||
|
||||
import com.fr3ts0n.pvs.ProcessVar;
|
||||
import com.fr3ts0n.pvs.PvChangeEvent;
|
||||
import com.fr3ts0n.pvs.PvChangeListener;
|
||||
import com.fr3ts0n.pvs.PvList;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
/**
|
||||
* Content handler for ProcessVar XML-Streams
|
||||
*
|
||||
* @author $Author: erwin $
|
||||
*/
|
||||
public class PvXMLHandler
|
||||
extends DefaultHandler
|
||||
{
|
||||
|
||||
/** List of XML-Tags handled by this Handler */
|
||||
private static final String[] XML_TAGS =
|
||||
{
|
||||
PvXMLWriter.TAG_PVLIST,
|
||||
PvXMLWriter.TAG_PROCESSVAR,
|
||||
PvXMLWriter.TAG_PVATTRIBUTE
|
||||
};
|
||||
// numeric indices to above List
|
||||
/** ID of TAG for PV-List */
|
||||
static final int TAG_ID_PVLIST = 0;
|
||||
/** ID for Tag Processvar */
|
||||
private static final int TAG_ID_PROCESSVAR = 1;
|
||||
/** ID for tag Attribute */
|
||||
private static final int TAG_ID_PVATTRIBUTE = 2;
|
||||
/** Stack of recursive process variables */
|
||||
private final Stack<Object[]> pvStack = new Stack<Object[]>();
|
||||
/** The root Process variable to be parsed on */
|
||||
private com.fr3ts0n.pvs.PvList rootPv = new PvList();
|
||||
/** currently parsed process variable */
|
||||
private ProcessVar currPv = rootPv;
|
||||
/** currently parsed attribute */
|
||||
private Object currAttrib;
|
||||
/** currently parsed value for attribute */
|
||||
private Object currValue;
|
||||
/** list of process var change listeners */
|
||||
private final HashMap<PvChangeListener, Integer> PvChangeListeners = new HashMap<PvChangeListener, Integer>();
|
||||
/** the logger object */
|
||||
private static final Logger log = Logger.getLogger(PvXMLHandler.class.getPackage().getName());
|
||||
|
||||
/**
|
||||
* Creates a new instance of PvXMLContentHandler
|
||||
*
|
||||
* @throws org.xml.sax.SAXException Exception thrown at Instantiation of SAX-parser
|
||||
*/
|
||||
private PvXMLHandler()
|
||||
{
|
||||
rootPv.setKeyValue("root");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of PvXMLContentHandler
|
||||
*
|
||||
* @throws org.xml.sax.SAXException Exception thrown at Instantiation of SAX-parser
|
||||
*/
|
||||
private PvXMLHandler(PvList rootPv)
|
||||
{
|
||||
setRootPv(rootPv);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the numeric ID of XML-Tag
|
||||
*
|
||||
* @param tagName Name of XML-Tag
|
||||
* @return numeric ID for XML-Tag or -1 if nott found
|
||||
*/
|
||||
private int getTagID(String tagName)
|
||||
{
|
||||
int result = -1;
|
||||
for (int i = 0; i < XML_TAGS.length; i++)
|
||||
{
|
||||
if (XML_TAGS[i].equals(tagName))
|
||||
{
|
||||
result = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
/**
|
||||
* handle incoming Text
|
||||
*
|
||||
* @param ch incoming text
|
||||
* @param start start position
|
||||
* @param length length of text
|
||||
*/
|
||||
public void characters(char[] ch, int start, int length)
|
||||
{
|
||||
String currStr = String.copyValueOf(ch, start, length).trim();
|
||||
|
||||
// If this is a valid String, then handle it as the new data
|
||||
if (currStr.length() > 0)
|
||||
{
|
||||
log.fine("Chars:'" + currStr + "'");
|
||||
currValue = currStr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* handle start tag of a nw element
|
||||
*
|
||||
* @param namespaceURI element's namespace
|
||||
* @param localName element's local name
|
||||
* @param qName element's qualified name
|
||||
* @param atts attributes within element tag
|
||||
*/
|
||||
public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
|
||||
{
|
||||
if (log.isLoggable(Level.FINE))
|
||||
{
|
||||
StringBuffer sb = new StringBuffer("StartElement:" + qName + ":");
|
||||
for (int i = 0; i < atts.getLength(); i++)
|
||||
{
|
||||
sb.append(atts.getQName(i)).append("=").append(atts.getValue(i)).append(",");
|
||||
}
|
||||
log.fine(sb.toString());
|
||||
}
|
||||
|
||||
int tagID = getTagID(qName);
|
||||
try
|
||||
{
|
||||
switch (tagID)
|
||||
{
|
||||
case TAG_ID_PROCESSVAR:
|
||||
if (currPv != null)
|
||||
{
|
||||
pvStack.push(new Object[]{currPv, currAttrib});
|
||||
}
|
||||
currPv = (ProcessVar) Class.forName(atts.getValue(PvXMLWriter.ATTR_TYPE)).newInstance();
|
||||
currPv.setKeyValue(atts.getValue(PvXMLWriter.ATTR_KEY));
|
||||
break;
|
||||
|
||||
case TAG_ID_PVATTRIBUTE:
|
||||
currAttrib = atts.getValue(PvXMLWriter.ATTR_NAME);
|
||||
break;
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* handle end tag of element
|
||||
*
|
||||
* @param namespaceURI element's namespace
|
||||
* @param localName element's local name
|
||||
* @param qName element's qualified name
|
||||
*/
|
||||
public void endElement(String namespaceURI, String localName, String qName)
|
||||
{
|
||||
log.fine("EndElement:" + qName);
|
||||
int tagID = getTagID(qName);
|
||||
switch (tagID)
|
||||
{
|
||||
case TAG_ID_PROCESSVAR:
|
||||
log.fine("PV:" + currPv.toString());
|
||||
firePvChanged(new PvChangeEvent(this, currPv.getKeyValue(), currPv, PvChangeEvent.PV_CONFIRMED));
|
||||
currValue = currPv;
|
||||
// If we have PV's on stack, the new PV is a recursive attribute
|
||||
if (!pvStack.empty())
|
||||
{
|
||||
Object[] stackElems = pvStack.pop();
|
||||
currPv = (ProcessVar) stackElems[0];
|
||||
currAttrib = stackElems[1];
|
||||
} else
|
||||
{
|
||||
log.severe("NO more PV's on Stack");
|
||||
}
|
||||
if (currPv == rootPv)
|
||||
{
|
||||
currAttrib = ((ProcessVar) currValue).getKeyValue();
|
||||
}
|
||||
|
||||
currPv.put(currAttrib, currValue);
|
||||
break;
|
||||
|
||||
case TAG_ID_PVATTRIBUTE:
|
||||
// if currently parsed PV is null, then we just finished a recursive one
|
||||
if (currPv != null)
|
||||
{
|
||||
// This is a plain attribute
|
||||
currPv.put(currAttrib, currValue);
|
||||
}
|
||||
currValue = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handling for list of PvChangeListeners
|
||||
*/
|
||||
/**
|
||||
* remove listener for Pv changes
|
||||
*
|
||||
* @param l Listener to be removed
|
||||
*/
|
||||
public synchronized void removePvChangeListener(PvChangeListener l)
|
||||
{
|
||||
log.fine("-PvListener:" + String.valueOf(this) + "->" + String.valueOf(l));
|
||||
|
||||
PvChangeListeners.remove(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* add listener for Pv changes with specified change events
|
||||
*
|
||||
* @param l Listener to be added
|
||||
* @param eventMask events (Bitmask) which this listener wants to listen on
|
||||
*/
|
||||
private synchronized void addPvChangeListener(PvChangeListener l, int eventMask)
|
||||
{
|
||||
Object oldListener = PvChangeListeners.get(l);
|
||||
PvChangeListeners.put(l, Integer.valueOf(eventMask));
|
||||
|
||||
if (oldListener == null)
|
||||
{
|
||||
log.fine("+PvListener:" + String.valueOf(this) + "->" + String.valueOf(l));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* add listener for Pv changes
|
||||
*
|
||||
* @param l Listener to be added
|
||||
*/
|
||||
public void addPvChangeListener(PvChangeListener l)
|
||||
{
|
||||
addPvChangeListener(l, PvChangeEvent.PV_ALLEVENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* fire a Pv Change event
|
||||
*
|
||||
* @param e Event for Process variable change
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
private void firePvChanged(PvChangeEvent e)
|
||||
{
|
||||
log.fine("PvChange:" + e.toString());
|
||||
|
||||
Integer evtMask;
|
||||
Map.Entry curr;
|
||||
|
||||
Set entries = PvChangeListeners.entrySet();
|
||||
Iterator it = entries.iterator();
|
||||
|
||||
while (it.hasNext())
|
||||
{
|
||||
curr = (Map.Entry) it.next();
|
||||
|
||||
if (curr.getKey() != null && curr.getKey() != this)
|
||||
{
|
||||
// check if listener wants to be notified by this event
|
||||
evtMask = (Integer) curr.getValue();
|
||||
|
||||
if ((evtMask.intValue() & e.getType()) != 0)
|
||||
{
|
||||
log.fine("Notify:" + curr);
|
||||
((PvChangeListener) curr.getKey()).pvChanged(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PvList getRootPv()
|
||||
{
|
||||
return rootPv;
|
||||
}
|
||||
|
||||
private void setRootPv(PvList mainPV)
|
||||
{
|
||||
this.rootPv = mainPV;
|
||||
this.currPv = mainPV;
|
||||
}
|
||||
|
||||
/**
|
||||
* main routine for testing class implementation
|
||||
*
|
||||
* @param argv command line arguments
|
||||
*/
|
||||
public static void main(String[] argv)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create a new Parser
|
||||
PvXMLHandler handler = new PvXMLHandler();
|
||||
// Use the default (non-validating) parser
|
||||
SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||
// Parse the input
|
||||
SAXParser saxParser = factory.newSAXParser();
|
||||
saxParser.parse(new FileInputStream(argv[0]), handler);
|
||||
} catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
+241
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* (C) Copyright 2015 by fr3ts0n <erwin.scheuch-heilig@gmx.at>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.fr3ts0n.pvs.io;
|
||||
|
||||
|
||||
import com.fr3ts0n.pvs.ProcessVar;
|
||||
import com.fr3ts0n.pvs.PvChangeEvent;
|
||||
import com.fr3ts0n.pvs.PvChangeListener;
|
||||
|
||||
import org.xml.sax.helpers.AttributesImpl;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.sax.SAXTransformerFactory;
|
||||
import javax.xml.transform.sax.TransformerHandler;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
/**
|
||||
* XML writer to write Process Variables into an XML-Stream
|
||||
*
|
||||
* @author $Author: erwin $
|
||||
*/
|
||||
public class PvXMLWriter
|
||||
implements PvChangeListener
|
||||
{
|
||||
|
||||
private Result xFormResult;
|
||||
private SAXTransformerFactory factory;
|
||||
private TransformerHandler handler;
|
||||
private Transformer serializer;
|
||||
private boolean documentStarted = false;
|
||||
/** XML Tag-Names */
|
||||
public static final String TAG_PVLIST = "PV-LIST";
|
||||
public static final String TAG_PROCESSVAR = "PV";
|
||||
public static final String TAG_PVATTRIBUTE = "AT";
|
||||
/** XML attribute values */
|
||||
public static final String ATTR_TYPE = "type";
|
||||
public static final String ATTR_KEY = "key";
|
||||
public static final String ATTR_NAME = "name";
|
||||
|
||||
/**
|
||||
* Creates a new instance of PvXMLWriter
|
||||
*/
|
||||
private PvXMLWriter()
|
||||
{
|
||||
try
|
||||
{
|
||||
factory = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
|
||||
handler = factory.newTransformerHandler();
|
||||
serializer = handler.getTransformer();
|
||||
serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
|
||||
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
serializer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
|
||||
} catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of PvXMLWriter
|
||||
*/
|
||||
public PvXMLWriter(OutputStream oStream)
|
||||
{
|
||||
this();
|
||||
setOutputStream(oStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* set a stream writer for the handler
|
||||
*/
|
||||
private void setOutputStream(OutputStream oStream)
|
||||
{
|
||||
try
|
||||
{
|
||||
xFormResult = new StreamResult(oStream);
|
||||
handler.setResult(xFormResult);
|
||||
} catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* initialize document writing
|
||||
*/
|
||||
private void startDocument()
|
||||
{
|
||||
AttributesImpl attrs = new AttributesImpl();
|
||||
try
|
||||
{
|
||||
handler.startDocument();
|
||||
handler.startElement("", TAG_PVLIST, TAG_PVLIST, attrs);
|
||||
documentStarted = true;
|
||||
} catch (Throwable e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* finalize Document writing
|
||||
*/
|
||||
private void endDocument()
|
||||
{
|
||||
try
|
||||
{
|
||||
handler.endElement("", TAG_PVLIST, TAG_PVLIST);
|
||||
handler.endDocument();
|
||||
documentStarted = false;
|
||||
} catch (Throwable e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* write a process variable as XML to an output stream
|
||||
*
|
||||
* @param pv processVar to write
|
||||
* @param recursiveDepth Depth of recursive PV writing
|
||||
* @param completeDoc if TRUE, XML document will be initialized before,
|
||||
* and finalized after writing this PV
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
private void writePv(ProcessVar pv, int recursiveDepth, boolean completeDoc)
|
||||
{
|
||||
Object currKey;
|
||||
Object currVal;
|
||||
|
||||
// Initialize XML-Document
|
||||
if (completeDoc || !documentStarted)
|
||||
{
|
||||
startDocument();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
AttributesImpl attrs = new AttributesImpl();
|
||||
attrs.addAttribute("", ATTR_TYPE, ATTR_TYPE, "CDATA", pv.getClass().getName());
|
||||
attrs.addAttribute("", ATTR_KEY, ATTR_KEY, "CDATA", String.valueOf(pv.getKeyValue()));
|
||||
handler.startElement("", TAG_PROCESSVAR, TAG_PROCESSVAR, attrs);
|
||||
|
||||
if (recursiveDepth > 0)// Loop through all PV-Attributes
|
||||
{
|
||||
Iterator it = pv.keySet().iterator();
|
||||
while (it.hasNext())
|
||||
{
|
||||
currKey = it.next();
|
||||
currVal = pv.get(currKey);
|
||||
|
||||
attrs.clear();
|
||||
attrs.addAttribute("", ATTR_NAME, ATTR_NAME, "CDADTA", currKey.toString());
|
||||
handler.startElement("", TAG_PVATTRIBUTE, TAG_PVATTRIBUTE, attrs);
|
||||
|
||||
if (currVal != null)
|
||||
{
|
||||
// If current value is a PV itself ...
|
||||
if (currVal instanceof ProcessVar)
|
||||
{
|
||||
// write recursively
|
||||
writePv((ProcessVar) currVal, recursiveDepth - 1, false);
|
||||
} else
|
||||
{
|
||||
// Otherwise write PV-Data as attribute
|
||||
String currStr = currVal.toString();
|
||||
handler.characters(currStr.toCharArray(), 0, currStr.length());
|
||||
}
|
||||
}
|
||||
// finish attribute XML-element
|
||||
handler.endElement("", TAG_PVATTRIBUTE, TAG_PVATTRIBUTE);
|
||||
}
|
||||
}
|
||||
// finish PV XNL-element
|
||||
handler.endElement("", TAG_PROCESSVAR, TAG_PROCESSVAR);
|
||||
} catch (Throwable e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// Finalize XML document
|
||||
if (completeDoc)
|
||||
{
|
||||
endDocument();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* write a process variable as XML to an output stream
|
||||
*
|
||||
* @param pv processVar to write
|
||||
* @param recursiveDepth Depth of recursive PV writing
|
||||
*/
|
||||
public void writePv(ProcessVar pv, int recursiveDepth)
|
||||
{
|
||||
writePv(pv, recursiveDepth, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard writing of PV
|
||||
* (uses recursive depth=100, NON complete Doc
|
||||
*
|
||||
* @param pv processVar to write
|
||||
*/
|
||||
private void writePv(ProcessVar pv)
|
||||
{
|
||||
writePv(pv, 100, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of PvChangeListener
|
||||
*/
|
||||
public void pvChanged(PvChangeEvent event)
|
||||
{
|
||||
// Test für XML-Ausgabe
|
||||
if (event.getValue() instanceof ProcessVar)
|
||||
{
|
||||
writePv((ProcessVar) event.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<body>
|
||||
Input / Output and serialisation for Process variables
|
||||
</body>
|
||||
</html>
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<body>
|
||||
Process variables and PV-related stuff
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user