package agg.attribute.gui.impl;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import agg.attribute.AttrInstance;
import agg.attribute.AttrInstanceMember;
import agg.attribute.AttrManager;
import agg.attribute.AttrMember;
import agg.attribute.AttrTuple;
import agg.attribute.AttrType;
import agg.attribute.gui.AttrEditorManager;
import agg.attribute.handler.AttrHandlerException;
import agg.attribute.handler.HandlerExpr;
import agg.attribute.util.RowDragEvent;
import agg.attribute.util.RowDragListener;
import agg.attribute.util.TableRowDragger;
import agg.attribute.view.AttrViewEvent;
/**
* Editor for all data of a tuple.
*
* @author $Author: olga $
* @version $Id: ExtendedTupleEditorSupport.java,v 1.2 2005/11/21 09:20:45 olga
* Exp $
*/
public abstract class ExtendedTupleEditorSupport extends BasicTupleEditor
implements ListSelectionListener, RowDragListener {
// Actions for tool bars and menus.
/** Action for removing a member from the edited tuple. */
protected Action deleteAction;
/** Action for evaluating a member of the edited tuple. */
protected Action evaluateAction;
/** Resetting the layout of the edited tuple. */
protected Action resetAction;
/** Making all members visible. */
protected Action showAllAction;
/** Making all members invisible. */
protected Action hideAllAction;
/**
* Collections of tuple actions, used for collectively enabling/disabling
* actions depending on the state of the editor.
*/
protected Vector<Action> tupleActions;
/**
* Collections of member actions, used for collectively enabling/disabling
* actions depending on the state of the editor.
*/
protected Vector<Action> memberActions;
// State indicators
/** Indicates if row selection is enabled. */
protected boolean rowSelectionEnabled;
/** Indicates if row dragging is enabled. */
protected boolean rowDraggingEnabled;
/** The row dragger instance. */
protected TableRowDragger rowDragger;
/**
* When disabling of dragging was requested while dragging was active, the
* operation is performed later, as soon as dragging stops.
*/
protected boolean rowDraggingDisablingRequested;
// Widgets
protected JTextArea outputTextArea;
protected JScrollPane outputScrollPane;
protected JPanel toolBarPanel;
protected JSplitPane tableAndOutputSplitPane;
// ///////////////////////////////////////////
// Constructing
//
/** Creating the tuple editor. */
public ExtendedTupleEditorSupport(AttrManager m, AttrEditorManager em) {
super(m, em);
}
protected void createTableView() {
super.createTableView();
// Reordering of columns.
this.tableView.getTableHeader().setReorderingAllowed(true);
// Enable row selection and -dragging.
setRowSelectionEnabled(true);
setRowDraggingEnabled(true);
// Decorating.
// tableScrollPane.setBorder(new BevelBorder(BevelBorder.LOWERED));
}
protected void genericCreateAllViews() {
createTableView();
createOutputTextArea();
createToolBar();
}
/**
* Called by createTableView(). Makes selecting of rows possible or not.
* Calling this method with 'true' is necessary if one desires any member
* actions (deleting, evaluating). Can also be called from 'outside', even
* in the middle of a session.
*/
public void setRowSelectionEnabled(boolean b) {
// AttrSession.logPrintln(this+": setRowSelectionEnabled("+b+")");
if (b) {
// Selecting of rows, not columns:
this.tableView.setRowSelectionAllowed(true);
this.tableView.setColumnSelectionAllowed(false);
// Just one row at a time:
this.tableView.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// Listen to selection events:
if (!this.rowSelectionEnabled) {
this.rowSelectionEnabled = true;
this.tableView.getSelectionModel().addListSelectionListener(this);
}
} else {
// Selecting of neither rows nor columns:
this.tableView.setRowSelectionAllowed(false);
this.tableView.setColumnSelectionAllowed(false);
// Stop listening to selection events:
if (this.rowSelectionEnabled) {
this.rowSelectionEnabled = false;
this.tableView.getSelectionModel().removeListSelectionListener(this);
}
}
}
/**
* Called by createTableView(). Makes dragging of rows possible or not.
* Calling this method with 'true' is necessary if one desires moving of
* rows around. Can also be called from 'outside', even in the middle of a
* session.
*/
public void setRowDraggingEnabled(boolean b) {
// AttrSession.logPrintln(this + ": setRowDraggingEnabled("+b+")");
if (b) {
if (this.rowDragger == null) {
this.rowDragger = new TableRowDragger(this.tableView);
}
if (!this.rowDraggingEnabled) {
this.rowDraggingEnabled = true;
this.rowDragger.addRowDragListener(this);
}
} else {
if (this.rowDraggingEnabled) {
// No disabling while dragging is active. Request will be
// honoured
// when dragging stops.
if (isDraggingActive()) {
this.rowDraggingDisablingRequested = true;
} else {
this.rowDraggingEnabled = false;
this.rowDragger.removeRowDragListener(this);
}
}
}
}
/**
* Switching sensitivity of buttons for actions which apply to the whole
* tuple on or off. Typically called with 'false' when the tuple is null.
*/
protected void setTupleActionsEnabled(boolean b) {
for (Enumeration<Action> en = this.tupleActions.elements(); en.hasMoreElements();) {
en.nextElement().setEnabled(b);
}
}
/**
* Switching sensitivity of buttons for actions which apply to single tuple
* members on or off. Typically called with 'false' when no member is
* selected.
*/
protected void setMemberActionsEnabled(boolean b) {
for (Enumeration<Action> en = this.memberActions.elements(); en.hasMoreElements();) {
en.nextElement().setEnabled(b);
}
}
/** Adding a tuple action to an action container. */
protected void addTupleAction(Action a) {
if (this.tupleActions == null)
this.tupleActions = new Vector<Action>(4);
this.tupleActions.addElement(a);
}
/** Adding a member action to an action container. */
protected void addMemberAction(Action a) {
if (this.memberActions == null)
this.memberActions = new Vector<Action>(4);
this.memberActions.addElement(a);
}
//
// "Library" of TUPLE actions that can be attached to toolbars and/or menus.
/**
* Action for setting the view back: all members become visible, the order
* is as created.
*/
@SuppressWarnings("serial")
protected Action getResetAction() {
if (this.resetAction != null)
return this.resetAction; // Already defined;
Action action = new AbstractAction("Reset") {
public void actionPerformed(ActionEvent ev) {
if (ExtendedTupleEditorSupport.this.tuple == null)
return;
ExtendedTupleEditorSupport.this.viewSetting.resetTuple(ExtendedTupleEditorSupport.this.tuple);
}
};
action.putValue(Action.SHORT_DESCRIPTION,
"Back to the original layout.");
addTupleAction(action);
this.resetAction = action;
return action;
}
/** Action for making all members visible. */
@SuppressWarnings("serial")
protected Action getShowAllAction() {
if (this.showAllAction != null)
return this.showAllAction; // Already defined;
Action action = new AbstractAction("Show All") {
public void actionPerformed(ActionEvent ev) {
if (ExtendedTupleEditorSupport.this.tuple == null)
return;
// System.out.println("ExtendedTupleEditorSupport.ShowAll-actionPerformed");
ExtendedTupleEditorSupport.this.viewSetting.setAllVisible(ExtendedTupleEditorSupport.this.tuple, true);
}
};
action.putValue(Action.SHORT_DESCRIPTION,
"Makes all tuple members visible.");
addTupleAction(action);
this.showAllAction = action;
return action;
}
/** Action for making all members invisible. */
@SuppressWarnings("serial")
protected Action getHideAllAction() {
if (this.hideAllAction != null)
return this.hideAllAction; // Already defined;
Action action = new AbstractAction("Hide All") {
public void actionPerformed(ActionEvent ev) {
if (ExtendedTupleEditorSupport.this.tuple == null)
return;
// System.out.println("ExtendedTupleEditorSupport.HideAll-actionPerformed");
ExtendedTupleEditorSupport.this.viewSetting.setAllVisible(ExtendedTupleEditorSupport.this.tuple, false);
}
};
action.putValue(Action.SHORT_DESCRIPTION, "Hides all tuple members.");
addTupleAction(action);
this.hideAllAction = action;
return action;
}
//
// "Library" of MEMBER actions that can be attached to toolbars and/or
// menus.
/** Action for deleting the selected member. */
@SuppressWarnings("serial")
protected Action getDeleteAction() {
if (this.deleteAction != null)
return this.deleteAction; // Already defined;
Action action = new AbstractAction("Delete") {
public void actionPerformed(ActionEvent ev) {
if (ExtendedTupleEditorSupport.this.tuple == null)
return;
AttrType type = ((AttrInstance) ExtendedTupleEditorSupport.this.tuple).getType();
int slot = ExtendedTupleEditorSupport.this.tableView.getSelectedRow();
if (slot >= type.getNumberOfEntries(ExtendedTupleEditorSupport.this.viewSetting)){
return;
}
else if (!type.isOwnMemberAt(ExtendedTupleEditorSupport.this.viewSetting, slot)) {
setMessage("Cannot delete this attribute member which belongs to a parent type."
+" Each attribute member must be deleted from its own type tuple.");
JOptionPane.showMessageDialog(null,
"<html><body>"
+"Cannot delete this attribute member which belongs to a parent type."
+"<br>"
+"Each attribute member must be deleted from its own type tuple.",
" Cannot delete ",
JOptionPane.ERROR_MESSAGE);
return;
}
type.deleteMemberAt(ExtendedTupleEditorSupport.this.viewSetting, slot);
}
};
action
.putValue(Action.SHORT_DESCRIPTION,
"Removes the selected member");
addMemberAction(action);
this.deleteAction = action;
return action;
}
/** Evaluating the expression of the selected member. */
@SuppressWarnings("serial")
protected Action getEvaluateAction() {
if (this.evaluateAction != null)
return this.evaluateAction; // Already defined;
Action action = new AbstractAction("Evaluate") {
public void actionPerformed(ActionEvent ev) {
AttrInstanceMember member = getSelectedMember();
if (member == null)
return;
HandlerExpr expr = member.getExpr();
if (expr == null)
return;
try {
expr.evaluate(((AttrInstance) ExtendedTupleEditorSupport.this.tuple).getContext());
member.setExpr(expr);
} catch (AttrHandlerException ex) {
setMessage(ex.getMessage());
}
}
};
action.putValue(Action.SHORT_DESCRIPTION, "Evaluates the expression");
addMemberAction(action);
this.evaluateAction = action;
return action;
}
//
// A message text area.
//
/** Creates a text area for displaying messages. */
protected void createOutputTextArea() {
this.outputTextArea = new JTextArea(80, 30);
this.outputTextArea.setRows(2);
this.outputTextArea.setEditable(false);
this.outputTextArea.setLineWrap(false);
this.outputScrollPane = new JScrollPane(this.outputTextArea,
VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
// outputTA.setBackground( Color.gray );
this.outputScrollPane.setMinimumSize(new Dimension(60, 30));
this.outputScrollPane.setPreferredSize(new Dimension(100, 30));
}
/** Shows the report for the currently selected row. */
public void displayValidityReport() {
if (this.tuple == null)
return;
setMessage("");
int row = this.tableView.getSelectedRow();
if (row < this.tuple.getNumberOfEntries() && row >= 0)
displayValidityReport(row);
}
/** Shows the report for the specified row. */
public void displayValidityReport(int row) {
displayValidityReport(this.tableModel.getMember(this.tuple, row));
}
/** Shows the report for the specified attribute member. */
public void displayValidityReport(AttrMember m) {
setMessage(m.getValidityReport());
}
/** Displays <code>text</code> in the message area, if it was created. */
public void setMessage(String text) {
if (this.outputTextArea == null)
return;
if (text != null && text.length() > 0) {
this.outputTextArea.setText(text.replaceAll("\n", " "));
this.outputTextArea.setRows(2);
}
else
this.outputTextArea.setText("");
}
//
// A Tool Bar:
protected abstract void createToolBar();
//
// Implementing the RowDragListener interface
//
/** Just acknowledge the fact. */
public void draggingStarted(RowDragEvent ev) {
setMessage("...Moving row...");
// System.out.println("Started dragging row "+draggedRow);
}
/** Here, just handle dragging disabling requests, if any. */
public void draggingStopped(RowDragEvent ev) {
if (this.rowDraggingDisablingRequested) {
this.rowDraggingDisablingRequested = false;
setRowDraggingEnabled(false);
}
displayValidityReport();
}
/** Actually moving a member wrt the current view. */
public void draggingMoved(RowDragEvent ev) {
/*
* System.out.println ("draggingMoved("+ev.getSourceRow()+", "+
* ev.getTargetRow()+")");
*/
int src = ev.getSourceRow();
int dest = ev.getTargetRow();
src = Math.min(src, this.tuple.getNumberOfEntries() - 1);
dest = Math.min(dest, this.tuple.getNumberOfEntries() - 1);
if (dest == -1 || src == -1)
return;
if (dest == src)
return;
// System.out.println("Source row="+src+"; dest. row="+dest);
if (src < dest)
dest++; // append if moving down the table;
this.viewSetting.moveSlotInserting(this.tuple, src, dest);
}
/** Convenience method. */
protected boolean isDraggingActive() {
if (!this.rowDraggingEnabled) {
return false;
}
return this.rowDragger.isDraggingActive();
}
/**
* Convenience method, called by the list selection event handling method
* valueChanged().
*/
protected void memberRowSelected(int row) {
displayValidityReport();
setMemberActionsEnabled(true);
}
/**
* Convenience method, called by the list selection event handling method
* valueChanged( ListSelectionEvent ev ), when the selected row is the
* bottom row for adding of new members..
*/
protected void newRowSelected() {
setMessage("A new member can be added in this row.");
setMemberActionsEnabled(false);
}
/** ListSelectionListener interface implementation. */
public void valueChanged(ListSelectionEvent ev) {
if (this.tuple == null)
return;
if (isDraggingActive())
return;
int row = ev.getFirstIndex();
if (row < this.tuple.getNumberOfEntries() && row >= 0) {
memberRowSelected(row);
} else if (row == this.tuple.getNumberOfEntries()) {
newRowSelected();
}
}
//
// Public methods.
//
// Implementation of the TupleEditor interface
/** Implemented as parent, plus managing enabling/disabling of actions. */
public void setTuple(AttrTuple anAttrTuple) {
super.setTuple(anAttrTuple);
setTupleActionsEnabled(anAttrTuple != null);
setMemberActionsEnabled(false);
} // setTuple()
public void attributeChanged(AttrViewEvent event) {
super.attributeChanged(event);
if (!isDraggingActive())
displayValidityReport();
}
}
/*
* $Log: ExtendedTupleEditorSupport.java,v $
* Revision 1.8 2010/08/23 07:30:02 olga
* tuning
*
* Revision 1.7 2010/03/08 15:36:09 olga
* code optimizing
*
* Revision 1.6 2008/10/15 07:51:22 olga
* Delete attr. member of parent type : error message dialog to warn the user
*
* Revision 1.5 2008/07/09 13:34:26 olga
* Applicability of RS - bug fixed
* Delete not used node/edge type - bug fixed
* AGG help - extended
*
* Revision 1.4 2007/11/01 09:58:17 olga
* Code refactoring: generic types- done
*
* Revision 1.3 2007/09/10 13:05:30 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.2 2005/11/21 09:20:45
* olga tests
*
* Revision 1.1 2005/08/25 11:56:59 enrico *** empty log message ***
*
* Revision 1.1 2005/05/30 12:58:04 olga Version with Eclipse
*
* Revision 1.5 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.4 2004/12/20 14:53:47 olga Changes because of matching
* optimisation.
*
* Revision 1.3 2003/03/05 18:24:10 komm sorted/optimized import statements
*
* Revision 1.2 2002/09/23 12:23:50 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.6 2000/04/05 12:07:48 shultzke serialVersionUID aus V1.0.0
* generiert
*
* Revision 1.5 1999/08/17 07:32:22 shultzke GUI leicht geaendert
*/