package agg.attribute.gui.impl;
import javax.swing.JOptionPane;
import javax.swing.table.AbstractTableModel;
//import javax.swing.table.TableCellEditor;
import agg.attribute.AttrConditionTuple;
import agg.attribute.AttrEvent;
import agg.attribute.AttrInstance;
import agg.attribute.AttrInstanceMember;
import agg.attribute.AttrMember;
import agg.attribute.AttrTuple;
import agg.attribute.AttrType;
import agg.attribute.AttrTypeMember;
import agg.attribute.AttrVariableMember;
import agg.attribute.gui.AttrTupleEditor;
import agg.attribute.handler.AttrHandler;
import agg.attribute.handler.HandlerExpr;
import agg.attribute.impl.AttrSession;
import agg.attribute.impl.ValueMember;
import agg.attribute.impl.DeclTuple;
import agg.attribute.impl.DeclMember;
import agg.attribute.impl.VerboseControl;
/**
* Table model for tuple editors. The following behavior can be customized by
* method calls: which columns to display, their order, their titles, classes of
* their content objects and if their objects are editable. When more specific
* customization is needed, this class can be extended.
*
* @version $Id: TupleTableModel.java,v 1.22 2010/11/28 22:08:46 olga Exp $
* @author $Author: olga $
*/
public class TupleTableModel extends AbstractTableModel implements
/*TableCellEditor, */TupleTableModelConstants {
/**
*
*/
private static final long serialVersionUID = 2201742847657275100L;
// Property keys for internal array access. Must be [0,1,2,...]
protected static final int COLUMN_INDEX = 0;
protected static final int COLUMN_TITLE = 1;
protected static final int COLUMN_CLASS = 2;
protected static final int COLUMN_EDITABLE = 3;
protected static final int N_COLUMN_PROPERTIES = 4;
/**
* Decides if more rows can be interactively added to the tuple, by
* displaying an extra row at the table bottom.
*/
protected boolean isExtensible = false;
/** Columns to display and their order. */
protected int columnArray[] = { NAME, EXPR };
/** Properties of each column with respect to the table. */
protected Object columnData[][] = new Object[N_TUPLE_KEYS][N_COLUMN_PROPERTIES];
/**
* Owning editor, serves e.g. for accessing of the edited tuple, the view
* setting or, the EditorManager when selecting a handler editor.
*/
protected AttrTupleEditor editor = null;
/** Temporary trick. Later, the editor manager will be asked each time. */
protected AttrHandler defaultHandler = null;
protected int currentColumn;
protected boolean valueChanged;
/** Constructing with the owning editor. */
public TupleTableModel(AttrTupleEditor editor) {
super();
this.editor = editor;
String handlerName = agg.attribute.handler.impl.javaExpr.JexHandler
.getLabelName();
this.defaultHandler = editor.getAttrManager().getHandler(handlerName);
initColumnProperties();
}
// Public methods for customizing the table model.
/** Changing the table layout. */
public void setColumnArray(int keys[]) {
if (keys == null)
this.columnArray = new int[0];
else
this.columnArray = keys;
// Making all columns invisible.
for (int i = 0; i < N_TUPLE_KEYS; i++) {
this.columnData[i][COLUMN_INDEX] = new Integer(-1);
}
// Assigning column numbers to wanted columns.
for (int i = 0; i < this.columnArray.length; i++) {
this.columnData[this.columnArray[i]][COLUMN_INDEX] = new Integer(i);
}
}
/**
* Setting if more rows can be interactively added to the tuple, by
* displaying an extra row at the table bottom.
*/
public void setExtensible(boolean b) {
this.isExtensible = b;
}
/**
* Tests if more rows can be interactively added to the tuple, by displaying
* an extra row at the table bottom.
*/
public boolean isExtensible() {
return this.isExtensible;
}
/** Changing a column title. */
public void setColumnTitle(int key, String title) {
setColumnProperty(key, COLUMN_TITLE, title);
}
/** Changing a column class. */
public void setColumnClass(int key, Class<?> clazz) {
setColumnProperty(key, COLUMN_CLASS, clazz);
}
/** Setting if a field at column is editable. */
public void setColumnEditable(int key, boolean b) {
setColumnProperty(key, COLUMN_EDITABLE, new Boolean(b));
}
/**
* Returns the member of 'tuple' at the specified row. Used internally and
* by the editor that uses this table model.
*/
public AttrMember getMember(AttrTuple tuple, int row) {
return tuple.getMemberAt(this.editor.getViewSetting(), row);
}
/** Converting column index to item key. */
public final int getItemKeyAt(int column) {
return this.columnArray[column];
}
/** Converting item key to column index. */
public final int getColumnAtKey(int key) {
return ((Integer) this.columnData[key][COLUMN_INDEX]).intValue();
}
/**
* TupleEditor's AttrObserver interface implementation. notifies the table
* of the change. The default implementation is simply updating the whole
* table. For optimizing consider the data in the delivered event.
*/
public void attributeChanged(AttrEvent event) {
if (event == null)
this.valueChanged = false;
else {
// System.out.println("TupleTableModel.attributeChanged: at column:
// "+currentColumn);
this.fireTableDataChanged();
}
}
//
// Internal methods.
/** Setting a column property. */
protected void setColumnProperty(int key, int propertyKey, Object property) {
this.columnData[key][propertyKey] = property;
}
/** Returns a column property. */
protected Object getColumnProperty(int key, int propertyKey) {
return this.columnData[key][propertyKey];
}
/**
* Returns the number of rows. If this is a model for an extendable table,
* makes the table one row higher than the number of its members. The last
* row is for adding of a new member. Otherwise returns the exact number of
* tuple members.
*/
public int getRowCount() {
AttrTuple tuple = this.editor.getTuple();
if (tuple == null)
return 0;
int nMembers = tuple.getNumberOfEntries(this.editor.getViewSetting());
if (isExtensible())
nMembers++;
// System.out.println("TupleTableModel.getRowCount: "+ nMembers);
return nMembers;
}
// Generic methods
/** Default initialization, overwritten by calls to setColumn...()-methods. */
protected void initColumnProperties() {
Class<?> stringClass = "".getClass();
Class<?> booleanClass = Boolean.TRUE.getClass();
setColumnTitle(UNKNOWN, "???");
setColumnClass(UNKNOWN, null);
setColumnEditable(UNKNOWN, false);
setColumnTitle(HANDLER, "Handler");
setColumnClass(HANDLER, stringClass);
setColumnEditable(HANDLER, false);
setColumnTitle(TYPE, "Type");
setColumnClass(TYPE, stringClass);
setColumnEditable(TYPE, true);
setColumnTitle(NAME, "Name");
setColumnClass(NAME, stringClass);
setColumnEditable(NAME, true);
setColumnTitle(EXPR, "Expression");
setColumnClass(EXPR, stringClass);
setColumnEditable(EXPR, true);
setColumnTitle(YIELDS, "Yields");
setColumnClass(YIELDS, stringClass);
setColumnEditable(YIELDS, false);
setColumnTitle(CORRECTNESS, "OK");
setColumnClass(CORRECTNESS, booleanClass);
setColumnEditable(CORRECTNESS, false);
setColumnTitle(IS_INPUT_PARAMETER, "In");
setColumnClass(IS_INPUT_PARAMETER, booleanClass);
setColumnEditable(IS_INPUT_PARAMETER, true);
setColumnTitle(IS_OUTPUT_PARAMETER, "Out");
setColumnClass(IS_OUTPUT_PARAMETER, booleanClass);
setColumnEditable(IS_OUTPUT_PARAMETER, true);
setColumnTitle(VISIBILITY, "Shown");
setColumnClass(VISIBILITY, booleanClass);
setColumnEditable(VISIBILITY, true);
}
/** Returns the item at 'key' of 'member'. */
protected Object getItem(AttrMember member, int key, AttrTuple tuple,
int row) {
// AttrInstanceMember m = (AttrInstanceMember) member;
if (member instanceof AttrTypeMember) {
return getItemOfAttrTypeMember(member, key, tuple, row);
} else if (member instanceof AttrInstanceMember) {
AttrInstanceMember m = (AttrInstanceMember) member;
switch (key) {
case HANDLER:
return m.getDeclaration().getHandler().getName();
case TYPE:
return m.getDeclaration().getTypeName();
case NAME:
return m.getDeclaration().getName();
case VISIBILITY:
return new Boolean(this.editor.getViewSetting()
.isVisible(tuple, row));
case EXPR:
return m.getExprAsText();
case CORRECTNESS:
return new Boolean(m.isValid() && m.getDeclaration().isValid());
case YIELDS:
return new Boolean(m.isValid() && m.getDeclaration().isValid());
case IS_INPUT_PARAMETER:
return new Boolean(((AttrVariableMember) m).isInputParameter());
case IS_OUTPUT_PARAMETER:
return new Boolean(((AttrVariableMember) m).isOutputParameter());
default:
return null;
}
} else
return null;
}
protected Object getItemOfAttrTypeMember(AttrMember member, int key,
AttrTuple tuple, int row) {
if (member instanceof AttrTypeMember) {
AttrTypeMember m = (AttrTypeMember) member;
switch (key) {
case HANDLER:
return m.getHandler().getName();
case TYPE:
return m.getTypeName();
case NAME:
return m.getName();
case VISIBILITY:
return new Boolean(this.editor.getViewSetting()
.isVisible(tuple, row));
case EXPR:
case CORRECTNESS:
case YIELDS:
case IS_INPUT_PARAMETER:
case IS_OUTPUT_PARAMETER:
default:
return null;
}
}
return null;
}
/** Returns the item at 'key' of the new bottom row. */
protected Object getItemOfNewRow(int key, AttrTuple tuple, int row) {
switch (key) {
// case HANDLER: return defaultHandler.getName();
default:
return null;
}
}
/** Modifies the item at 'key' of 'member'. */
protected void setItem(Object aValue, AttrMember member, int key,
AttrTuple tuple, int row) {
// System.out.println("TupleTableModel.setItem ");
// AttrInstanceMember m = (AttrInstanceMember) member;
if (member instanceof AttrTypeMember) {
setItemOfAttrTypeMember(aValue, member, key, tuple, row);
} else if (member instanceof AttrInstanceMember) {
AttrInstanceMember m = (AttrInstanceMember) member;
switch (key) {
case HANDLER:
AttrSession.stdoutPrintln(VerboseControl.logTrace, "Handler");
m.getDeclaration().setHandler((AttrHandler) aValue);
break;
case TYPE:
AttrSession.stdoutPrintln(VerboseControl.logTrace, "Type");
if (!"".equals((String) aValue))
m.getDeclaration().setType((String) aValue);
break;
case NAME:
AttrSession.stdoutPrintln(VerboseControl.logTrace, "Name");
if (!"".equals((String) aValue)) {
if (((DeclTuple) ((DeclMember) m.getDeclaration())
.getHoldingTuple()).isClassName((String) aValue))
m.getDeclaration().setName("");
else if (m.getDeclaration().getHoldingTuple().getMemberAt((String) aValue) == null)
m.getDeclaration().setName((String) aValue);
}
break;
case VISIBILITY:
AttrSession
.stdoutPrintln(VerboseControl.logTrace, "Visibility");
this.editor.getViewSetting().setVisibleAt(tuple,
((Boolean) aValue).booleanValue(), row);
break;
case EXPR:
// set expr iff the type and the name of the member are valid
if (m.getDeclaration().isValid()) {
AttrSession.stdoutPrintln(VerboseControl.logTrace, "Expr");
HandlerExpr oldexpr = m.getExpr();
((ValueMember) m).checkValidity(oldexpr);
String olderrorMsg = ((ValueMember) m).getErrorMsg();
String newText = (String) aValue;
if (newText.equals("")) {
m.setExprAsText(newText);
} else if (((DeclTuple) ((DeclMember) m.getDeclaration())
.getHoldingTuple()).isClassName(newText)) {
m.setExprAsText("");
} else if (oldexpr == null
|| !newText.equals(oldexpr.toString())) {
try {
// check if aValue = $package.class$.static_method
// or aValue = package.class.static_method
// and cut to class.static_method
// newText = AttrTupleManager.getDefaultManager().getStaticMethodCall((String) aValue);
newText = this.getStaticMethodCall((String) aValue);
HandlerExpr expression = ((ValueMember) m).getHandler()
.newHandlerExpr(((ValueMember) m).getDeclaration()
.getType(), newText); // (String)aValue);
((ValueMember) m).checkValidity(expression);
String errorMsg = ((ValueMember) m).getErrorMsg();
if (m.isValid()) {
m.setExprAsText(newText);
}
else if (oldexpr != null && olderrorMsg.length() == 0) {
m.setExprAsText(oldexpr.toString());
}
else if (errorMsg.length() > 0){
JOptionPane.showMessageDialog(null,
errorMsg,
" Attribute Parser ", JOptionPane.ERROR_MESSAGE);
}
} catch (agg.attribute.handler.AttrHandlerException ex) {
// System.out.println(ex.getLocalizedMessage());
}
}
}
break;
case IS_INPUT_PARAMETER:
AttrSession.stdoutPrintln(VerboseControl.logTrace,
"Is_Input_Parameter");
((AttrVariableMember) m).setInputParameter(((Boolean) aValue)
.booleanValue());
break;
case IS_OUTPUT_PARAMETER:
AttrSession.stdoutPrintln(VerboseControl.logTrace,
"Is_Out_Parameter");
((AttrVariableMember) m).setOutputParameter(((Boolean) aValue)
.booleanValue());
break;
default:
;
}
AttrSession.logPrintln(VerboseControl.logTrace,
"TupleTableModel:\n<-setItem");
}
}
private void setItemOfAttrTypeMember(Object aValue, AttrMember member,
int key, AttrTuple tuple, int row) {
if (member instanceof AttrTypeMember) {
AttrTypeMember m = (AttrTypeMember) member;
switch (key) {
case HANDLER:
AttrSession.stdoutPrintln(VerboseControl.logTrace, "Handler");
m.setHandler((AttrHandler) aValue);
break;
case TYPE:
AttrSession.stdoutPrintln(VerboseControl.logTrace, "Type");
m.setType((String) aValue);
break;
case NAME:
AttrSession.stdoutPrintln(VerboseControl.logTrace, "Name");
m.setName((String) aValue);
break;
case EXPR:
case CORRECTNESS:
case YIELDS:
case IS_INPUT_PARAMETER:
case IS_OUTPUT_PARAMETER:
default:
;
}
AttrSession.logPrintln(VerboseControl.logTrace,
"TupleTableModel:\n<-setTypeItem");
}
}
// check the form: $package.class$.static_method
private String getStaticMethodCall(String aValue) {
if (aValue.indexOf("$") == 0) {
int ind = aValue.substring(1).indexOf("$");
if (ind > 0) {
String clstr = aValue.substring(1, ind + 1);
try {
Class.forName(clstr);
String tst = clstr.substring(clstr.indexOf(".") + 1);
while (tst.indexOf(".") != -1) {
clstr = tst.concat("");
tst = clstr.substring(clstr.indexOf(".") + 1);
}
clstr = tst.concat("");
String result = clstr + aValue.substring(ind + 2);
return result;
} catch (ClassNotFoundException ex) {
System.out.println("TupleTableModel: ClassNotFoundException: "+ex.getMessage());
}
}
} else {
try {
if (aValue.indexOf(".") >= 0) {
String clstr = aValue.substring(0, aValue.indexOf("."));
Class.forName(clstr);
return aValue;
}
} catch (ClassNotFoundException cex) {
// System.out.println(cex.getMessage());
String tst = aValue;
String pack = null;
String tmp = "";
while (tst.indexOf(".") != -1) {
String next = tst.substring(0, tst.indexOf("."));
Package p = Package.getPackage(tmp + next);
if (p != null) {
pack = p.getName();
tmp = p.getName();
} else {
tmp = tmp + next + ".";
}
tst = tst.substring(tst.indexOf(".") + 1, tst.length());
}
if (pack != null) {
String result = aValue.replaceFirst(pack + ".", "");
String clstr = result.substring(0, result.indexOf("."));
try {
Class.forName(pack + "." + clstr);
return result;
} catch (ClassNotFoundException ex) {
System.out.println("TupleTableModel: ClassNotFoundException: "+ex.getMessage());
}
}
}
}
return aValue;
}
/**
* Modifies the new bottom row. Involves adding a new member to 'tuple'.
*/
protected void setItemOfNewRow(Object aValue, int key, AttrTuple tuple,
int row) {
// System.out.println(
// "TupleTableModel:\n->setItemOfNewRow\nnumber of entries: "
// + tuple.getNumberOfEntries());
if (tuple instanceof AttrConditionTuple) {
// System.out.println("TupleTableModel.setItemOfNewRow ::
// addCondition: "+(String) aValue);
((AttrConditionTuple) tuple).addCondition((String) aValue);
return;
}
if (tuple instanceof AttrInstance) {
AttrTypeMember typeMember = ((AttrInstance) tuple).getType()
.addMember();
// addMember fuegt auf Instanzebene sofort einen Eintrag hinzu.
// nach der Deklarierung durch addMember kann sofort mit dem neuen
// Member gearbeitet
// werden.
typeMember.setHandler(this.defaultHandler);
int lastIndex = tuple.getNumberOfEntries() - 1;
AttrInstanceMember m = (AttrInstanceMember) tuple
.getMemberAt(lastIndex);
setItem(aValue, m, key, tuple, row);
AttrSession.logPrintln(VerboseControl.logTrace,
"TupleTableModel:\n<-setItemOfNewRow");
}
else if (tuple instanceof AttrType) {
AttrTypeMember typeMember = ((AttrType) tuple).addMember();
typeMember.setHandler(this.defaultHandler);
int lastIndex = tuple.getNumberOfEntries() - 1;
AttrTypeMember m = (AttrTypeMember) tuple.getMemberAt(lastIndex);
setItem(aValue, m, key, tuple, row);
AttrSession.logPrintln(VerboseControl.logTrace,
"TupleTableModel:\n<-setItemOfNewRow");
}
}
/** Returns the header column label for the specified key. */
protected String getItemLabel(int key) {
String label = (String) getColumnProperty(key, COLUMN_TITLE);
// AttrSession.logPrintln("getItemLabel("+key+")="+label);
return label;
}
/** Returns the class for an item key. */
protected Class<?> getItemClass(int key) {
Class<?> c = (Class<?>) getColumnProperty(key, COLUMN_CLASS);
// AttrSession.logPrintln("getItemClass("+key+")="+c);
return c;
}
/**
* Tests if the item at 'key' of the specified member is editable. Default
* implementation looks only at the key, ignoring 'member'. When needed,
* this behaviour can be overridden.
*/
protected boolean isItemEditable(AttrMember member, int key) {
return ((Boolean) getColumnProperty(key, COLUMN_EDITABLE))
.booleanValue();
}
/**
* Tests if the item at 'key' in the new bottom row is editable. Default
* implementation: same as other rows.
*/
protected boolean isNewRowEditable(int key) {
return ((Boolean) getColumnProperty(key, COLUMN_EDITABLE))
.booleanValue();
}
// TableModel interface implementation: dispatching to my specific
// methods.
/** TableModel interface implementation. */
public final int getColumnCount() {
return this.columnArray.length;
}
/** TableModel interface implementation: dispatching to my specific methods. */
public final Object getValueAt(int row, int column) {
AttrTuple tuple = this.editor.getTuple();
if (tuple == null)
return null;
else if (row >= tuple.getNumberOfEntries())
return getItemOfNewRow(getItemKeyAt(column), tuple, row);
else
return getItem(getMember(tuple, row), getItemKeyAt(column), tuple,
row);
}
/** TableModel interface implementation: dispatching to my specific methods. */
public final String getColumnName(int column) {
return getItemLabel(getItemKeyAt(column));
}
/** Returns the number of a changed column. */
public final int getChangedColumn() {
return this.currentColumn;
}
/**
* Returns true if a new value was created or an already exist value was
* changed, otherwise false.
*/
public final boolean isColumnValueChanged() {
return this.valueChanged;
}
/** TableModel interface implementation: dispatching to my specific methods. */
public final boolean isCellEditable(int row, int column) {
AttrTuple tuple = this.editor.getTuple();
if (tuple == null) {
return false;
}
else if (row >= tuple.getNumberOfEntries()) {
return isNewRowEditable(getItemKeyAt(column));
}
else {
return isItemEditable(getMember(tuple, row), getItemKeyAt(column));
}
}
/** TableModel interface implementation: dispatching to my specific methods. */
public final void setValueAt(Object aValue, int row, int column) {
AttrTuple tuple = this.editor.getTuple();
if (tuple == null) {
return;
}
Object oldvalue = getValueAt(row, column);
this.currentColumn = column;
if (row >= tuple.getNumberOfEntries()) {
this.valueChanged = true;
setItemOfNewRow(aValue, getItemKeyAt(column), tuple, row);
} else {
if (oldvalue == null) {
this.valueChanged = true;
} else if (!oldvalue.equals(aValue)) {
this.valueChanged = true;
} else {
this.valueChanged = false;
}
setItem(aValue, getMember(tuple, row), getItemKeyAt(column), tuple,
row);
}
AttrSession.logPrintln(VerboseControl.logTrace,
"TupleTableModel:\n<-setValueAt");
}
/** TableModel interface implementation: dispatching to my specific methods. */
public final Class<?> getColumnClass(int column) {
return getItemClass(getItemKeyAt(column));
}
}
/*
* $Log: TupleTableModel.java,v $
* Revision 1.22 2010/11/28 22:08:46 olga
* tuning
*
* Revision 1.21 2010/09/23 08:13:17 olga
* tuning
*
* Revision 1.20 2010/03/22 09:41:54 olga
* tuning
*
* Revision 1.19 2010/03/21 21:22:11 olga
* edit attribute - improved
*
* Revision 1.18 2010/03/19 14:44:30 olga
* isClassName(String) is only used in AGG GUI now
*
* Revision 1.17 2008/07/14 07:35:48 olga
* Applicability of RS - new option added, more tuning
* Node animation - new animation parameter added,
* Undo edit manager - possibility to disable it when graph transformation
* because it costs much more time and memory
*
* Revision 1.16 2008/01/14 09:01:26 olga
* String.isEmpty() replaced by String.length()==0
*
* Revision 1.15 2008/01/14 08:46:42 olga
* Bug fixed in using of CSP without Backjumping (CSP w/o BJ) match algorithm;
* Bug fixed in using layered graph transformation with loop over layers.
*
* Revision 1.14 2007/11/19 08:48:39 olga
* Some GUI usability mistakes fixed.
* Default values in node/edge of a type graph implemented.
* Code tuning.
*
* Revision 1.13 2007/11/05 09:18:19 olga
* code tuning
*
* Revision 1.12 2007/11/01 09:58:17 olga
* Code refactoring: generic types- done
*
* Revision 1.11 2007/09/24 09:42:35 olga
* AGG transformation engine tuning
*
* Revision 1.10 2007/09/13 14:58:59 olga
* tests
*
* Revision 1.9 2007/09/10 13:05:29 olga
* In this update:
* - package xerces2.5.0 is not used anymore;
* - class com.objectspace.jgl.Pair is replaced by the agg own generic class agg.util.Pair;
* - bugs fixed in: usage of PACs in rules; match completion;
* usage of static method calls in attr. conditions
* - graph editing: added some new features
* Revision 1.8 2007/03/28 10:00:59 olga -
* extensive changes of Node/Edge Type Editor, - first Undo implementation for
* graphs and Node/edge Type editing and transformation, - new / reimplemented
* options for layered transformation, for graph layouter - enable / disable for
* NACs, attr conditions, formula - GUI tuning
*
* Revision 1.7 2007/02/05 12:33:44 olga CPA: chengeAttribute
* conflict/dependency : attributes with constants bug fixed, but the critical
* pairs computation has still a gap.
*
* Revision 1.6 2006/12/13 13:33:04 enrico reimplemented code
*
* Revision 1.5 2006/08/02 09:00:57 olga Preliminary version 1.5.0 with -
* multiple node type inheritance, - new implemented evolutionary graph layouter
* for graph transformation sequences
*
* Revision 1.4 2006/01/16 09:35:33 olga Extended attr. setting
*
* Revision 1.3 2005/11/16 09:50:57 olga tests
*
* Revision 1.2 2005/11/07 09:38:07 olga Null pointer during retype attr. member
* fixed.
*
* Revision 1.1 2005/08/25 11:56:58 enrico *** empty log message ***
*
* Revision 1.1 2005/05/30 12:58:04 olga Version with Eclipse
*
* Revision 1.8 2005/04/11 13:06:13 olga Errors during CPA are corrected.
*
* Revision 1.7 2005/03/03 13:48:42 olga - Match with NACs and attr. conditions
* with mixed variables - error corrected - save/load class packages written by
* user - PACs : creating T-equivalents - improved - save/load matches of the
* rules (only one match of a rule) - more friendly graph/rule editor GUI - more
* syntactical checks in attr. editor
*
* Revision 1.6 2004/11/15 11:24:45 olga Neue Optionen fuer Transformation;
* verbesserter default Graphlayout; Close GraGra mit Abfrage wenn was geaendert
* wurde statt Delete GraGra
*
* Revision 1.5 2004/06/09 11:32:53 olga Attribute-Eingebe/Bedingungen : NAC
* kann jetzt eigene Variablen und Bedingungen haben. CP Berechnung korregiert.
*
* Revision 1.4 2003/03/05 18:24:11 komm sorted/optimized import statements
*
* Revision 1.3 2002/11/25 14:56:14 olga Der Fehler unter Windows 2000 im
* AttributEditor ist endlich behoben. Es laeuft aber mit Java1.3.0 laeuft
* endgueltig nicht. Also nicht Java1.3.0 benutzen!
*
* Revision 1.2 2002/09/23 12:23:51 komm added type graph in xt_basis, editor
* and GUI
*
* Revision 1.1.1.1 2002/07/11 12:16:57 olga Imported sources
*
* Revision 1.7 2000/04/05 12:08:01 shultzke serialVersionUID aus V1.0.0
* generiert
*
*/