package org.enhydra.jawe.base.panel.panels;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import org.enhydra.jawe.ButtonPropertyChangedListener;
import org.enhydra.jawe.JaWEManager;
import org.enhydra.jawe.ResourceManager;
import org.enhydra.jawe.base.controller.JaWEActions;
import org.enhydra.jawe.base.controller.JaWEController;
import org.enhydra.jawe.base.editor.StandardXPDLElementEditor;
import org.enhydra.jawe.base.panel.InlinePanel;
import org.enhydra.jawe.base.panel.PanelSettings;
import org.enhydra.jawe.base.panel.panels.tablesorting.BasicSortingTable;
import org.enhydra.shark.xpdl.XMLCollection;
import org.enhydra.shark.xpdl.XMLCollectionElement;
import org.enhydra.shark.xpdl.XMLComplexElement;
import org.enhydra.shark.xpdl.XMLElement;
import org.enhydra.shark.xpdl.XMLElementChangeInfo;
import org.enhydra.shark.xpdl.XMLElementChangeListener;
import org.enhydra.shark.xpdl.XMLUtil;
/**
* Creates a table panel.
* @author Sasa Bojanic
* @author Zoran Milakovic
* @author Miroslav Popov
*/
public class XMLBasicTablePanel extends XMLBasicPanel implements XMLElementChangeListener {
public static Color FOREIGN_EL_COLOR_BKG = Color.lightGray;
public static Color SPEC_EL_COLOR_BKG = Color.orange;
protected static Dimension miniTableDimension = new Dimension(450, 125);
protected static Dimension smallTableDimension = new Dimension(450, 200);
protected static Dimension mediumTableDimension = new Dimension(550, 200);
protected static Dimension largeTableDimension = new Dimension(650, 200);
/**
* Object which we are replacing from one place to another within
* the list by dragging it.
*/
protected XMLElement movingElement;
/**
* Index of the object which we are replacing from one place to another
* within the list by dragging it.
*/
protected int movingElementPosition;
/**
* The new index of the object which we are replacing from one place
* to another within the list by dragging it.
*/
protected int newMovingElementPosition;
/** Indicates if object is being dragged. */
protected boolean dragging = false;
/**
* Indicates if the code for changing object position within the list
* is executed.
*/
protected boolean changing = false;
protected JTable allItems;
protected JPanel toolbox;
protected Vector columnNames;
protected List columnsToShow;
protected InlinePanel ipc;
public XMLBasicTablePanel(
InlinePanel ipc,
XMLCollection myOwner,
List columnsToShow,
List elementsToShow,
String title,
boolean hasBorder,
boolean hasEmptyBorder,
boolean automaticWidth,
boolean miniDimension,
final boolean colors,
final boolean showArrows) {
super(ipc,myOwner, title, true, hasBorder, hasEmptyBorder);
this.ipc=ipc;
myOwner.addListener(this);
myOwner.setNotifyListeners(true);
columnNames = getColumnNames(columnsToShow);
this.columnsToShow = columnsToShow;
allItems = createTable(colors);
setupTable(miniDimension, automaticWidth, showArrows);
fillTableContent(elementsToShow);
toolbox = createToolbar();
JPanel paneAndArrows = new JPanel();
paneAndArrows.setLayout(new BoxLayout(paneAndArrows, BoxLayout.X_AXIS));
paneAndArrows.add(createScrollPane());
// if (showArrows) {
// JPanel p = createArrowPanel();
// paneAndArrows.add(Box.createRigidArea(new Dimension(5, 0)));
// paneAndArrows.add(p);
// }
add(toolbox);
add(Box.createVerticalStrut(3));
add(paneAndArrows);
adjustActions();
}
public JTable getTable() {
return allItems;
}
public XMLElement getSelectedElement() {
int row = allItems.getSelectedRow();
if (row >= 0) {
return (XMLElement) allItems.getValueAt(row, 0);
}
return null;
}
public boolean setSelectedElement(Object el) {
try {
int rc = allItems.getRowCount();
if (rc > 0) {
for (int i = 0; i < rc; i++) {
if (el==allItems.getValueAt(i, 0)) {
allItems.setRowSelectionInterval(i, i);
// focus the row
JViewport viewport = (JViewport) allItems.getParent();
// This rectangle is relative to the table where the
// northwest corner of cell (0,0) is always (0,0).
Rectangle rect = allItems.getCellRect(i, 0, true);
// The location of the viewport relative to the table
Point pt = viewport.getViewPosition();
// Translate the cell location so that it is relative
// to the view, assuming the northwest corner of the
// view is (0,0)
rect.setLocation(rect.x - pt.x, rect.y - pt.y);
// Scroll the area into view
viewport.scrollRectToVisible(rect);
return true;
}
}
}
} catch (Exception ex) {
}
return false;
}
public void setSelectedRow(int row) {
try {
allItems.setRowSelectionInterval(row, row);
adjustActions();
} catch (Exception e) {
}
}
public void addRow(XMLElement e) {
int rowpos = allItems.getRowCount();
DefaultTableModel dtm = (DefaultTableModel) allItems.getModel();
Vector v = getRow(e);
dtm.insertRow(rowpos, v);
}
public void removeRow(int row) {
DefaultTableModel dtm = (DefaultTableModel) allItems.getModel();
dtm.removeRow(row);
}
protected void moveItem(int upOrDown) {
newMovingElementPosition = movingElementPosition;
if (newMovingElementPosition == -1) {
return;
}
if (upOrDown == 0) {
newMovingElementPosition--;
} else {
newMovingElementPosition++;
}
moveItem();
}
protected void moveItem() {
changing = true;
XMLCollection owncol = (XMLCollection) getOwner();
int rowCnt = allItems.getRowCount();
if (movingElement == null || movingElementPosition == -1 || newMovingElementPosition == -1
|| newMovingElementPosition == movingElementPosition || (rowCnt - 1) < movingElementPosition
|| (rowCnt - 1) < newMovingElementPosition || !owncol.contains(movingElement)) {
changing = false;
return;
}
if (JaWEManager.getInstance().getJaWEController().canRepositionElement(owncol, movingElement)) {
XMLElement currentElementAtPosition = (XMLElement) allItems.getValueAt(newMovingElementPosition, 0);
int newpos = owncol.indexOf(currentElementAtPosition);
DefaultTableModel dtm = (DefaultTableModel) allItems.getModel();
Vector v = getRow(movingElement);
dtm.removeRow(movingElementPosition);
dtm.insertRow(newMovingElementPosition, v);
JaWEController jc = JaWEManager.getInstance().getJaWEController();
jc.startUndouableChange();
owncol.reposition(movingElement, newpos);
List toSelect = new ArrayList();
toSelect.add(movingElement);
jc.endUndouableChange(toSelect);
setSelectedRow(newMovingElementPosition);
movingElementPosition = newMovingElementPosition;
}
changing = false;
}
protected Action newElementAction = new AbstractAction(JaWEActions.NEW_ACTION) {
public void actionPerformed(ActionEvent ae) {
JaWEController jc = JaWEManager.getInstance().getJaWEController();
XMLCollection col = (XMLCollection) getOwner();
XMLElement newEl = JaWEManager.getInstance().getXPDLObjectFactory().createXPDLObject(col, null, false);
// CUSTOM: always show modal dialog
boolean isForModal=true; //PanelUtilities.isForModalDialog(newEl);
// END CUSTOM
if (!isForModal && ipc.isModified()) {
int sw=ipc.showModifiedWarning();
if( sw == JOptionPane.CANCEL_OPTION || (sw==JOptionPane.YES_OPTION && ipc.isModified())) {
return;
}
}
boolean updInProg=false;
if (isForModal) {
StandardXPDLElementEditor ed = new StandardXPDLElementEditor();
ed.editXPDLElement(newEl);
boolean statOK=(ed.getStatus()==StandardXPDLElementEditor.STATUS_OK);
boolean canIns=true;
if (statOK) {
canIns=jc.canInsertElement(col, newEl);
}
if (!statOK || !canIns) {
if (!canIns) {
jc.getJaWEFrame().message(ed.getLanguageDependentString("WarningCannotInsertElement"),JOptionPane.WARNING_MESSAGE);
}
return;
}
updInProg=true;
}
jc.startUndouableChange();
col.add(newEl);
List temp = new ArrayList();
temp.add(newEl);
jc.endUndouableChange(temp);
if (updInProg) {
setSelectedElement(newEl);
}
adjustActions();
}
};
protected Action editElementAction = new AbstractAction(JaWEActions.EDIT_PROPERTIES_ACTION) {
public void actionPerformed(ActionEvent ae) {
XMLElement editElement = getSelectedElement();
if (editElement != null) {
if (ipc.isModified()) {
int sw=ipc.showModifiedWarning();
if( sw == JOptionPane.CANCEL_OPTION || (sw==JOptionPane.YES_OPTION && ipc.isModified())) {
return;
}
}
// CUSTOM: show modal dialog
StandardXPDLElementEditor ed = new StandardXPDLElementEditor();
ed.editXPDLElement(editElement);
XMLCollection col = (XMLCollection) getOwner();
int idx = col.indexOf(editElement);
col.remove(editElement);
col.add(editElement);
if (idx >= 0) {
col.reposition(editElement, idx);
}
//JaWEManager.getInstance().getXPDLElementEditor().editXPDLElement(editElement);
// END CUSTOM
}
}
};
protected Action deleteElementAction = new AbstractAction(JaWEActions.DELETE_ACTION) {
public void actionPerformed(ActionEvent ae) {
XMLElement deleteElement = getSelectedElement();
if (deleteElement != null) {
JaWEController jc = JaWEManager.getInstance().getJaWEController();
List sel=new ArrayList();
sel.add(deleteElement.getParent());
if (jc.confirmDelete(sel, deleteElement)) {
XMLCollection parent = (XMLCollection)getOwner();
jc.startUndouableChange();
parent.remove(deleteElement);
jc.endUndouableChange(sel);
ipc.getPanelSettings().adjustActions();
adjustActions();
}
}
}
};
protected Action moveUpAction = new AbstractAction("MoveUp") {
public void actionPerformed(ActionEvent ae) {
moveItem(0);
adjustActions();
}
};
protected Action moveDownAction = new AbstractAction("MoveDown") {
public void actionPerformed(ActionEvent ae) {
moveItem(1);
adjustActions();
}
};
protected Vector getColumnNames(List columnsToShow) {
// creating a table which do not allow cell editing
Vector cnames = new Vector();
cnames.add("Object");
XMLElement cel = ((XMLCollection) getOwner()).generateNewElement();
if (cel instanceof XMLComplexElement) {
Iterator it = columnsToShow.iterator();
while (it.hasNext()) {
String elemName = (String) it.next();
XMLElement el = ((XMLComplexElement) cel).get(elemName);
if (el != null) {
cnames.add(JaWEManager.getInstance().getLabelGenerator().getLabel(el));
} else {
it.remove();
}
}
} else {
cnames.add(JaWEManager.getInstance().getLabelGenerator().getLabel(cel));
}
return cnames;
}
protected JTable createTable(final boolean colors) {
JTable t=new BasicSortingTable(this, new Vector(), columnNames) {
public boolean isCellEditable(int row, int col) {
return false;
}
// This table colors elements depending on their owner
public Component prepareRenderer(TableCellRenderer renderer, int rowIndex, int vColIndex) {
Component c = super.prepareRenderer(renderer, rowIndex, vColIndex);
if (!isCellSelected(rowIndex, vColIndex) && colors) {
XMLElement el = (XMLElement) getValueAt(rowIndex, 0);
if (el instanceof XMLCollectionElement) {
XMLCollectionElement cel = (XMLCollectionElement) el;
XMLCollection celOwner = (XMLCollection) cel.getParent();
if (celOwner == null) {
c.setBackground(SPEC_EL_COLOR_BKG);
} else if (celOwner!=getOwner()) {
c.setBackground(FOREIGN_EL_COLOR_BKG);
} else {
c.setBackground(getBackground());
}
} else {
c.setBackground(getBackground());
}
}
return c;
}
};
Color bkgCol=new Color(245,245,245);
if (ipc.getSettings() instanceof PanelSettings) {
bkgCol=((PanelSettings)ipc.getSettings()).getBackgroundColor();
}
t.setBackground(bkgCol);
return t;
}
protected void setupTable(boolean miniDimension, boolean automaticWidth, final boolean showArrows) {
TableColumn column;
// setting the first column (object column) to be invisible
column = allItems.getColumnModel().getColumn(0);
column.setMinWidth(0);
column.setMaxWidth(0);
column.setPreferredWidth(0);
column.setResizable(false);
// setting fields that will not be displayed within the table
// setting some table properties
allItems.setColumnSelectionAllowed(false);
allItems.setRowSelectionAllowed(true);
allItems.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
allItems.getTableHeader().setReorderingAllowed(false);
Dimension tDim;
int noOfVisibleColumns = columnNames.size() - 1;
if (miniDimension) {
tDim = new Dimension(miniTableDimension);
} else if (noOfVisibleColumns <= 3) {
tDim = new Dimension(smallTableDimension);
} else if (noOfVisibleColumns <= 5) {
tDim = new Dimension(mediumTableDimension);
} else {
tDim = new Dimension(largeTableDimension);
}
if (automaticWidth) {
tDim.width = allItems.getPreferredScrollableViewportSize().width;
}
allItems.setPreferredScrollableViewportSize(new Dimension(tDim));
allItems.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), "edit");
allItems.getActionMap().put("edit", editElementAction);
allItems.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0, false), "delete");
allItems.getActionMap().put("delete", deleteElementAction);
final XMLCollection col = (XMLCollection) getOwner();
final boolean canRepos = JaWEManager.getInstance().getJaWEController().canRepositionElement(col, null);
if (!getOwner().isReadOnly())
allItems.setToolTipText(ResourceManager.getLanguageDependentString("MessageDragItemToChangeItsPosition"));
// mouse listener for editing on double-click
allItems.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
if (me.getClickCount() > 1) {
editElementAction.actionPerformed(null);
}
}
/** Marks the object which place within the table will be changed.*/
public void mousePressed(MouseEvent me) {
movingElement = null;
movingElementPosition = -1;
if (showArrows && !getOwner().isReadOnly() && canRepos) {
dragging = true;
}
try {
movingElementPosition = allItems.getSelectedRow();
if (movingElementPosition >= 0) {
movingElement = (XMLElement) allItems.getValueAt(movingElementPosition, 0);
adjustActions();
}
} catch (Exception ex) {
}
}
/** Just indicates that dragging is over.*/
public void mouseReleased(MouseEvent me) {
dragging = false;
}
});
/** Changes position of object within the list.*/
if (showArrows && !myOwner.isReadOnly() && canRepos) {// && ((XMLCollection)getOwner()).getParent().isReadOnly()))) {
ListSelectionModel rowSM = allItems.getSelectionModel();
rowSM.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent lse) {
if (dragging && !changing) {
newMovingElementPosition = -1;
try {
newMovingElementPosition = allItems.getSelectedRow();
} catch (Exception ex) {
}
moveItem();
}
adjustActions();
}
});
}
}
protected void fillTableContent(List elementsToShow) {
DefaultTableModel dtm = (DefaultTableModel) allItems.getModel();
Iterator it = elementsToShow.iterator();
while (it.hasNext()) {
XMLElement elem = (XMLElement) it.next();
Vector v = getRow(elem);
dtm.addRow(v);
}
}
protected Vector getRow(XMLElement elem) {
Vector v = new Vector();
if (elem instanceof XMLComplexElement) {
Iterator itAllElems = columnsToShow.iterator();
v = new Vector();
XMLComplexElement cmel=(XMLComplexElement) elem;
while (itAllElems.hasNext()) {
String elName=(String)itAllElems.next();
XMLElement el = cmel.get(elName);
if (el!=null) {
v.add(new XMLElementView(ipc,el, XMLElementView.TOVALUE));
}
}
} else {
v.add(new XMLElementView(ipc,elem, XMLElementView.TOVALUE));
}
v.add(0, elem);
return v;
}
protected JScrollPane createScrollPane() {
// creates panel
JScrollPane allItemsPane = new JScrollPane();
allItemsPane.setViewportView(allItems);
return allItemsPane;
}
protected JPanel createToolbar() {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
JButton buttonNew = PanelUtilities.createToolbarButton(ipc.getSettings(),newElementAction);
buttonNew.setRolloverEnabled(true);
JButton buttonEdit = PanelUtilities.createToolbarButton(ipc.getSettings(),editElementAction);
buttonEdit.setRolloverEnabled(true);
JButton buttonDelete = PanelUtilities.createToolbarButton(ipc.getSettings(), deleteElementAction);
buttonDelete.setRolloverEnabled(true);
panel.add(buttonNew);
panel.add(Box.createRigidArea(new Dimension(3, 3)));
panel.add(buttonEdit);
panel.add(Box.createRigidArea(new Dimension(3, 3)));
panel.add(buttonDelete);
panel.add(Box.createHorizontalGlue());
return panel;
}
protected JPanel createArrowPanel() {
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
JButton buttonUp = new JButton();
buttonUp.setIcon(ipc.getPanelSettings().getArrowUpImageIcon());
buttonUp.setPreferredSize(new Dimension(16, 16));
buttonUp.setEnabled(false);
buttonUp.addActionListener(moveUpAction);
moveUpAction.addPropertyChangeListener(new ButtonPropertyChangedListener(buttonUp));
JButton buttonDown = new JButton();
buttonDown.setIcon(ipc.getPanelSettings().getArrowDownImageIcon());
buttonDown.setPreferredSize(new Dimension(16, 16));
buttonDown.setEnabled(false);
buttonDown.addActionListener(moveDownAction);
moveDownAction.addPropertyChangeListener(new ButtonPropertyChangedListener(buttonDown));
p.add(buttonUp);
p.add(Box.createVerticalGlue());
p.add(buttonDown);
return p;
}
public void xmlElementChanged(XMLElementChangeInfo info) {
if (info.getAction() == XMLElementChangeInfo.REMOVED) {
Iterator it = info.getChangedSubElements().iterator();
while (it.hasNext()) {
XMLElement el = (XMLElement) it.next();
int row = getElementRow(el);
// System.out.println("Removing row " + row + " for element " + el);
if (row != -1) {
removeRow(row);
}
}
} else if (info.getAction() == XMLElementChangeInfo.INSERTED) {
Iterator it = info.getChangedSubElements().iterator();
while (it.hasNext()) {
XMLElement el = (XMLElement) it.next();
addRow(el);
}
}
}
protected int getElementRow(XMLElement el) {
int row = -1;
for (int i = 0; i < allItems.getRowCount(); i++) {
XMLElement toCompare = (XMLElement) allItems.getValueAt(i, 0);
if (el==toCompare) {
row = i;
break;
}
}
return row;
}
protected void adjustActions() {
JaWEController jc = JaWEManager.getInstance().getJaWEController();
XMLElement selEl=getSelectedElement();
newElementAction.setEnabled(jc.canCreateElement((XMLCollection) getOwner()));
editElementAction.setEnabled((selEl != null && XMLUtil.getPackage(selEl)!=null));
deleteElementAction.setEnabled((selEl != null && jc.canRemoveElement((XMLCollection)getOwner(), selEl)));
boolean canRepos = JaWEManager.getInstance().getJaWEController().canRepositionElement((XMLCollection) getOwner(),
null);
moveUpAction.setEnabled(selEl != null && allItems.getSelectedRow() > 0 && canRepos);
moveDownAction.setEnabled(selEl != null
&& allItems.getSelectedRow() < allItems.getModel().getRowCount() - 1 && canRepos);
}
public void cleanup () {
myOwner.removeListener(this);
}
}