Files
secondo/Javagui/viewer/UpdateViewer.java

1256 lines
33 KiB
Java
Raw Normal View History

2026-01-23 17:03:45 +08:00
/*
----
This file is part of SECONDO.
Copyright (C) 2004, University in Hagen, Department of Computer Science,
Database Systems for New Applications.
SECONDO 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.
SECONDO 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 SECONDO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
----
04-2005, Matthias Zielke
01-2006, T. Behr: generic approach for displaying different types realized
12-2006, T. Behr: SplitPane between relation and insertions introduced
Removing rows from insertions implemented
*/
package viewer;
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;
import gui.SecondoObject;
import viewer.update.*;
import sj.lang.*;
import tools.Reporter;
/*
This specialized viewer shall only be used for updating relations. Therefore it can not
be called for any object retrieved by commands from the CommandPanel. It asks itself for
relations to be loaded and displays them. Afterwards update-operations can be applied to
the relation and the changes are finally sent to SECONDO. If succesfull the new updated
relation will be shown, otherwise an errormessage should be displayed.
*/
public class UpdateViewer extends SecondoViewer implements TableModelListener {
private String viewerName = "UpdateViewer";
// Needed to build the actionPanel that offers the user possible update-operations
private JPanel actionPanel;
private JTextField relField;
private JButton load;
private JButton clear;
private JButton insert;
private JButton delete;
private JButton update;
private JButton reset;
private JButton commit;
private JButton popup;
private EditDialog editDialog;
// the controller decides which action shall be taken next and listens to all buttons
// for user-input
private ActionController controller;
// ScrollPanes to show the update-relation or a relation with new tuples to be inserted
private JScrollPane relScroll;
private JScrollPane insertScroll;
private JSplitPane insertSplit= new JSplitPane(JSplitPane.VERTICAL_SPLIT);
// Dialog to show errormessages
private JDialog errorDialog;
// Dialog to specify relation to be loaded and filters to be applied
private LoadDialog loadDialog;
// stores the data actually shown in the viewer
private String[][] relData;
// stores the data retrieved from secondo for the originally loaded relation
private String[][] originalData;
// Contains the IDs of all tuples of the actual relation
private Vector tupleIds;
// Shows the relation currently edited
private JTable relTable;
private String[] head;
private String[] attrTypes;
// In updatemode contains true for each updated attribute for each record
private boolean[][] changedCells;
// For each updated row an entry with its index is inserted
private Vector changedRows;
// Contains all changed Cells in the order they were edited
private Vector updatesOrdered;
// Contains the information of the inserted tuples
private String[][] insertData;
// Shows the relation to insert new tuples
private JTable insertTable;
// Each updated attribute is marked by this renderer
private DefaultTableCellRenderer renderer;
private boolean relEditable;
/*
Builds the viewer and sets the intital values
*/
public UpdateViewer() {
setLayout(new BorderLayout());
controller = new ActionController(this);
// Build actionpanel
actionPanel = new JPanel();
actionPanel.setLayout(new GridLayout(1, 7));
load = new JButton("Load Relation");
load.addActionListener(controller);
actionPanel.add(load);
clear = new JButton("Clear");
clear.addActionListener(controller);
actionPanel.add(clear);
insert = new JButton("Insert");
insert.addActionListener(controller);
actionPanel.add(insert);
delete = new JButton("Delete");
delete.addActionListener(controller);
actionPanel.add(delete);
update = new JButton("Update");
update.addActionListener(controller);
actionPanel.add(update);
reset = new JButton("Reset");
reset.addActionListener(controller);
actionPanel.add(reset);
commit = new JButton("Commit");
commit.addActionListener(controller);
actionPanel.add(commit);
editDialog=new EditDialog();
popup = new JButton("Popup");
popup.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent evt){
UpdateViewer.this.editField();
}
});
actionPanel.add(popup);
add(actionPanel, BorderLayout.NORTH);
renderer = new DefaultTableCellRenderer();
renderer.setBackground(Color.YELLOW);
relEditable = false;
setSelectionMode(ActionController.INITIAL);
}
/*
Get the name of this viewer.
The name is used in the menu of the MainWindow.
*/
public String getName() {
return viewerName;
}
/*
Because this viewer shall not display objects others than relations loaded
by the viewer itself only false is returned.
*/
public boolean addObject(SecondoObject o) {
return false;
}
/*
Because this viewer shall not display objects others than relations loaded
by the viewer itself no object shall be removed.
*/
public void removeObject(SecondoObject o) {
}
/*
Because this viewer shall not display objects others than relations loaded
by the viewer itself no objects shall be removed.
*/
public void removeAll() {
}
/*
Because this viewer shall not display objects others than relations loaded
by the viewer itself false is returned.
*/
public boolean canDisplay(SecondoObject o) {
return false;
}
/*
Because this viewer shall not display objects others than relations loaded
by the viewer itself false is returned.
*/
public boolean isDisplayed(SecondoObject o) {
return false;
}
/*
Because this viewer shall not display objects others than relations loaded
by the viewer itself false is returned.
*/
public boolean selectObject(SecondoObject O) {
return false;
}
/*
Because all commands for this viewer can easily be accessed from the actionPanel
no MenuVector is built.
*/
public MenuVector getMenuVector() {
return null;
}
/*
Because this viewer shall not display objects others than relations loaded
by the viewer itself 0 is returned.
*/
public double getDisplayQuality(SecondoObject SO) {
return 0;
}
/*
Shows a dialog with the errorText.
*/
public void showErrorDialog(String errorText) {
Reporter.showError(errorText);
this.repaint();
this.validate();
}
/*
If the paramater 'relation' is really a relation it will be shown in the viewer. Otherwise
false will be returned.
*/
public boolean showNewRelation(ListExpr relation) {
relTable = createTableFrom(relation);
if (relTable == null) {
return false;
}
relScroll = new JScrollPane();
add(relScroll, BorderLayout.CENTER);
relTable.setRowSelectionAllowed(false);
relTable.setColumnSelectionAllowed(false);
relEditable = false;
TableModel model = relTable.getModel();
model.addTableModelListener(this);
relScroll.setViewportView(relTable);
this.repaint();
this.validate();
return true;
}
/*
Shows the original relation retrieved from SECONDO. All updates that have not been
commited yet will be lost.
*/
public void showOriginalRelation() {
relTable.setRowSelectionAllowed(false);
relTable.setColumnSelectionAllowed(false);
relEditable = false;
for (int i = 0; i < relData.length; i++) {
for (int j = 0; j < relData[0].length; j++) {
changedCells[i][j] = false;
changedRows.clear();
relData[i][j] = new String(originalData[i][j]);
}
}
relTable.clearSelection();
relTable.invalidate();
this.repaint();
this.validate();
}
/*
Removes the relation that could be edited to insert new tuples.
*/
public void removeInsertRelation() {
// this.remove(insertScroll);
this.remove(insertSplit);
this.add(relScroll, BorderLayout.CENTER);
insertData = null;
insertTable = null;
insertScroll = null;
this.validate();
}
/* Adds remove functionality to the insertTable */
private void addRemoveToInsertTable(){
if(insertTable==null){
return;
}
insertTable.addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent evt){
if( (evt.getKeyCode()==KeyEvent.VK_DELETE)){
removeInsertSelection();
}
}
});
}
/*
Removes the last added tuple from the insert-relation
*/
public boolean removeLastInsertTuple(){
if (insertData.length == 1){
removeInsertRelation();
return false;
}
else {
String[][] newInsertData = new String[insertData.length - 1][insertData[0].length];
for (int i = 0; i < insertData.length -1 ; i++) {
newInsertData[i] = insertData[i];
}
insertData = newInsertData;
insertTable = new JTable(insertData, head);
insertScroll.setViewportView(insertTable);
insertSplit.setBottomComponent(insertScroll);
this.add(insertSplit,BorderLayout.CENTER);
insertSplit.revalidate();
insertSplit.setDividerLocation(0.5);
addRemoveToInsertTable();
// this.add(insertScroll, BorderLayout.SOUTH);
this.validate();
this.repaint();
return true;
}
}
/*
Removes the relation actually shown from this viewer. All information about this relation
will be lost.
*/
public void removeRelation() {
this.remove(relScroll);
relData = null;
relTable = null;
head = null;
attrTypes = null;
changedCells = null;
changedRows = null;
originalData = null;
this.validate();
this.repaint();
}
/** Pops up a new window for editing the current field.
*/
private void editField(){
if(relTable==null){
Reporter.showError("No table load.");
return;
}
int row = relTable.getSelectedRow();
int col = relTable.getSelectedColumn();
if(row<0 || col<0){
row = relTable.getEditingRow();
col = relTable.getEditingRow();
}
int er = relTable.getEditingRow();
int ec = relTable.getEditingColumn();
if(er>=0 && ec >=0){
relTable.getCellEditor(er,ec).stopCellEditing();
}
relTable.removeEditor();
if(row<0 || col<0){
Reporter.showError("Select a field first");
return;
}
String res = editDialog.editText(relTable.getValueAt(row,col).toString());
if(res!=null){
relTable.setValueAt(res,row,col);
}
}
/*
For each mode and state the viewer is in only certain operations and choices are possible.
This method assures only the actually allowed actions can be executed or chosen.
*/
public void setSelectionMode(int selectMode) {
switch (selectMode) {
case ActionController.INITIAL: {
insert.setBackground(Color.LIGHT_GRAY);
delete.setBackground(Color.LIGHT_GRAY);
update.setBackground(Color.LIGHT_GRAY);
clear.setEnabled(false);
insert.setEnabled(false);
delete.setEnabled(false);
update.setEnabled(false);
reset.setEnabled(false);
commit.setEnabled(false);
popup.setEnabled(false);
break;
}
case ActionController.LOADED: {
insert.setBackground(Color.LIGHT_GRAY);
delete.setBackground(Color.LIGHT_GRAY);
update.setBackground(Color.LIGHT_GRAY);
clear.setEnabled(true);
insert.setEnabled(true);
delete.setEnabled(true);
update.setEnabled(true);
reset.setEnabled(false);
commit.setEnabled(false);
popup.setEnabled(false);
break;
}
case ActionController.INSERT: {
insert.setBackground(Color.YELLOW);
delete.setEnabled(false);
update.setEnabled(false);
reset.setEnabled(true);
commit.setEnabled(true);
relTable.setRowSelectionAllowed(false);
relTable.setColumnSelectionAllowed(false);
relEditable = false;
popup.setEnabled(false);
break;
}
case ActionController.DELETE: {
delete.setBackground(Color.YELLOW);
insert.setEnabled(false);
delete.setEnabled(false);
update.setEnabled(false);
reset.setEnabled(true);
commit.setEnabled(true);
relTable.setRowSelectionAllowed(true);
relEditable = false;
popup.setEnabled(false);
break;
}
case ActionController.UPDATE: {
update.setBackground(Color.YELLOW);
insert.setEnabled(false);
delete.setEnabled(false);
update.setEnabled(false);
reset.setEnabled(true);
commit.setEnabled(true);
relTable.setRowSelectionAllowed(false);
relTable.setColumnSelectionAllowed(false);
relEditable = true;
popup.setEnabled(true);
for (int i = 0; i < relData.length; i++) {
for (int j = 0; j < relData[0].length; j++) {
changedCells[i][j] = false;
}
}
break;
}
default:
showErrorDialog("The mode: " + selectMode + " is not known");
break;
}
}
/** Removes all selected rows from the InsertTable. **/
private void removeInsertSelection(){
if(insertTable==null){ // no table available
return;
}
if(insertTable.isEditing()){
return;
}
int[] selectedRows = insertTable.getSelectedRows();
if( selectedRows.length==0){
JOptionPane.showMessageDialog(this,"Nothing selected");
return;
}
int answer = JOptionPane.showConfirmDialog(this,"All selected rows will be deleted\n Do you want to continue?",
"Please Confirm",
JOptionPane.YES_NO_OPTION);
if((answer!=JOptionPane.YES_OPTION)){
return;
}
String[][] newInsertData = new String[insertData.length-selectedRows.length][insertData[0].length];
// copy all non-removed rows
int pos = 0;
for(int i=0;i < insertData.length;i++){
if(pos>=selectedRows.length){ // all selected rows are removed already
newInsertData[i-pos] = insertData[i];
} else if(i==selectedRows[pos]){ // remove this row
pos++;
} else {
newInsertData[i-pos] = insertData[i];
}
}
insertData = newInsertData;
insertTable = new JTable(insertData, head);
addRemoveToInsertTable();
insertScroll.setViewportView(insertTable);
int lastPos = insertSplit.getDividerLocation();
insertSplit.setBottomComponent(insertScroll);
this.add(insertSplit,BorderLayout.CENTER);
this.validate();
this.repaint();
insertSplit.setDividerLocation(lastPos);
}
/*
Creates a JTable from the parameter LE. If LE doesn't represent a relation 'null' will be
returned. The members that represent the original relation-data and the actual relation-data
are initialized. The IDs of the tuples of the relation are stored in a seperate vector
*/
private JTable createTableFrom(ListExpr LE) {
boolean result = true;
JTable NTable = null;
if (LE.listLength() != 2)
return null;
else {
ListExpr type = LE.first();
ListExpr value = LE.second();
// analyse type
if (type.isAtom())
return null;
ListExpr maintype = type.first();
if (type.listLength() != 2
|| !maintype.isAtom()
|| maintype.atomType() != ListExpr.SYMBOL_ATOM
|| !(maintype.symbolValue().equals("rel") | maintype
.symbolValue().equals("mrel")))
return null; // not a relation
ListExpr tupletype = type.second();
// analyse Tuple
ListExpr TupleFirst = tupletype.first();
if (tupletype.listLength() != 2
|| !TupleFirst.isAtom()
|| TupleFirst.atomType() != ListExpr.SYMBOL_ATOM
|| !(TupleFirst.symbolValue().equals("tuple") | TupleFirst
.symbolValue().equals("mtuple")))
return null; // not a tuple
ListExpr TupleTypeValue = tupletype.second();
// the table head
// Don't count the last attribute which is the tupleidentifier of each tuple
int tupleLength = TupleTypeValue.listLength() - 1;
head = new String[tupleLength];
attrTypes = new String[tupleLength];
for (int i = 0; (i < tupleLength) && result; i++) {
ListExpr TupleSubType = TupleTypeValue.first();
if (TupleSubType.listLength() != 2)
result = false;
else {
head[i] = TupleSubType.first().writeListExprToString();
attrTypes[i] = TupleSubType.second()
.writeListExprToString();
}
TupleTypeValue = TupleTypeValue.rest();
}
if (result) {
// analyse the values
ListExpr TupleValue;
Vector V = new Vector();
tupleIds = new Vector();
String[] row;
ListExpr Elem;
while (!value.isEmpty()) {
TupleValue = value.first();
row = new String[head.length];
for(int pos=0;pos<head.length; pos++){
Elem = TupleValue.first();
LEFormatter LEF = AttributeFormatter.getFormatter(attrTypes[pos]);
row[pos] = LEF.ListExprToString(Elem);
TupleValue = TupleValue.rest();
}
V.add(row);
// Get the tupleid of this tuple as the last attribute
Elem = TupleValue.first();
if (Elem.isAtom()
&& Elem.atomType() == ListExpr.STRING_ATOM) {
tupleIds.add(Elem.textValue());
} else if ((Elem.isAtom() && Elem.atomType() == ListExpr.TEXT_ATOM)
|| (!Elem.isAtom() && Elem.listLength() == 1
&& Elem.first().isAtom() && Elem
.first().atomType() == ListExpr.TEXT_ATOM)) {
if (!Elem.isAtom())
Elem = Elem.first();
tupleIds.add(Elem.textValue());
} else
tupleIds.add(TupleValue.first().writeListExprToString());
value = value.rest();
}
//Initialize data
relData = new String[V.size()][head.length];
originalData = new String[V.size()][head.length];
changedCells = new boolean[V.size()][head.length];
changedRows = new Vector();
updatesOrdered = new Vector();
for (int i = 0; i < V.size(); i++) {
relData[i] = (String[]) V.get(i);
for (int j = 0; j < head.length; j++) {
changedCells[i][j] = false;
originalData[i][j] = new String(relData[i][j]);
}
}
// a specialized constructor is needed to mark updated attributes
// with a different renderer and to make the table only editable
// in update-mode
NTable = new JTable(relData, head) {
public TableCellRenderer getCellRenderer(int row, int column) {
if (changedCells[row][column]) {
return renderer;
} else
return super.getCellRenderer(row, column);
}
public boolean isCellEditable(int row, int column) {
return relEditable;
}
};
}
}
if (result)
return NTable;
else
return null;
}
/*
If the table was edited this method is called. Registers which cell was edited and
prepares this cell to be marked differently with the next 'repaint'.
*/
public void tableChanged(TableModelEvent e) {
int row = e.getFirstRow();
int column = e.getColumn();
int[] lastChanged = {row, column};
updatesOrdered.add(lastChanged);
changedCells[row][column] = true;
changedRows.add(new Integer(row));
this.repaint();
this.validate();
}
/*
The last cell the user edited before he pressed "commit" is usually not considered
because "tableChanged" will only be called, if he pressed "return" or selected a different cell
of the JTable before "commiting". Therefore this method takes over the value of the
last edited cell that was not taken into consideration yet.
*/
public void takeOverLastEditing(boolean updateMode){
if (updateMode){
if (relTable.isEditing()) {
int editedRow = relTable.getEditingRow();
int editedColumn = relTable.getEditingColumn();
CellEditor editor = relTable.getCellEditor(editedRow, editedColumn);
editor.stopCellEditing();
}
}
else{
if (insertTable.isEditing()) {
int editedRow = insertTable.getEditingRow();
int editedColumn = insertTable.getEditingColumn();
CellEditor editor = insertTable.getCellEditor(editedRow, editedColumn);
editor.stopCellEditing();
}
}
}
/*
Shows an empty relation that can be edited to contain tuples that shall be inserted.
*/
public void showInsertRelation() {
insertData = new String[1][relTable.getColumnCount()];
for (int i = 0; i < relTable.getColumnCount(); i++) {
insertData[0][i] = "";
}
insertTable = new JTable(insertData, head);
addRemoveToInsertTable();
insertScroll = new JScrollPane() {
public Dimension getPreferredSize() {
return new Dimension(this.getParent().getWidth(), this
.getParent().getHeight() / 5);
}
};
insertScroll.setViewportView(insertTable);
insertSplit.setTopComponent(relScroll);
insertSplit.setBottomComponent(insertScroll);
this.add(insertSplit, BorderLayout.CENTER);
this.revalidate();
this.validate();
this.repaint();
insertSplit.revalidate();
insertSplit.setDividerLocation(0.5);
}
/*
Is called when yet at least one insert-tuple was edited and another one shall be
edited. Takes over the already edited insert-tuples and shows one more empty tuple.
*/
public void addInsertTuple() {
this.remove(insertScroll);
String[][] newInsertData = new String[insertData.length + 1][insertData[0].length];
for (int i = 0; i < insertData.length; i++) {
newInsertData[i] = insertData[i];
}
for (int j = 0; j < insertData[0].length; j++) {
newInsertData[insertData.length][j] = "";
}
insertData = newInsertData;
insertTable = new JTable(insertData, head);
addRemoveToInsertTable();
insertScroll.setViewportView(insertTable);
int lastPos = insertSplit.getDividerLocation();
// insertSplit.setTopComponent(relScroll);
insertSplit.setBottomComponent(insertScroll);
this.add(insertSplit,BorderLayout.CENTER);
this.validate();
this.repaint();
insertSplit.setDividerLocation(lastPos);
}
/*
Returns the text inserted by the user into the JTextField. It should be the name of a
relation.
*/
public String getLoadName() {
return loadDialog.getLoadName();
}
/*
Returns all the filters that shall be applied when the next relation will be loaded
*/
public String[] getFilters() {
return loadDialog.getFilters();
}
/*
Returns true if the 'loadDialog' was cancelled
*/
public boolean loadCancelled() {
return loadDialog.loadCancelled();
}
/*
Returns the types of all attributes of the actually loaded relation.
*/
public String[] getAttrTypes() {
return attrTypes;
}
/*
Returns the values of all tuples that were edited to be inserted.
*/
public String[][] getInsertTuples() {
return insertData;
}
/*
Returns the values of all tuples that were marked to be deleted.
*/
public String[][] getDeleteTuples() {
int[] selectedRows = relTable.getSelectedRows();
String[][] deleteTuples = new String[selectedRows.length][relData[0].length];
for (int i = 0; i < selectedRows.length; i++) {
deleteTuples[i] = relData[selectedRows[i]];
}
return deleteTuples;
}
/*
Allows the user to reset delete-selections by pressing 'reset'
*/
public boolean resetDeleteSelections(){
if (relTable.getSelectedRows().length > 0){
relTable.clearSelection();
return true;
}
else{
return false;
}
}
/*
Returns the indices of all tuples that were marked to be deleted.
*/
public int[] getDeleteRows(){
return relTable.getSelectedRows();
}
/*
Returns the original values of the tuple at position 'index'.
*/
public String[] getOriginalTuple(int index) {
return originalData[index];
}
/*
Returns the tupleId of the record at position 'index'.
*/
public String getTupleId(int index){
return (String)(tupleIds.get(index));
}
/*
Returns an array with the indices of all updated tuples.
*/
public int[] updatedTuples() {
int[] updateTuples = new int[changedRows.size()];
for (int i = 0; i < updateTuples.length; i++) {
updateTuples[i] = ((Integer) changedRows.get(i)).intValue();
}
return updateTuples;
}
/*
Returns the values of the updated tuple at position 'index'.
*/
public String[] getUpdateTuple(int index) {
return relData[index];
}
/*
For the tuple at position 'index' returns all indices of the attributes that have
been changed inside this tuple.
*/
public int[] getChangedAttributes(int index) {
boolean[] attrs = changedCells[index];
Vector changedAttrs = new Vector();
for (int i = 0; i < changedCells[index].length; i++) {
if (changedCells[index][i]) {
changedAttrs.add(new Integer(i));
}
}
int[] result = new int[changedAttrs.size()];
for (int i = 0; i < result.length; i++) {
result[i] = ((Integer) changedAttrs.get(i)).intValue();
}
return result;
}
/*
Resets the last editited cell in updatemode to its original value.
*/
public boolean resetLastUpdate(){
if (changedRows.size() > 0) {
int[] lastChanged = (int[]) updatesOrdered.lastElement();
changedCells[lastChanged[0]][lastChanged[1]] = false;
changedRows.remove(changedRows.size() - 1);
updatesOrdered.remove(updatesOrdered.size() - 1);
relData[lastChanged[0]][lastChanged[1]] = originalData[lastChanged[0]][lastChanged[1]];
this.repaint();
this.validate();
return true;
}
else{
return false;
}
}
/* Resets all updates */
public boolean resetUpdates(){
if(relTable==null)
return false;
// reset the curretly editing cell if any
if(relTable.isEditing()){
int x = relTable.getEditingRow();
int y = relTable.getEditingColumn();
relTable.editingStopped(new ChangeEvent(this));
relTable.setValueAt(originalData[x][y],x,y);
}
for(int i=0;i<updatesOrdered.size();i++){
int[] changed = (int[]) updatesOrdered.get(i);
changedCells[changed[0]][changed[1]] = false;
relData[changed[0]][changed[1]] = originalData[changed[0]][changed[1]];
}
updatesOrdered.clear();
changedRows.clear();
relTable.revalidate();
relTable.repaint();
return true;
}
/** Start edititing the cell at the given position.
* All errors (wrong arguments, cell is not editable and so on) are
* ignored.
**/
public void relGoTo(int x, int y){
try{
relTable.editCellAt(x,y,null);
} catch(Exception e){
Reporter.debug(e);
}
}
/** Starts the edititing of the specified cell within the insert table **/
public void insertGoTo(int x, int y){
try{
insertTable.editCellAt(x,y,null);
}catch(Exception e){
Reporter.debug(e);
}
}
/*
Returns the names of the attributes of the tuples of the currently loaded relation.
*/
public String[] getAttrNames() {
return head;
}
/*
Shows a dialog to let the user specifiy which relation he wants to load and which filter-
criteria he wants to apply.
*/
public void showLoadDialog() {
if (loadDialog == null)
loadDialog = new LoadDialog();
else
loadDialog.clear();
loadDialog.setSize(600, 500);
loadDialog.setVisible(true);
}
/*
This class implements a dialog in which the user can specify which relation he wants to
load an which filter-criteria he wants to apply.
*/
private class LoadDialog extends JDialog implements ActionListener {
private final static String titleString = "Load relation";
//relationPanel
JPanel relPanel ;
JLabel relNameLabel;
JTextField relField;
//filterPanel
JPanel filterPanel ;
JPanel addPanel;
JButton addFilter;
JScrollPane filterScroll;
JPanel criteria ;
Vector removeButtons;
Vector criteriaPanels;
Vector criteriaFields;
//commitPanel
JPanel commitPanel;
JButton commit;
JButton cancel;
private boolean cancelled;
/*
Builds the visible dialog.
*/
public LoadDialog() {
//General settings
this.setModal(true);
this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
this.getContentPane().setLayout(new BorderLayout());
this.setTitle(titleString);
//Build relationPanel
relPanel = new JPanel();
relNameLabel = new JLabel("relation-name");
relPanel.add(relNameLabel);
relField = new JTextField(20);
relPanel.add(relField);
this.getContentPane().add(relPanel, BorderLayout.NORTH);
//Build filterPanel
filterPanel = new JPanel(new BorderLayout());
addPanel = new JPanel();
addFilter = new JButton("add filter");
addFilter.addActionListener(this);
addPanel.add(addFilter);
filterPanel.add(addPanel,BorderLayout.NORTH);
filterScroll = new JScrollPane();
criteria = new JPanel();
filterScroll.setViewportView(criteria);
filterPanel.add(filterScroll, BorderLayout.CENTER);
this.getContentPane().add(filterPanel, BorderLayout.CENTER);
//Build commitPanel
commitPanel = new JPanel();
cancel = new JButton("cancel");
cancel.addActionListener(this);
commitPanel.add(cancel);
commit = new JButton("commit");
commit.addActionListener(this);
commitPanel.add(commit);
this.getContentPane().add(commitPanel, BorderLayout.SOUTH);
removeButtons = new Vector();
criteriaPanels = new Vector();
criteriaFields = new Vector();
relField.addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent evt){
if(evt.getKeyCode()==KeyEvent.VK_ENTER){
LoadDialog.this.cancelled=false;
LoadDialog.this.setVisible(false);
}
}
});
}
/*
Is called if any of the buttons of the dialog was pressed.
*/
public void actionPerformed(ActionEvent e) {
if (e.getSource() == addFilter) {
JPanel nextFilterPanel = new JPanel();
JTextField nextField = new JTextField(20);
JButton nextRemove = new JButton("remove");
nextRemove.addActionListener(this);
nextFilterPanel.add(nextField);
nextFilterPanel.add(nextRemove);
criteriaPanels.add(nextFilterPanel);
removeButtons.add(nextRemove);
criteriaFields.add(nextField);
rebuildCriteriaPanel();
}
if (e.getActionCommand().equals("remove")){
for (int i = 0; i < removeButtons.size(); i++){
if(e.getSource() == removeButtons.get(i)){
removeButtons.remove(i);
criteriaFields.remove(i);
criteriaPanels.remove(i);
break;
}
}
rebuildCriteriaPanel();
}
if (e.getSource() == commit) {
cancelled = false;
this.setVisible(false);
}
if (e.getSource() == cancel) {
cancelled = true;
this.setVisible(false);
}
}
/*
Rebuilds the panel which contains the filter-conditions and sets an adjusted new
GridLayout to have a better view.
*/
private void rebuildCriteriaPanel(){
criteria.removeAll();
if (criteriaPanels.size() < 8)
criteria.setLayout(new GridLayout(8,1));
else
criteria.setLayout(new GridLayout(criteriaPanels.size(),1));
for (int i = 0; i < criteriaPanels.size(); i++){
criteria.add((JPanel)criteriaPanels.get(i));
}
this.validate();
this.repaint();
}
/*
Clears the dialog from all previously edited data.
*/
public void clear(){
removeButtons.clear();
criteriaFields.clear();
criteriaPanels.clear();
relField.setText("");
rebuildCriteriaPanel();
}
/*
Returns the name of the JTextField for the relation.
*/
public String getLoadName(){
return relField.getText().trim();
}
/*
Returns all the filter-conditions of the JTextFields for the filters.
*/
public String[] getFilters(){
String[] filters = new String[criteriaFields.size()];
for (int i = 0; i < filters.length; i++){
filters[i] = ((JTextField) criteriaFields.get(i)).getText().trim();
}
return filters;
}
/*
Returns true if this dialog was closed by pressing 'cancel'.
*/
public boolean loadCancelled(){
return cancelled;
}
}
private class EditDialog extends JDialog{
public EditDialog(){
area = new JTextPane();
//area.setLineWrap(true);
area.setEditable(true);
getContentPane().setLayout(new BorderLayout());
JPanel command = new JPanel();
JButton accept = new JButton("accept");
JButton cancel = new JButton("cancel");
command.add(accept);
command.add(cancel);
getContentPane().add(command,BorderLayout.SOUTH);
accept.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent evt){
retVal = area.getText();
area.setText("");
EditDialog.this.setVisible(false);
}
});
cancel.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent evt){
retVal = null;
area.setText("");
EditDialog.this.setVisible(false);
}
});
JScrollPane sp = new JScrollPane(area);
getContentPane().add(sp,BorderLayout.CENTER);
}
public String editText(String origtext){
if(origtext==null){
origtext="";
}
area.setText(origtext);
setSize(640,480);
setModal(true);
setVisible(true);
return retVal;
}
private JTextPane area;
private String retVal;
}
}