/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo 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 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo 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 OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.components.tabular;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.util.Enumeration;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import org.openflexo.components.tabular.model.AbstractModel;
import org.openflexo.components.tabular.model.ToggleIconColumn;
import org.openflexo.foundation.DataModification;
import org.openflexo.foundation.FlexoModelObject;
import org.openflexo.foundation.FlexoObservable;
import org.openflexo.foundation.GraphicalFlexoObserver;
import org.openflexo.inspector.InspectableObject;
import org.openflexo.localization.FlexoLocalization;
import org.openflexo.selection.SelectionListener;
import org.openflexo.selection.SelectionManager;
import org.openflexo.selection.SelectionSynchronizedComponent;
import org.openflexo.view.controller.FlexoController;
/**
* Tabular view representing an AbstractModel
*
* @author sguerin
*
*/
public abstract class TabularView extends JPanel implements TableModelListener, ListSelectionListener, SelectionSynchronizedComponent,
GraphicalFlexoObserver {
protected final class TableMouseListener extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e) {
Point p = e.getPoint();
int col = _table.columnAtPoint(p);
int row = _table.rowAtPoint(p);
if (col > -1 && col < _model.getColumnCount() && row > -1 && row < _model.getRowCount()) {
if (e.getClickCount() == 2) {
if (_model.isCellEditable(row, col)) {
if (logger.isLoggable(Level.FINE)) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Double-click detected in a editable cell. Do nothing !");
}
}
} else if (row > -1 && row < _model.getRowCount()) {
if (logger.isLoggable(Level.FINE)) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Double-click detected in a NON-editable cell. Select !");
}
}
FlexoModelObject selectMe = _model.elementAt(row);
if (_controller.moduleViewForObject(selectMe) != null) {
_controller.setCurrentEditedObjectAsModuleView(selectMe);
}
}
} else if (e.getClickCount() == 1) {
if (logger.isLoggable(Level.FINE)) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Simple-click detected !");
}
}
// FlexoModelObject selectMe = _model.elementAt(row);
// _focusedObject = selectMe;
// updateSlaveTabularViews();
if (_table.getEditingRow() > -1 && _table.getEditingRow() != row) {
if (logger.isLoggable(Level.INFO)) {
logger.info("Change row where edition was started, fire stop editing !");
}
TableCellEditor cellEditor = _model.columnAt(col).getCellEditor();
if (cellEditor != null) {
cellEditor.stopCellEditing();
e.consume();
}
}
if (!e.isConsumed()) {
if (_model.columnAt(col) instanceof ToggleIconColumn) {
ToggleIconColumn toggleIconColumn = (ToggleIconColumn) _model.columnAt(col);
toggleIconColumn.toogleValue(row);
}
}
}
} else {
if (_table.getEditingRow() > -1 && _table.getEditingRow() != row) {
if (logger.isLoggable(Level.INFO)) {
logger.info("Clicked outside the table, stop cell edition!");
}
if (_table.getCellEditor() != null) {
_table.getCellEditor().stopCellEditing();
}
e.consume();
}
}
}
@Override
public void mousePressed(MouseEvent e) {
super.mousePressed(e);
if (!e.isConsumed() && _controller.getSelectionManager() != null) {
_controller.getSelectionManager().getContextualMenuManager().processMousePressed(e);
}
}
@Override
public void mouseReleased(MouseEvent e) {
super.mouseReleased(e);
if (!e.isConsumed() && _controller.getSelectionManager() != null) {
_controller.getSelectionManager().getContextualMenuManager().processMouseReleased(e);
}
}
}
protected static final Logger logger = Logger.getLogger(TabularView.class.getPackage().getName());
protected FlexoController _controller;
protected JTable _table;
protected AbstractModel _model;
protected ListSelectionModel _listSelectionModel;
protected Vector<TabularView> _slaveTabularViews;
protected TabularView _masterTabularView;
private JScrollPane scrollPane;
protected Vector<FlexoModelObject> _selectedObjects;
protected boolean _selectedObjectsNeedsRecomputing;
protected boolean selectionHasChanged = false;
private SelectionListener temporarySelectionListener = new SelectionListener() {
@Override
public void fireBeginMultipleSelection() {
}
@Override
public void fireEndMultipleSelection() {
}
@Override
public void fireObjectDeselected(FlexoModelObject object) {
selectionHasChanged = true;
}
@Override
public void fireObjectSelected(FlexoModelObject object) {
selectionHasChanged = true;
}
@Override
public void fireResetSelection() {
selectionHasChanged = true;
}
};
public TabularView(FlexoController controller, AbstractModel model, int visibleRowCount) {
this(controller, model);
setVisibleRowCount(visibleRowCount);
}
public TabularView(FlexoController controller, AbstractModel model) {
super();
_model = model;
_controller = controller;
_slaveTabularViews = new Vector<TabularView>();
if (model != null) {
model.addTableModelListener(this);
if (model.getModel() != null) {
model.getModel().addObserver(this);
}
model.fireTableDataChanged();
}
_table = new FlexoJTable(model);
_table.getTableHeader().setReorderingAllowed(false);
// _table.setPreferredSize(new Dimension(model.getTotalPreferredWidth(),100));
_table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
_selectedObjects = new Vector<FlexoModelObject>();
_selectedObjectsNeedsRecomputing = false;
// _table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
initColumnModel();
/*for (int i = 0; i < model.getColumnCount(); i++) {
TableColumn col = _table.getColumnModel().getColumn(i);
col.setPreferredWidth(model.getDefaultColumnSize(i));
if (model.getColumnResizable(i)) {
col.setResizable(true);
} else {
// L'idee, c'est d'etre vraiment sur ;-) !
col.setWidth(model.getDefaultColumnSize(i));
col.setMinWidth(model.getDefaultColumnSize(i));
col.setMaxWidth(model.getDefaultColumnSize(i));
col.setResizable(false);
}
if (model.columnAt(i).requireCellRenderer()) {
col.setCellRenderer(model.columnAt(i).getCellRenderer());
}
if (model.columnAt(i).requireCellEditor()) {
col.setCellEditor(model.columnAt(i).getCellEditor());
}
}*/
if (model.getRowHeight() > 0) {
_table.setRowHeight(model.getRowHeight());
}
_table.setShowVerticalLines(true);
_table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
_listSelectionModel = _table.getSelectionModel();
_listSelectionModel.addListSelectionListener(this);
scrollPane = new JScrollPane(_table);
setLayout(new BorderLayout());
add(_table.getTableHeader(), BorderLayout.NORTH);
add(scrollPane, BorderLayout.CENTER);
TableMouseListener tableMouseListener = new TableMouseListener();
_table.addMouseListener(tableMouseListener);
scrollPane.getViewport().addMouseListener(tableMouseListener);
_table.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
super.mouseMoved(e);
if (!e.isConsumed() && _controller.getSelectionManager() != null) {
_controller.getSelectionManager().getContextualMenuManager().processMouseMoved(e);
}
}
});
validate();
}
private void initColumnModel() {
if (logger.isLoggable(Level.FINE)) {
logger.fine("initColumnModel() with " + _model.getColumnCount() + " columns");
}
for (int i = 0; i < _model.getColumnCount(); i++) {
TableColumn col = _table.getColumnModel().getColumn(i);
FlexoLocalization.localizedForKey(getModel().columnAt(i).getTitle(), col);
col.setPreferredWidth(_model.getDefaultColumnSize(i));
if (_model.getColumnResizable(i)) {
col.setResizable(true);
} else {
// L'idee, c'est d'etre vraiment sur ;-) !
col.setWidth(_model.getDefaultColumnSize(i));
col.setMinWidth(_model.getDefaultColumnSize(i));
col.setMaxWidth(_model.getDefaultColumnSize(i));
col.setResizable(false);
}
if (_model.columnAt(i).requireCellRenderer()) {
col.setCellRenderer(_model.columnAt(i).getCellRenderer());
}
if (_model.columnAt(i).requireCellEditor()) {
col.setCellEditor(_model.columnAt(i).getCellEditor());
}
}
}
public AbstractModel getModel() {
return _model;
}
public void setVisibleRowCount(int rows) {
int height = 0;
for (int row = 0; row < rows; row++) {
height += _table.getRowHeight(row);
}
_table.setPreferredScrollableViewportSize(new Dimension(_table.getPreferredScrollableViewportSize().width, height));
}
@Override
public void valueChanged(ListSelectionEvent e) {
// Ignore extra messages.
if (e.getValueIsAdjusting()) {
return;
}
if (logger.isLoggable(Level.FINE)) {
logger.fine("valueChanged() ListSelectionEvent=" + e + " ListSelectionModel=" + _listSelectionModel.toString());
}
_selectedObjectsNeedsRecomputing = true;
/* At least one of this item has change */
int beginIndex = e.getFirstIndex();
int endIndex = e.getLastIndex();
Vector<FlexoModelObject> toBeRemovedFromSelection = new Vector<FlexoModelObject>();
Vector<FlexoModelObject> toBeAddedToSelection = new Vector<FlexoModelObject>();
// First remove all selected object that cannot be represented on this view
/*if (getSelectionManager() != null) {
for (Enumeration en=getSelectionManager().getSelection().elements(); en.hasMoreElements();) {
FlexoModelObject next = (FlexoModelObject)en.nextElement();
if (!mayRepresents(next)) {
toBeRemovedFromSelection.add(next);
if (logger.isLoggable(Level.FINE)) logger.fine("Mark "+next+" for deletion ");
}
}
}
*/
for (int i = beginIndex; i <= endIndex; i++) {
if (_listSelectionModel.isSelectedIndex(i) != _controller.getSelectionManager().selectionContains(_model.elementAt(i))) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Selection status for object " + _model.elementAt(i) + " at index " + i + " has changed");
}
if (_listSelectionModel.isSelectedIndex(i)) {
// Change for addition
toBeAddedToSelection.add(_model.elementAt(i));
} else {
// Change for removing
toBeRemovedFromSelection.add(_model.elementAt(i));
}
}
}
/*for (Enumeration en=toBeAddedToSelection.elements(); en.hasMoreElements();) {
FlexoModelObject next = (FlexoModelObject)en.nextElement();
getSelectionManager().addToSelected(next);
}*/
fireBeginMultipleSelection();
getSelectionManager().addToSelected(toBeAddedToSelection);
fireEndMultipleSelection();
/*
for (Enumeration en=toBeRemovedFromSelection.elements(); en.hasMoreElements();) {
FlexoModelObject next = (FlexoModelObject)en.nextElement();
getSelectionManager().removeFromSelected(next);
}
*/
updateSlaveTabularViews();
if (getSelectionManager() != null) {
for (Enumeration en = getSelectionManager().getSelection().elements(); en.hasMoreElements();) {
FlexoModelObject next = (FlexoModelObject) en.nextElement();
if (!mayRepresents(next)) {
toBeRemovedFromSelection.add(next);
if (logger.isLoggable(Level.FINE)) {
logger.fine("Mark " + next + " for deletion ");
}
}
}
}
getSelectionManager().removeFromSelected(toBeRemovedFromSelection);
}
private void updateSlaveTabularViews() {
Vector<FlexoModelObject> currentSelection = getSelectedObjects();
if (logger.isLoggable(Level.FINE)) {
logger.fine("udpateSlaveTabularViews");
}
if (logger.isLoggable(Level.FINE)) {
logger.fine("Current selection: " + currentSelection);
}
if (currentSelection.size() == 1) {
setModelInSlaveTabularViews(currentSelection.firstElement());
} else {
setModelInSlaveTabularViews(null);
}
}
private void setModelInSlaveTabularViews(FlexoModelObject newModel) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("setModelInDrivenTableViews with " + newModel);
}
if (_slaveTabularViews != null) {
for (Enumeration<TabularView> en = _slaveTabularViews.elements(); en.hasMoreElements();) {
TabularView next = en.nextElement();
next.setModelObject(newModel);
}
}
}
private void setModelObject(FlexoModelObject newModel) {
if (_table.isEditing() && _table.getCellEditor() != null && getModel().getModel() != null && getModel().getModel() != newModel
&& newModel != null) {
_table.getCellEditor().stopCellEditing();
}
_listSelectionModel.removeListSelectionListener(this);
getModel().setModel(newModel);
_listSelectionModel.addListSelectionListener(this);
_selectedObjectsNeedsRecomputing = true;
}
public Vector<FlexoModelObject> getSelectedObjects() {
if (_selectedObjectsNeedsRecomputing) {
_selectedObjects.clear();
for (int i = 0; i < _model.getRowCount(); i++) {
if (_listSelectionModel.isSelectedIndex(i)) {
_selectedObjects.add(_model.elementAt(i));
}
}
_selectedObjectsNeedsRecomputing = false;
}
return _selectedObjects;
}
public boolean isSelected(Vector<FlexoModelObject> objectList) {
return getSelectedObjects().containsAll(objectList);
}
public boolean isSelected(FlexoModelObject object) {
return getSelectedObjects().contains(object);
}
public void selectObject(FlexoModelObject object) {
resetSelection();
// Calling addToSelected does not always work
if (getSelectionManager() != null) {
getSelectionManager().addToSelected(object);
}
}
public Vector getObjects() {
return getSelectedObjects();
}
public FlexoModelObject getObject() {
return _model.getModel();
}
public Vector<TabularView> getSlaveTabularViews() {
return _slaveTabularViews;
}
public void addToSlaveTabularViews(TabularView tabularView) {
_slaveTabularViews.add(tabularView);
tabularView.setMasterTabularView(this);
}
public void removeFromSlaveTabularViews(TabularView tabularView) {
_slaveTabularViews.remove(tabularView);
tabularView.setMasterTabularView(null);
}
public TabularView getMasterTabularView() {
return _masterTabularView;
}
public void setMasterTabularView(TabularView tabularView) {
_masterTabularView = tabularView;
}
/**
* Implements
*
* @see org.openflexo.view.InspectableObjectView#getInspectedObject()
* @see org.openflexo.view.InspectableObjectView#getInspectedObject()
*/
public InspectableObject getInspectedObject() {
if (_model.getModel() instanceof InspectableObject) {
return (InspectableObject) _model.getModel();
}
return null;
}
/**
* Implements
*
* @see org.openflexo.view.MultipleInspectableObjectView#getInspectedObjects()
* @see org.openflexo.view.MultipleInspectableObjectView#getInspectedObjects()
*/
public Vector getInspectedObjects() {
return getObjects();
}
protected boolean refreshRequested = false;
protected void refreshNow() {
// Before updating the content of the table, we make a copy of the current selection
Vector<FlexoModelObject> v = (Vector<FlexoModelObject>) _controller.getSelectionManager().getSelection().clone();
selectionHasChanged = false;
_controller.getSelectionManager().addToSelectionListeners(temporarySelectionListener);
_model.fireTableDataChanged();
// After updating the content of the table, we set the selection back to its previous state (content has change but not the
// selection)
_controller.getSelectionManager().removeFromSelectionListeners(temporarySelectionListener);
if (selectionHasChanged) {
_controller.getSelectionManager().setSelectedObjects(v);// Note that deleted objects are automatically ignored by the SM
}
refreshRequested = false;
}
/**
* Overrides
*
* @see org.openflexo.foundation.FlexoObserver#update(org.openflexo.foundation.FlexoObservable,
* org.openflexo.foundation.DataModification)
* @see org.openflexo.foundation.FlexoObserver#update(org.openflexo.foundation.FlexoObservable,
* org.openflexo.foundation.DataModification)
*/
@Override
public void update(FlexoObservable o, DataModification dataModification) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("update received in TabularView for " + o + " dataModification=" + dataModification);
}
synchronized (this) {
if (refreshRequested) {
return;
}
refreshRequested = true;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
refreshNow();
} finally {
refreshRequested = false;
}
}
});
}
}
/**
* Overrides
*
* @see javax.swing.event.TableModelListener#tableChanged(javax.swing.event.TableModelEvent)
* @see javax.swing.event.TableModelListener#tableChanged(javax.swing.event.TableModelEvent)
*/
@Override
public void tableChanged(TableModelEvent e) {
if (e instanceof AbstractModel.ModelObjectHasChanged) {
AbstractModel.ModelObjectHasChanged event = (AbstractModel.ModelObjectHasChanged) e;
if (logger.isLoggable(Level.FINE)) {
logger.fine("Model has changed from " + event.getOldModel() + " to " + event.getNewModel());
}
if (event.getOldModel() != null) {
event.getOldModel().deleteObserver(this);
}
if (event.getNewModel() != null) {
event.getNewModel().addObserver(this);
}
} else if (e instanceof AbstractModel.SelectObjectEvent) {
AbstractModel.SelectObjectEvent event = (AbstractModel.SelectObjectEvent) e;
selectObject(event.getSelectedObject());
} else if (e instanceof AbstractModel.RowMoveForObjectEvent) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Reselect object, and then the edited cell");
}
AbstractModel.RowMoveForObjectEvent event = (AbstractModel.RowMoveForObjectEvent) e;
selectObject(event.getEditedObject());
_table.setEditingColumn(event.getColumn());
_table.setEditingRow(event.getNewRow());
} else if (e instanceof AbstractModel.TableStructureHasChanged) {
_table.setModel(_model);
_table.createDefaultColumnsFromModel();
initColumnModel();
}
}
@Override
public SelectionManager getSelectionManager() {
return _controller.getSelectionManager();
}
@Override
public Vector<FlexoModelObject> getSelection() {
if (getSelectionManager() != null) {
return getSelectionManager().getSelection();
}
return null;
}
@Override
public void resetSelection() {
if (getSelectionManager() != null) {
getSelectionManager().resetSelection();
} else {
fireResetSelection();
}
}
@Override
public void addToSelected(FlexoModelObject object) {
if (mayRepresents(object)) {
if (getSelectionManager() != null) {
getSelectionManager().addToSelected(object);
} else {
fireObjectSelected(object);
}
}
}
@Override
public void removeFromSelected(FlexoModelObject object) {
if (mayRepresents(object)) {
if (getSelectionManager() != null) {
getSelectionManager().removeFromSelected(object);
} else {
fireObjectDeselected(object);
}
}
}
@Override
public void addToSelected(Vector<? extends FlexoModelObject> objects) {
if (getSelectionManager() != null) {
getSelectionManager().addToSelected(objects);
} else {
fireBeginMultipleSelection();
for (Enumeration en = objects.elements(); en.hasMoreElements();) {
FlexoModelObject next = (FlexoModelObject) en.nextElement();
fireObjectSelected(next);
}
fireEndMultipleSelection();
}
}
@Override
public void removeFromSelected(Vector<? extends FlexoModelObject> objects) {
if (getSelectionManager() != null) {
getSelectionManager().removeFromSelected(objects);
} else {
fireBeginMultipleSelection();
for (Enumeration en = objects.elements(); en.hasMoreElements();) {
FlexoModelObject next = (FlexoModelObject) en.nextElement();
fireObjectDeselected(next);
}
fireEndMultipleSelection();
}
}
@Override
public void setSelectedObjects(Vector<? extends FlexoModelObject> objects) {
if (getSelectionManager() != null) {
getSelectionManager().setSelectedObjects(objects);
} else {
resetSelection();
addToSelected(objects);
}
}
@Override
public boolean mayRepresents(FlexoModelObject anObject) {
boolean b = getModel().indexOf(anObject) > -1;
Enumeration<TabularView> en = _slaveTabularViews.elements();
while (en.hasMoreElements() && !b) {
TabularView v = en.nextElement();
b |= v.mayRepresents(anObject);
}
return b;
}
@Override
public FlexoModelObject getFocusedObject() {
if (getSelectionManager() != null) {
return getSelectionManager().getFocusedObject();
}
return null;
}
/**
* ATTENTION ICI: manipuler ce code avec precaution !!!
*/
@Override
public void fireObjectSelected(FlexoModelObject object) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("TabularView for " + getObject() + " fireObjectSelected() with " + object);
}
FlexoModelObject parent = getParentObject(object);
if (getMasterTabularView() != null && parent != null) {
// If master tabular view not null (means that is is a slave
// tabular view), and if current selection has no object selected
// in master view, then select object in master view
if (getMasterTabularView().getSelectedObjects().size() == 0) {
getMasterTabularView().fireObjectSelected(parent);
}
}
if (getModel().indexOf(object) > -1) {
if (isSelected(object) == false) {
// Change the selection status of b
int index = _model.indexOf(object);
_listSelectionModel.removeListSelectionListener(this);
_listSelectionModel.addSelectionInterval(index, index);
_listSelectionModel.addListSelectionListener(this);
_selectedObjectsNeedsRecomputing = true;
updateSlaveTabularViews();
}
}
}
/**
* ATTENTION ICI: manipuler ce code avec precaution !!!
*/
@Override
public void fireObjectDeselected(FlexoModelObject object) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("TabularView for " + getObject() + " fireObjectDeselected() with " + object);
}
FlexoModelObject parent = getParentObject(object);
if (getMasterTabularView() != null && parent != null) {
// If master tabular view not null (means that is is a slave
// tabular view), and if parent of deselected object is selected
// in parent view but not contained in selection, also deselect
// parent object from master view
if (getMasterTabularView().getSelectedObjects().contains(parent) && !getSelectionManager().selectionContains(parent)) {
getMasterTabularView().fireObjectDeselected(parent);
}
}
if (mayRepresents(object)) {
if (isSelected(object) == true) {
// Change the selection status of b
int index = _model.indexOf(object);
_listSelectionModel.removeListSelectionListener(this);
_listSelectionModel.removeSelectionInterval(index, index);
_listSelectionModel.addListSelectionListener(this);
_selectedObjectsNeedsRecomputing = true;
updateSlaveTabularViews();
}
}
if (getSlaveTabularViews().size() > 0 && getSelectedObjects().size() == 0) {
// If this view is a master view that have slave views
// and if current selection is now empty, we might check
// if some slave views needs this master view to be set
for (Enumeration en = getSlaveTabularViews().elements(); en.hasMoreElements();) {
TabularView next = (TabularView) en.nextElement();
next.updateSelection();
}
}
}
protected abstract FlexoModelObject getParentObject(FlexoModelObject object);
@Override
public void fireResetSelection() {
_selectedObjectsNeedsRecomputing = true;
_listSelectionModel.removeListSelectionListener(this);
_listSelectionModel.clearSelection();
_listSelectionModel.addListSelectionListener(this);
}
@Override
public void fireBeginMultipleSelection() {
}
@Override
public void fireEndMultipleSelection() {
}
/**
* Update selection
*/
public void updateSelection() {
if (getSelectionManager() != null) {
getSelectionManager().fireUpdateSelection(this);
}
}
public void editCellAt(int col, int row) {
if (_table != null) {
_table.editCellAt(row, col);
}
}
}