* [ 1821870 ] Add column visibility control to grid
This commit is contained in:
parent
e33b46da0d
commit
7b15ae945d
|
@ -3,5 +3,6 @@
|
|||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="lib" path="/tools/lib/looks-2.0.4.jar"/>
|
||||
<classpathentry kind="lib" path="/tools/lib/swingx-0.9.0.jar"/>
|
||||
<classpathentry kind="output" path="build"/>
|
||||
</classpath>
|
||||
|
|
|
@ -0,0 +1,857 @@
|
|||
/******************************************************************************
|
||||
* Product: Adempiere ERP & CRM Smart Business Solution *
|
||||
* Copyright (C) 2007 Adempiere, Inc. All Rights Reserved. *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. This program 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 this program; if not, write to the Free Software Foundation, Inc., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
*****************************************************************************/
|
||||
package org.compiere.swing;
|
||||
|
||||
import org.jdesktop.swingx.VerticalLayout;
|
||||
import org.jdesktop.swingx.action.AbstractActionExt;
|
||||
import org.jdesktop.swingx.action.ActionContainerFactory;
|
||||
import org.jdesktop.swingx.table.ColumnControlPopup;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.TableColumnModelEvent;
|
||||
import javax.swing.event.TableColumnModelListener;
|
||||
import javax.swing.table.TableColumn;
|
||||
import javax.swing.table.TableColumnModel;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Code and description adapted from SwingX ColumnControlButton class.
|
||||
*
|
||||
* A component to allow interactive customization of <code>CTable</code>'s
|
||||
* columns.
|
||||
* It's main purpose is to allow toggling of table columns' visibility.
|
||||
* Additionally, arbitrary configuration actions can be exposed.
|
||||
* <p>
|
||||
*
|
||||
* This component is installed in the <code>CTable</code>'s
|
||||
* trailing corner, if enabled:
|
||||
*
|
||||
* <pre><code>
|
||||
* table.setColumnControlVisible(true);
|
||||
* </code></pre>
|
||||
*
|
||||
* From the perspective of a <code>CTable</code>, the component's behaviour is
|
||||
* opaque. Typically, the button's action is to popup a component for user
|
||||
* interaction. <p>
|
||||
*
|
||||
* This class is responsible for handling/providing/updating the lists of
|
||||
* actions and to keep all action's state in synch with Table-/Column state.
|
||||
* The visible behaviour of the popup is delegated to a
|
||||
* <code>ColumnControlPopup</code>. <p>
|
||||
*
|
||||
* @see CTable#setColumnControl
|
||||
*
|
||||
*/
|
||||
public class CColumnControlButton extends JButton {
|
||||
/** Marker to auto-recognize actions which should be added to the popup. */
|
||||
public static final String COLUMN_CONTROL_MARKER = "column.";
|
||||
/** exposed for testing. */
|
||||
protected ColumnControlPopup popup;
|
||||
// TODO: the table reference is a potential leak?
|
||||
/** The table which is controlled by this. */
|
||||
private CTable table;
|
||||
/** Listener for table property changes. */
|
||||
private PropertyChangeListener tablePropertyChangeListener;
|
||||
/** Listener for table's columnModel. */
|
||||
TableColumnModelListener columnModelListener;
|
||||
/** the list of actions for column menuitems.*/
|
||||
private List<ColumnVisibilityAction> columnVisibilityActions;
|
||||
|
||||
/**
|
||||
* Creates a column control button for the table. The button
|
||||
* uses the given icon and has no text.
|
||||
* @param table the <code>JTable</code> controlled by this component
|
||||
* @param icon the <code>Icon</code> to show
|
||||
*/
|
||||
public CColumnControlButton(CTable table, Icon icon) {
|
||||
super();
|
||||
init();
|
||||
// JW: icon LF dependent?
|
||||
setAction(createControlAction(icon));
|
||||
installTable(table);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateUI() {
|
||||
super.updateUI();
|
||||
// JW: icon LF dependent?
|
||||
setMargin(new Insets(1, 2, 2, 1)); // Make this LAF-independent
|
||||
getColumnControlPopup().updateUI();
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the popup component's visibility. This method is
|
||||
* called by this control's default action. <p>
|
||||
*
|
||||
* Here: delegates to getControlPopup().
|
||||
*/
|
||||
public void togglePopup() {
|
||||
getColumnControlPopup().toggleVisibility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyComponentOrientation(ComponentOrientation o) {
|
||||
super.applyComponentOrientation(o);
|
||||
getColumnControlPopup().applyComponentOrientation(o);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------- Action in synch with column properties
|
||||
/**
|
||||
* A specialized <code>Action</code> which takes care of keeping in synch with
|
||||
* TableColumn state.
|
||||
*
|
||||
* NOTE: client must call releaseColumn if this action is no longer needed!
|
||||
*
|
||||
*/
|
||||
public class ColumnVisibilityAction extends AbstractActionExt {
|
||||
|
||||
private TableColumn column;
|
||||
|
||||
private PropertyChangeListener columnListener;
|
||||
|
||||
/** flag to distinguish selection changes triggered by
|
||||
* column's property change from those triggered by
|
||||
* user interaction. Hack around #212-swingx.
|
||||
*/
|
||||
private boolean fromColumn;
|
||||
|
||||
/**
|
||||
* Creates a action synched to the table column.
|
||||
*
|
||||
* @param column the <code>TableColumn</code> to keep synched to.
|
||||
*/
|
||||
public ColumnVisibilityAction(TableColumn column) {
|
||||
super((String) null);
|
||||
setStateAction();
|
||||
installColumn(column);
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases all references to the synched <code>TableColumn</code>.
|
||||
* Client code must call this method if the
|
||||
* action is no longer needed. After calling this action must not be
|
||||
* used any longer.
|
||||
*/
|
||||
public void releaseColumn() {
|
||||
column.removePropertyChangeListener(columnListener);
|
||||
column = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void itemStateChanged(final ItemEvent e) {
|
||||
if ((e.getStateChange() == ItemEvent.DESELECTED)
|
||||
//JW: guarding against 1 leads to #212-swingx: setting
|
||||
// column visibility programatically fails if
|
||||
// the current column is the second last visible
|
||||
// guarding against 0 leads to hiding all columns
|
||||
// by deselecting the menu item.
|
||||
&& (table.getColumnCount() <= 1)
|
||||
// JW Fixed #212: basically implemented Rob's idea to distinguish
|
||||
// event sources instead of unconditionally reselect
|
||||
// not entirely sure if the state transitions are completely
|
||||
// defined but all related tests are passing now.
|
||||
&& !fromColumn) {
|
||||
reselect();
|
||||
} else {
|
||||
setSelected(e.getStateChange() == ItemEvent.SELECTED);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public synchronized void setSelected(boolean newValue) {
|
||||
super.setSelected(newValue);
|
||||
if (!newValue) {
|
||||
if (table.isColumnVisible(column)) {
|
||||
table.setColumnVisibility(column, newValue);
|
||||
}
|
||||
} else {
|
||||
if (!table.isColumnVisible(column)) {
|
||||
table.setColumnVisibility(column, newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does nothing. Synch from action state to TableColumn state
|
||||
* is done in itemStateChanged.
|
||||
*/
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchs selected property to visible. This
|
||||
* is called on change of tablecolumn's <code>visible</code> property.
|
||||
*
|
||||
* @param visible column visible state to synch to.
|
||||
*/
|
||||
private void updateFromColumnVisible(boolean visible) {
|
||||
fromColumn = true;
|
||||
setSelected(visible);
|
||||
fromColumn = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchs name property to value. This is called on change of
|
||||
* tableColumn's <code>headerValue</code> property.
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
private void updateFromColumnHeader(Object value) {
|
||||
if (value == null) {
|
||||
this.setEnabled(false);
|
||||
} else {
|
||||
setName(String.valueOf(value));
|
||||
this.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enforces selected to <code>true</code>. Called if user interaction
|
||||
* tried to de-select the last single visible column.
|
||||
*
|
||||
*/
|
||||
private void reselect() {
|
||||
firePropertyChange("selected", null, Boolean.TRUE);
|
||||
}
|
||||
|
||||
// -------------- init
|
||||
private void installColumn(TableColumn column) {
|
||||
this.column = column;
|
||||
column.addPropertyChangeListener(getColumnListener());
|
||||
updateFromColumnHeader(column.getHeaderValue());
|
||||
// #429-swing: actionCommand must be string
|
||||
if (column.getIdentifier() != null) {
|
||||
setActionCommand(column.getIdentifier().toString());
|
||||
}
|
||||
boolean visible = table.isColumnVisible(column);
|
||||
updateFromColumnVisible(visible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the listener to column's property changes. The listener
|
||||
* is created lazily if necessary.
|
||||
*
|
||||
* @return the <code>PropertyChangeListener</code> listening to
|
||||
* <code>TableColumn</code>'s property changes, guaranteed to be
|
||||
* not <code>null</code>.
|
||||
*/
|
||||
protected PropertyChangeListener getColumnListener() {
|
||||
if (columnListener == null) {
|
||||
columnListener = createPropertyChangeListener();
|
||||
}
|
||||
return columnListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns the listener to column's property changes.
|
||||
* Subclasses are free to roll their own.
|
||||
* <p>
|
||||
* Implementation note: this listener reacts to column's
|
||||
* <code>visible</code> and <code>headerValue</code> properties and
|
||||
* calls the respective <code>updateFromXX</code> methodes.
|
||||
*
|
||||
* @return the <code>PropertyChangeListener</code> to use with the
|
||||
* column
|
||||
*/
|
||||
protected PropertyChangeListener createPropertyChangeListener() {
|
||||
return new PropertyChangeListener() {
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if ("visible".equals(evt.getPropertyName())) {
|
||||
updateFromColumnVisible((Boolean) evt.getNewValue());
|
||||
} else if ("headerValue".equals(evt.getPropertyName())) {
|
||||
updateFromColumnHeader(evt.getNewValue());
|
||||
if (evt.getNewValue() == null)
|
||||
populatePopup();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------- the popup
|
||||
|
||||
/**
|
||||
* A default implementation of ColumnControlPopup.
|
||||
* It uses a JPopupMenu with
|
||||
* MenuItems corresponding to the Actions as
|
||||
* provided by the ColumnControlButton.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class DefaultColumnControlPopup implements ColumnControlPopup {
|
||||
private JPopupMenu popupMenu;
|
||||
private JScrollPane scroller;
|
||||
private JPanel panelMenus;
|
||||
|
||||
//------------------ public methods to control visibility status
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
*/
|
||||
public void updateUI() {
|
||||
SwingUtilities.updateComponentTreeUI(getPopupMenu());
|
||||
}
|
||||
|
||||
private JPanel getPanelMenu() {
|
||||
if (panelMenus == null) {
|
||||
panelMenus = new JPanel();
|
||||
panelMenus.setLayout(new VerticalLayout());
|
||||
panelMenus.setBackground(UIManager.getColor("MenuItem.background"));
|
||||
panelMenus.setBorder(BorderFactory.createEmptyBorder());
|
||||
}
|
||||
return panelMenus;
|
||||
}
|
||||
|
||||
private JScrollPane getScroller() {
|
||||
if (scroller == null) {
|
||||
scroller = createScroller();
|
||||
scroller.getVerticalScrollBar().setFocusable( false );
|
||||
scroller.setViewportView(getPanelMenu());
|
||||
}
|
||||
return scroller;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
*/
|
||||
public void toggleVisibility(JComponent owner) {
|
||||
JPopupMenu popupMenu = getPopupMenu();
|
||||
JPanel panel = getPanelMenu();
|
||||
if (popupMenu.isVisible()) {
|
||||
popupMenu.setVisible(false);
|
||||
} else if (panel.getComponentCount() > 0) {
|
||||
JScrollPane scroller = getScroller();
|
||||
panel.validate();
|
||||
|
||||
Dimension pSize = table.getParent().getSize();
|
||||
Dimension size = panel.getPreferredSize();
|
||||
if (size.height >= pSize.height) {
|
||||
scroller.setPreferredSize(new Dimension(size.width, pSize.height - 30));
|
||||
} else {
|
||||
scroller.setPreferredSize(size);
|
||||
}
|
||||
popupMenu.setPopupSize(new Dimension(scroller.getPreferredSize().width + 20,
|
||||
scroller.getPreferredSize().height - 20));
|
||||
|
||||
Dimension buttonSize = owner.getSize();
|
||||
int xPos = owner.getComponentOrientation().isLeftToRight() ? buttonSize.width
|
||||
- popupMenu.getPreferredSize().width
|
||||
: 0;
|
||||
|
||||
popupMenu.show(owner,
|
||||
xPos, buttonSize.height);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
*/
|
||||
public void applyComponentOrientation(ComponentOrientation o) {
|
||||
getPopupMenu().applyComponentOrientation(o);
|
||||
|
||||
}
|
||||
|
||||
//-------------------- public methods to manipulate popup contents.
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
*/
|
||||
public void removeAll() {
|
||||
getPanelMenu().removeAll();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
*/
|
||||
public void addVisibilityActionItems(
|
||||
List<? extends AbstractActionExt> actions) {
|
||||
addItems(new ArrayList<Action>(actions));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
*/
|
||||
public void addAdditionalActionItems(List<? extends Action> actions) {
|
||||
if (actions.size() == 0)
|
||||
return;
|
||||
addSeparator();
|
||||
addItems(actions);
|
||||
}
|
||||
|
||||
//--------------------------- internal helpers to manipulate popups content
|
||||
|
||||
/**
|
||||
* Here: creates and adds a menuItem to the popup for every
|
||||
* Action in the list. Does nothing if
|
||||
* if the list is empty.
|
||||
*
|
||||
* PRE: actions != null.
|
||||
*
|
||||
* @param actions a list containing the actions to add to the popup.
|
||||
* Must not be null.
|
||||
*
|
||||
*/
|
||||
protected void addItems(List<? extends Action> actions) {
|
||||
ActionContainerFactory factory = new ActionContainerFactory(null);
|
||||
for (Action action : actions) {
|
||||
AbstractActionExt a = (AbstractActionExt)action;
|
||||
if (action.isEnabled()) {
|
||||
if (a.isStateAction())
|
||||
addItem(createCheckBox((AbstractActionExt)action));
|
||||
else {
|
||||
addItem(factory.createButton(action));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private JCheckBox createCheckBox(AbstractActionExt action) {
|
||||
JCheckBox c = new JCheckBox(action);
|
||||
c.setSelected(action.isSelected());
|
||||
c.addItemListener(action);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* adds a separator to the popup.
|
||||
*
|
||||
*/
|
||||
protected void addSeparator() {
|
||||
getPanelMenu().add(Box.createVerticalStrut(2));
|
||||
getPanelMenu().add(new JSeparator());
|
||||
getPanelMenu().add(Box.createVerticalStrut(2));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param item the menuItem to add to the popup.
|
||||
*/
|
||||
protected void addItem(AbstractButton item) {
|
||||
getPanelMenu().add(item);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the popup to add menuitems. Guaranteed to be != null.
|
||||
*/
|
||||
protected JPopupMenu getPopupMenu() {
|
||||
if (popupMenu == null) {
|
||||
popupMenu = new JPopupMenu();
|
||||
popupMenu.removeAll();
|
||||
popupMenu.setLayout(new BorderLayout());
|
||||
popupMenu.add(getScroller(), BorderLayout.CENTER);
|
||||
}
|
||||
return popupMenu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the scroll pane which houses the scrollable list.
|
||||
*/
|
||||
protected JScrollPane createScroller() {
|
||||
JScrollPane sp = new JScrollPane( null,
|
||||
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
|
||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER );
|
||||
sp.setHorizontalScrollBar(null);
|
||||
sp.setBorder(BorderFactory.createEmptyBorder());
|
||||
return sp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns to popup component for user interaction. Lazily
|
||||
* creates the component if necessary.
|
||||
*
|
||||
* @return the ColumnControlPopup for showing the items, guaranteed
|
||||
* to be not <code>null</code>.
|
||||
* @see #createColumnControlPopup()
|
||||
*/
|
||||
protected ColumnControlPopup getColumnControlPopup() {
|
||||
if (popup == null) {
|
||||
popup = createColumnControlPopup();
|
||||
}
|
||||
return popup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to return a <code>ColumnControlPopup</code>.
|
||||
* Subclasses can override to hook custom implementations.
|
||||
*
|
||||
* @return the <code>ColumnControlPopup</code> used.
|
||||
*/
|
||||
protected ColumnControlPopup createColumnControlPopup() {
|
||||
return new DefaultColumnControlPopup();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------- updates from table propertyChangelistnere
|
||||
|
||||
/**
|
||||
* Adjusts internal state after table's column model property has changed.
|
||||
* Handles cleanup of listeners to the old/new columnModel (Note, that
|
||||
* it listens to the column model only if it can control column visibility).
|
||||
* Updates content of popup.
|
||||
*
|
||||
* @param oldModel the old <code>TableColumnModel</code> we had been listening to.
|
||||
*/
|
||||
protected void updateFromColumnModelChange(TableColumnModel oldModel) {
|
||||
if (oldModel != null && columnModelListener != null) {
|
||||
oldModel.removeColumnModelListener(columnModelListener);
|
||||
}
|
||||
populatePopup();
|
||||
table.getColumnModel().addColumnModelListener(getColumnModelListener());
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchs this button's enabled with table's enabled.
|
||||
*
|
||||
*/
|
||||
protected void updateFromTableEnabledChanged() {
|
||||
getAction().setEnabled(table.isEnabled());
|
||||
|
||||
}
|
||||
|
||||
// ------------------------ updating the popup
|
||||
/**
|
||||
* Populates the popup from scratch.
|
||||
*
|
||||
* If applicable, creates and adds column visibility actions. Always adds
|
||||
* additional actions.
|
||||
*/
|
||||
protected void populatePopup() {
|
||||
clearAll();
|
||||
createVisibilityActions();
|
||||
addVisibilityActionItems();
|
||||
addAdditionalActionItems();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* removes all components from the popup, making sure to release all
|
||||
* columnVisibility actions.
|
||||
*
|
||||
*/
|
||||
protected void clearAll() {
|
||||
clearColumnVisibilityActions();
|
||||
getColumnControlPopup().removeAll();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Releases actions and clears list of actions.
|
||||
*
|
||||
*/
|
||||
protected void clearColumnVisibilityActions() {
|
||||
if (columnVisibilityActions == null)
|
||||
return;
|
||||
for (ColumnVisibilityAction action : columnVisibilityActions) {
|
||||
action.releaseColumn();
|
||||
}
|
||||
columnVisibilityActions.clear();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds visibility actions into the popup view.
|
||||
*
|
||||
* Here: delegates the list of actions to the DefaultColumnControlPopup.
|
||||
* <p>
|
||||
* PRE: columnVisibilityActions populated before calling this.
|
||||
*
|
||||
*/
|
||||
protected void addVisibilityActionItems() {
|
||||
getColumnControlPopup().addVisibilityActionItems(
|
||||
Collections.unmodifiableList(getColumnVisibilityActions()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds additional actions to the popup.
|
||||
* Here: delegates the list of actions as returned by #getAdditionalActions()
|
||||
* to the DefaultColumnControlPopup.
|
||||
* Does nothing if #getColumnActions() is empty.
|
||||
*
|
||||
*/
|
||||
protected void addAdditionalActionItems() {
|
||||
getColumnControlPopup().addAdditionalActionItems(
|
||||
Collections.unmodifiableList(getAdditionalActions()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates and adds a ColumnVisiblityAction for every column that should be
|
||||
* togglable via the column control. <p>
|
||||
*
|
||||
* Here: all table columns contained in the <code>TableColumnModel</code> -
|
||||
* visible and invisible columns - to <code>createColumnVisibilityAction</code> and
|
||||
* adds all not <code>null</code> return values.
|
||||
*
|
||||
* <p>
|
||||
* PRE: canControl()
|
||||
*
|
||||
* @see #createColumnVisibilityAction
|
||||
*/
|
||||
protected void createVisibilityActions() {
|
||||
Enumeration<TableColumn> columns = table.getColumnModel().getColumns();
|
||||
while(columns.hasMoreElements()) {
|
||||
TableColumn column = columns.nextElement();
|
||||
if (column.getHeaderValue() != null) {
|
||||
ColumnVisibilityAction action = createColumnVisibilityAction(column);
|
||||
if (action != null) {
|
||||
getColumnVisibilityActions().add(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a <code>ColumnVisibilityAction</code> for the given
|
||||
* <code>TableColumn</code>. The return value might be null, f.i. if the
|
||||
* column should not be allowed to be toggled.
|
||||
*
|
||||
* @param column the <code>TableColumn</code> to use for the action
|
||||
* @return a ColumnVisibilityAction to use for the given column,
|
||||
* may be <code>null</code>.
|
||||
*/
|
||||
protected ColumnVisibilityAction createColumnVisibilityAction(TableColumn column) {
|
||||
return new ColumnVisibilityAction(column);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazyly creates and returns the List of visibility actions.
|
||||
*
|
||||
* @return the list of visibility actions, guaranteed to be != null.
|
||||
*/
|
||||
protected List<ColumnVisibilityAction> getColumnVisibilityActions() {
|
||||
if (columnVisibilityActions == null) {
|
||||
columnVisibilityActions = new ArrayList<ColumnVisibilityAction>();
|
||||
}
|
||||
return columnVisibilityActions;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* creates and returns a list of additional Actions to add to the popup.
|
||||
* Here: the actions are looked up in the table's actionMap according
|
||||
* to the keys as returned from #getColumnControlActionKeys();
|
||||
*
|
||||
* @return a list containing all additional actions to include into the popup.
|
||||
*/
|
||||
protected List<Action> getAdditionalActions() {
|
||||
List actionKeys = getColumnControlActionKeys();
|
||||
List<Action> actions = new ArrayList<Action>();
|
||||
for (Object key : actionKeys) {
|
||||
actions.add(table.getActionMap().get(key));
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up and returns action keys to access actions in the
|
||||
* table's actionMap which should be included into the popup.
|
||||
*
|
||||
* Here: all keys with isColumnControlActionKey(key). The list
|
||||
* is sorted by those keys.
|
||||
*
|
||||
* @return the action keys of table's actionMap entries whose
|
||||
* action should be included into the popup.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List getColumnControlActionKeys() {
|
||||
Object[] allKeys = table.getActionMap().allKeys();
|
||||
List columnKeys = new ArrayList();
|
||||
for (int i = 0; i < allKeys.length; i++) {
|
||||
if (isColumnControlActionKey(allKeys[i])) {
|
||||
columnKeys.add(allKeys[i]);
|
||||
}
|
||||
}
|
||||
// JW: this will blow for non-String keys!
|
||||
// so this method is less decoupled from the
|
||||
// decision method isControl than expected.
|
||||
Collections.sort(columnKeys);
|
||||
return columnKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Here: true if a String key starts with #COLUMN_CONTROL_MARKER.
|
||||
*
|
||||
* @param actionKey a key in the table's actionMap.
|
||||
* @return a boolean to indicate whether the given actionKey maps to
|
||||
* an action which should be included into the popup.
|
||||
*
|
||||
*/
|
||||
protected boolean isColumnControlActionKey(Object actionKey) {
|
||||
return (actionKey instanceof String) &&
|
||||
((String) actionKey).startsWith(COLUMN_CONTROL_MARKER);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------- init
|
||||
|
||||
private void installTable(CTable table) {
|
||||
this.table = table;
|
||||
table.addPropertyChangeListener(getTablePropertyChangeListener());
|
||||
updateFromColumnModelChange(null);
|
||||
updateFromTableEnabledChanged();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the column control button's gui
|
||||
*/
|
||||
private void init() {
|
||||
setFocusPainted(false);
|
||||
setFocusable(false);
|
||||
// this is a trick to get hold of the client prop which
|
||||
// prevents closing of the popup
|
||||
JComboBox box = new JComboBox();
|
||||
Object preventHide = box.getClientProperty("doNotCancelPopup");
|
||||
putClientProperty("doNotCancelPopup", preventHide);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates and returns the default action for this button.
|
||||
*
|
||||
* @param icon the Icon to use in the action.
|
||||
* @return the default action.
|
||||
*/
|
||||
private Action createControlAction(Icon icon) {
|
||||
Action control = new AbstractAction() {
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
togglePopup();
|
||||
}
|
||||
|
||||
};
|
||||
control.putValue(Action.SMALL_ICON, icon);
|
||||
return control;
|
||||
}
|
||||
|
||||
// -------------------------------- listeners
|
||||
|
||||
/**
|
||||
* Returns the listener to table's property changes. The listener is
|
||||
* lazily created if necessary.
|
||||
* @return the <code>PropertyChangeListener</code> for use with the
|
||||
* table, guaranteed to be not <code>null</code>.
|
||||
*/
|
||||
protected PropertyChangeListener getTablePropertyChangeListener() {
|
||||
if (tablePropertyChangeListener == null) {
|
||||
tablePropertyChangeListener = createTablePropertyChangeListener();
|
||||
}
|
||||
return tablePropertyChangeListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the listener to table's property changes. Subclasses are free
|
||||
* to roll their own. <p>
|
||||
* Implementation note: this listener reacts to table's <code>enabled</code> and
|
||||
* <code>columnModel</code> properties and calls the respective
|
||||
* <code>updateFromXX</code> methodes.
|
||||
*
|
||||
* @return the <code>PropertyChangeListener</code> for use with the table.
|
||||
*/
|
||||
protected PropertyChangeListener createTablePropertyChangeListener() {
|
||||
return new PropertyChangeListener() {
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if ("columnModel".equals(evt.getPropertyName())) {
|
||||
updateFromColumnModelChange((TableColumnModel) evt
|
||||
.getOldValue());
|
||||
} else if ("enabled".equals(evt.getPropertyName())) {
|
||||
updateFromTableEnabledChanged();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the listener to table's column model. The listener is
|
||||
* lazily created if necessary.
|
||||
* @return the <code>TableColumnModelListener</code> for use with the
|
||||
* table's column model, guaranteed to be not <code>null</code>.
|
||||
*/
|
||||
protected TableColumnModelListener getColumnModelListener() {
|
||||
if (columnModelListener == null) {
|
||||
columnModelListener = createColumnModelListener();
|
||||
}
|
||||
return columnModelListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the listener to columnModel. Subclasses are free to roll their
|
||||
* own.
|
||||
* <p>
|
||||
* Implementation note: this listener reacts to "real" columnRemoved/-Added by
|
||||
* populating the popups content from scratch.
|
||||
*
|
||||
* @return the <code>TableColumnModelListener</code> for use with the
|
||||
* table's columnModel.
|
||||
*/
|
||||
protected TableColumnModelListener createColumnModelListener() {
|
||||
return new TableColumnModelListener() {
|
||||
/** Tells listeners that a column was added to the model. */
|
||||
public void columnAdded(TableColumnModelEvent e) {
|
||||
populatePopup();
|
||||
}
|
||||
|
||||
/** Tells listeners that a column was removed from the model. */
|
||||
public void columnRemoved(TableColumnModelEvent e) {
|
||||
populatePopup();
|
||||
}
|
||||
|
||||
|
||||
/** Tells listeners that a column was repositioned. */
|
||||
public void columnMoved(TableColumnModelEvent e) {
|
||||
}
|
||||
|
||||
/** Tells listeners that a column was moved due to a margin change. */
|
||||
public void columnMarginChanged(ChangeEvent e) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells listeners that the selection model of the TableColumnModel
|
||||
* changed.
|
||||
*/
|
||||
public void columnSelectionChanged(ListSelectionEvent e) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} // end class ColumnControlButton
|
|
@ -19,11 +19,14 @@ package org.compiere.swing;
|
|||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.logging.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
import javax.swing.table.*;
|
||||
|
||||
import org.compiere.util.*;
|
||||
import org.jdesktop.swingx.icon.ColumnControlIcon;
|
||||
|
||||
/**
|
||||
* Model Independent enhanced JTable.
|
||||
|
@ -49,8 +52,22 @@ public class CTable extends JTable
|
|||
setSurrendersFocusOnKeystroke(true);
|
||||
//Default row height too narrow
|
||||
setRowHeight(getFont().getSize() + 8);
|
||||
|
||||
setColumnControlVisible(true);
|
||||
addHierarchyListener(createHierarchyListener());
|
||||
} // CTable
|
||||
|
||||
private HierarchyListener createHierarchyListener() {
|
||||
return new HierarchyListener() {
|
||||
|
||||
public void hierarchyChanged(HierarchyEvent e) {
|
||||
if (e.getChangeFlags() == HierarchyEvent.PARENT_CHANGED)
|
||||
configureColumnControl();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/** Last model index sorted */
|
||||
protected int p_lastSortIndex = -1;
|
||||
/** Sort direction */
|
||||
|
@ -68,6 +85,27 @@ public class CTable extends JTable
|
|||
/** Logger */
|
||||
private static Logger log = Logger.getLogger(CTable.class.getName());
|
||||
|
||||
/**
|
||||
* ScrollPane's original vertical scroll policy. If the column control is
|
||||
* visible the policy is set to ALWAYS.
|
||||
*/
|
||||
private int verticalScrollPolicy;
|
||||
|
||||
/**
|
||||
* Flag to indicate if the column control is visible.
|
||||
*/
|
||||
private boolean columnControlVisible = false;
|
||||
|
||||
/**
|
||||
* The component used a column control in the upper trailing corner of
|
||||
* an enclosing <code>JScrollPane</code>.
|
||||
*/
|
||||
private JComponent columnControlButton;
|
||||
|
||||
private List<TableColumn> hiddenColumns = new ArrayList<TableColumn>();
|
||||
|
||||
private Map<TableColumn, ColumnAttributes> columnAttributesMap
|
||||
= new HashMap<TableColumn, ColumnAttributes>();
|
||||
|
||||
/**
|
||||
* Set Model index of Key Column.
|
||||
|
@ -179,10 +217,13 @@ public class CTable extends JTable
|
|||
renderer = getCellRenderer(row, col);
|
||||
comp = renderer.getTableCellRendererComponent
|
||||
(this, getValueAt(row, col), false, false, row, col);
|
||||
if (comp != null)
|
||||
{
|
||||
int rowWidth = comp.getPreferredSize().width;
|
||||
width = Math.max(width, rowWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.log(Level.SEVERE, column.getIdentifier().toString(), e);
|
||||
|
@ -195,6 +236,51 @@ public class CTable extends JTable
|
|||
} // for all columns
|
||||
} // autoSize
|
||||
|
||||
public void packColumn(TableColumn column)
|
||||
{
|
||||
int width = 0;
|
||||
// Header
|
||||
TableCellRenderer renderer = column.getHeaderRenderer();
|
||||
if (renderer == null)
|
||||
renderer = new DefaultTableCellRenderer();
|
||||
Component comp = null;
|
||||
if (renderer != null)
|
||||
comp = renderer.getTableCellRendererComponent
|
||||
(this, column.getHeaderValue(), false, false, 0, 0);
|
||||
//
|
||||
if (comp != null)
|
||||
{
|
||||
width = comp.getPreferredSize().width;
|
||||
width = Math.max(width, comp.getWidth());
|
||||
|
||||
// Cells
|
||||
int col = column.getModelIndex();
|
||||
int maxRow = Math.min(20, getRowCount());
|
||||
try
|
||||
{
|
||||
for (int row = 0; row < maxRow; row++)
|
||||
{
|
||||
renderer = getCellRenderer(row, col);
|
||||
comp = renderer.getTableCellRendererComponent
|
||||
(this, getValueAt(row, col), false, false, row, col);
|
||||
if (comp != null)
|
||||
{
|
||||
int rowWidth = comp.getPreferredSize().width;
|
||||
width = Math.max(width, rowWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.log(Level.SEVERE, column.getIdentifier().toString(), e);
|
||||
}
|
||||
// Width not greater than 250
|
||||
width = Math.min(MAXSIZE, width + SLACK);
|
||||
}
|
||||
//
|
||||
column.setPreferredWidth(width);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sort Table
|
||||
|
@ -328,6 +414,8 @@ public class CTable extends JTable
|
|||
*/
|
||||
class CTableMouseListener extends MouseAdapter
|
||||
{
|
||||
private TableColumn cachedResizingColumn = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
|
@ -341,12 +429,58 @@ public class CTable extends JTable
|
|||
* @param e event
|
||||
*/
|
||||
public void mouseClicked (MouseEvent e)
|
||||
{
|
||||
if (isInResizeRegion(e))
|
||||
{
|
||||
if (e.getClickCount() == 2)
|
||||
packColumn(cachedResizingColumn);
|
||||
uncacheResizingColumn();
|
||||
}
|
||||
else
|
||||
{
|
||||
int vc = getColumnModel().getColumnIndexAtX(e.getX());
|
||||
// log.info( "Sort " + vc + "=" + getColumnModel().getColumn(vc).getHeaderValue());
|
||||
int mc = convertColumnIndexToModel(vc);
|
||||
TableColumn column = getTableHeader().getResizingColumn();
|
||||
if (column != null) return;
|
||||
sort(mc);
|
||||
}
|
||||
}
|
||||
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
cacheResizingColumn(e);
|
||||
}
|
||||
|
||||
public void mousePressed(MouseEvent e) {
|
||||
cacheResizingColumn(e);
|
||||
}
|
||||
|
||||
private void cacheResizingColumn(MouseEvent e) {
|
||||
TableColumn column = getTableHeader().getResizingColumn();
|
||||
if (column != null) {
|
||||
cachedResizingColumn = column;
|
||||
}
|
||||
}
|
||||
|
||||
private void uncacheResizingColumn() {
|
||||
cachedResizingColumn = null;
|
||||
}
|
||||
|
||||
private boolean isInResizeRegion(MouseEvent e) {
|
||||
return cachedResizingColumn != null; // inResize;
|
||||
}
|
||||
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
}
|
||||
|
||||
public void mouseExited(MouseEvent e) {
|
||||
uncacheResizingColumn();
|
||||
}
|
||||
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
uncacheResizingColumn();
|
||||
}
|
||||
|
||||
} // CTableMouseListener
|
||||
|
||||
|
||||
|
@ -371,4 +505,192 @@ public class CTable extends JTable
|
|||
return p_asc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the column control visible property.
|
||||
* <p>
|
||||
*
|
||||
* @return boolean to indicate whether the column control is visible.
|
||||
* @see #setColumnControlVisible(boolean)
|
||||
* @see #setColumnControl(JComponent)
|
||||
*/
|
||||
public boolean isColumnControlVisible() {
|
||||
return columnControlVisible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the column control visible property. If true and
|
||||
* <code>JXTable</code> is contained in a <code>JScrollPane</code>, the
|
||||
* table adds the column control to the trailing corner of the scroll pane.
|
||||
* <p>
|
||||
*
|
||||
* Note: if the table is not inside a <code>JScrollPane</code> the column
|
||||
* control is not shown even if this returns true. In this case it's the
|
||||
* responsibility of the client code to actually show it.
|
||||
* <p>
|
||||
*
|
||||
* The default value is <code>false</code>.
|
||||
*
|
||||
* @param visible boolean to indicate if the column control should be shown
|
||||
* @see #isColumnControlVisible()
|
||||
* @see #setColumnControl(JComponent)
|
||||
*
|
||||
*/
|
||||
public void setColumnControlVisible(boolean visible) {
|
||||
boolean old = isColumnControlVisible();
|
||||
this.columnControlVisible = visible;
|
||||
if (old != isColumnControlVisible()) {
|
||||
configureColumnControl();
|
||||
firePropertyChange("columnControlVisible", old, !old);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the component used as column control. Lazily creates the
|
||||
* control to the default if it is <code>null</code>.
|
||||
*
|
||||
* @return component for column control, guaranteed to be != null.
|
||||
* @see #setColumnControl(JComponent)
|
||||
* @see #createDefaultColumnControl()
|
||||
*/
|
||||
public JComponent getColumnControl() {
|
||||
if (columnControlButton == null) {
|
||||
columnControlButton = createDefaultColumnControl();
|
||||
}
|
||||
return columnControlButton;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the default column control used by this table.
|
||||
* This implementation returns a <code>ColumnControlButton</code> configured
|
||||
* with default <code>ColumnControlIcon</code>.
|
||||
*
|
||||
* @return the default component used as column control.
|
||||
* @see #setColumnControl(JComponent)
|
||||
* @see org.jdesktop.swingx.table.ColumnControlButton
|
||||
* @see org.jdesktop.swingx.icon.ColumnControlIcon
|
||||
*/
|
||||
protected JComponent createDefaultColumnControl() {
|
||||
return new CColumnControlButton(this, new ColumnControlIcon());
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the upper trailing corner of an enclosing
|
||||
* <code>JScrollPane</code>.
|
||||
*
|
||||
* Adds/removes the <code>ColumnControl</code> depending on the
|
||||
* <code>columnControlVisible</code> property.<p>
|
||||
*
|
||||
* @see #setColumnControlVisible(boolean)
|
||||
* @see #setColumnControl(JComponent)
|
||||
*/
|
||||
protected void configureColumnControl() {
|
||||
Container p = getParent();
|
||||
if (p instanceof JViewport) {
|
||||
Container gp = p.getParent();
|
||||
if (gp instanceof JScrollPane) {
|
||||
JScrollPane scrollPane = (JScrollPane) gp;
|
||||
// Make certain we are the viewPort's view and not, for
|
||||
// example, the rowHeaderView of the scrollPane -
|
||||
// an implementor of fixed columns might do this.
|
||||
JViewport viewport = scrollPane.getViewport();
|
||||
if (viewport == null || viewport.getView() != this) {
|
||||
return;
|
||||
}
|
||||
if (isColumnControlVisible()) {
|
||||
verticalScrollPolicy = scrollPane
|
||||
.getVerticalScrollBarPolicy();
|
||||
scrollPane.setCorner(JScrollPane.UPPER_TRAILING_CORNER,
|
||||
getColumnControl());
|
||||
|
||||
scrollPane
|
||||
.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
|
||||
} else {
|
||||
if (verticalScrollPolicy != 0) {
|
||||
// Fix #155-swingx: reset only if we had force always before
|
||||
// PENDING: JW - doesn't cope with dynamically changing the policy
|
||||
// shouldn't be much of a problem because doesn't happen too often??
|
||||
scrollPane.setVerticalScrollBarPolicy(verticalScrollPolicy);
|
||||
}
|
||||
try {
|
||||
scrollPane.setCorner(JScrollPane.UPPER_TRAILING_CORNER,
|
||||
null);
|
||||
} catch (Exception ex) {
|
||||
// Ignore spurious exception thrown by JScrollPane. This
|
||||
// is a Swing bug!
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param column
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean isColumnVisible(TableColumn column)
|
||||
{
|
||||
return !hiddenColumns.contains(column);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide or show column
|
||||
* @param column
|
||||
* @param visible
|
||||
*/
|
||||
public void setColumnVisibility(TableColumn column, boolean visible)
|
||||
{
|
||||
if (visible)
|
||||
{
|
||||
if (isColumnVisible(column)) return;
|
||||
ColumnAttributes attributes = columnAttributesMap.get(column);
|
||||
if (attributes == null) return;
|
||||
|
||||
column.setCellEditor(attributes.cellEditor);
|
||||
column.setCellRenderer(attributes.cellRenderer);
|
||||
column.setMinWidth(attributes.minWidth);
|
||||
column.setMaxWidth(attributes.maxWidth);
|
||||
column.setPreferredWidth(attributes.preferredWidth);
|
||||
columnAttributesMap.remove(column);
|
||||
hiddenColumns.remove(column);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isColumnVisible(column)) return;
|
||||
|
||||
ColumnAttributes attributes = new ColumnAttributes();
|
||||
attributes.cellEditor = column.getCellEditor();
|
||||
attributes.cellRenderer = column.getCellRenderer();
|
||||
attributes.minWidth = column.getMinWidth();
|
||||
attributes.maxWidth = column.getMaxWidth();
|
||||
attributes.preferredWidth = column.getPreferredWidth();
|
||||
columnAttributesMap.put(column, attributes);
|
||||
|
||||
TableCellNone h = new TableCellNone(column.getIdentifier() != null ?
|
||||
column.getIdentifier().toString() : column.getHeaderValue().toString());
|
||||
column.setCellEditor(h);
|
||||
column.setCellRenderer(h);
|
||||
column.setMinWidth(0);
|
||||
column.setMaxWidth(0);
|
||||
column.setPreferredWidth(0);
|
||||
|
||||
hiddenColumns.add(column);
|
||||
}
|
||||
}
|
||||
|
||||
class ColumnAttributes {
|
||||
protected TableCellEditor cellEditor;
|
||||
|
||||
protected TableCellRenderer cellRenderer;
|
||||
|
||||
protected Object headerValue;
|
||||
|
||||
protected int minWidth;
|
||||
|
||||
protected int maxWidth;
|
||||
|
||||
protected int preferredWidth;
|
||||
}
|
||||
|
||||
} // CTable
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/******************************************************************************
|
||||
* Product: Adempiere ERP & CRM Smart Business Solution *
|
||||
* Copyright (C) 2007 Adempiere, Inc. All Rights Reserved. *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. This program 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 this program; if not, write to the Free Software Foundation, Inc., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
*****************************************************************************/
|
||||
package org.compiere.swing;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.util.EventObject;
|
||||
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.event.CellEditorListener;
|
||||
import javax.swing.table.TableCellEditor;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
|
||||
/**
|
||||
* Dummy editor and renderer use for invisible column
|
||||
* @author Low Heng Sin
|
||||
*
|
||||
*/
|
||||
public class TableCellNone implements TableCellEditor, TableCellRenderer {
|
||||
|
||||
private Object m_value;
|
||||
private String m_columnName;
|
||||
|
||||
public TableCellNone(String columnName) {
|
||||
m_columnName = columnName;
|
||||
}
|
||||
|
||||
public Component getTableCellEditorComponent(JTable table, Object value,
|
||||
boolean isSelected, int row, int column) {
|
||||
m_value = value;
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addCellEditorListener(CellEditorListener l) {
|
||||
}
|
||||
|
||||
public void cancelCellEditing() {
|
||||
}
|
||||
|
||||
public Object getCellEditorValue() {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
public boolean isCellEditable(EventObject anEvent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void removeCellEditorListener(CellEditorListener l) {
|
||||
}
|
||||
|
||||
public boolean shouldSelectCell(EventObject anEvent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean stopCellEditing() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Component getTableCellRendererComponent(JTable table, Object value,
|
||||
boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
m_value = value;
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue