All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.cuf.ui.table.VisibilityDialog Maven / Gradle / Ivy

The newest version!
package net.sf.cuf.ui.table;

import net.sf.cuf.ui.SwingDecorator;

import java.awt.Component;
import java.awt.Container;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractListModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.table.TableModel;


/**
 * A modal visibility dialog for a table.
 * The dialog allows to show and hide columns in a table.
 * The user may choose from all the columns present in the table model.
 * 

* The dialog will be centered over the parent window the first time it is opened. * Later on it will keep its last position. * * @author Hendrik Wördehoff, sd&m AG */ public class VisibilityDialog extends BasicDialog { /** List box of column headers. */ private JList mColumnHeaders; private boolean[] mResult; /** * Constructor. * @param pOwner parent window (must not be null) */ public VisibilityDialog(final Frame pOwner) { super(pOwner, "TABLEVIS_DIALOG"); addComponents(); } /** * Create all the components of the dialog. *

* The dialog features the following interesting points: *

    *
  • the OK button acts as the default button and can be activated with the ENTER key
  • *
  • Cancel becomes default button when it gets the focus so the default button has to * be reset to OK as soon as the focus moves away
  • *
  • double clicking on the list toggles the respective list entry
  • *
  • {@link net.sf.cuf.ui.SwingDecorator} is used for initialising the components
  • *
*/ private void addComponents() { // define layout Container pane = getContentPane(); pane.setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridy = 0; gbc.anchor = GridBagConstraints.WEST; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.ipadx = 0; gbc.ipady = 0; Insets insetsList = new Insets(2, 4, 2, 4); Insets insetsManipulationButtons = new Insets(2, 10, 2, 4); Insets insetsButtons = new Insets(15, 4, 2, 4); // add list to display the column visibility mColumnHeaders = new JList(); mColumnHeaders.setCellRenderer(new ColumnListCellRenderer()); mColumnHeaders.addMouseListener(new MouseAdapter() { public void mouseClicked(final MouseEvent pEvent) { if (pEvent.getClickCount() == 2 && pEvent.getModifiers() == MouseEvent.BUTTON1_MASK) { processColumnToggle(mColumnHeaders.locationToIndex(pEvent.getPoint())); pEvent.consume(); } else { super.mouseClicked(pEvent); } } }); gbc.gridheight = 4; gbc.insets = insetsList; pane.add(new JScrollPane(mColumnHeaders, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER), gbc); gbc.gridheight = 1; // add list manipulation buttons gbc.fill = GridBagConstraints.HORIZONTAL; gbc.insets = insetsManipulationButtons; JButton buttonShow = new JButton(); SwingDecorator.initialize(buttonShow, "TABLEVIS_DIALOG_SHOW"); buttonShow.setDefaultCapable(false); buttonShow.addActionListener(pEvent -> processColumnsShowHide(true)); gbc.gridx = 1; pane.add(buttonShow, gbc); JButton buttonHide = new JButton(); SwingDecorator.initialize(buttonHide, "TABLEVIS_DIALOG_HIDE"); buttonHide.setDefaultCapable(false); buttonHide.addActionListener(pEvent -> processColumnsShowHide(false)); gbc.gridy++; gbc.weighty = 100; gbc.anchor = GridBagConstraints.NORTHWEST; pane.add(buttonHide, gbc); gbc.weighty = 0; gbc.anchor = GridBagConstraints.WEST; JButton buttonSelectAll = new JButton(); SwingDecorator.initialize(buttonSelectAll, "TABLEVIS_DIALOG_SELECTALL"); buttonSelectAll.setDefaultCapable(false); buttonSelectAll.addActionListener(pEvent -> { // select all list entries mColumnHeaders.setSelectionInterval(0, mColumnHeaders.getModel().getSize() - 1); }); gbc.gridy++; pane.add(buttonSelectAll, gbc); JButton buttonSelectNone = new JButton(); SwingDecorator.initialize(buttonSelectNone, "TABLEVIS_DIALOG_SELECTNONE"); buttonSelectNone.setDefaultCapable(false); buttonSelectNone.addActionListener(pEvent -> { // clear any selection mColumnHeaders.clearSelection(); }); gbc.gridy++; pane.add(buttonSelectNone, gbc); gbc.fill = GridBagConstraints.NONE; gbc.gridy++; // add OK and Cancel buttons gbc.gridx = 0; gbc.gridwidth = 2; gbc.anchor = GridBagConstraints.SOUTHEAST; gbc.insets = insetsButtons; pane.add(createOkCancelButtons(), gbc); } /** * Show the modal dialog. * This method blocks until all the user closes the dialog. *

* The visibility is held in a boolean[]. There must be an * entry in this array for each table model column. true * means the respective column is visible. false makes the * column hidden. * * @param pTableModel current table model (must not be null) * @param pVisible current visibility of the columns in the table (must not be null) * @return the selected visibility or null if user cancelled the dialog */ public boolean[] show(final TableModel pTableModel, final boolean[] pVisible) { // check preconditions if (pTableModel == null) throw new IllegalArgumentException("tableModel must not be null"); if (pVisible == null) throw new IllegalArgumentException("tableSortInfoList must not be null"); if (pTableModel.getColumnCount() != pVisible.length) throw new IllegalArgumentException("tableModel and visibility must contain the same number of elements"); // initialize list mColumnHeaders.setModel(new ColumnListModel(fetchColumnHeaders(pTableModel, 0), pVisible)); mColumnHeaders.setSelectionModel(new javax.swing.DefaultListSelectionModel()); // there is no other way to get rid of the focus on the last selected item mColumnHeaders.ensureIndexIsVisible(0); mColumnHeaders.requestFocus(); // show dialog showDialog(); // will block until hide() gets called. // return the result return mResult; } /** * Close the dialog and extract the result from the user input. */ protected void processDialogOk() { setVisible(false); // set result ColumnListModel columns = (ColumnListModel) mColumnHeaders.getModel(); mResult = new boolean[columns.getSize()]; for (int i = 0; i < columns.getSize(); i++) { mResult[i] = ((ColumnListElement) columns.getElementAt(i)).mVisible; } } /** * Close the dialog and clear the result. */ protected void processDialogCancel() { setVisible(false); // set result mResult = null; // no result } /** * Change the visibility of all selected list entries. * @param pShow true if all selected entries are to be made visible */ private void processColumnsShowHide(final boolean pShow) { Object[] selected = mColumnHeaders.getSelectedValues(); for (final Object aSelected : selected) { ((ColumnListElement) aSelected).mVisible = pShow; } ((ColumnListModel) mColumnHeaders.getModel()).notifyListeners(); } /** * Toggle the visibility of a single list entry. * @param pIndex index of the entry to be toggled */ private void processColumnToggle(final int pIndex) { if (pIndex != -1) { ColumnListElement elem = (ColumnListElement)(mColumnHeaders.getModel()).getElementAt(pIndex); elem.mVisible = !elem.mVisible; ((ColumnListModel) mColumnHeaders.getModel()).notifyListeners(pIndex); } } /** * List model for our display of the table columns. *

* It is the responsibility of the caller to trigger the notification of * the listeners about any changes to the list model. */ private static class ColumnListModel extends AbstractListModel { /** List of {@link ColumnListElement}s. */ private List mColumns; /** * Constructor. * Initializes the list model with the given data. * @param pHeaders list of column names * @param pVisible list of visibility state of the columns */ public ColumnListModel(final Object[] pHeaders, final boolean[] pVisible) { int count = pHeaders.length; mColumns = new ArrayList<>(count); for (int i = 0; i < count; i++) { mColumns.add(new ColumnListElement(pHeaders[i].toString(), pVisible[i])); } } public Object getElementAt(final int pIndex) { return mColumns.get(pIndex); } public int getSize() { return mColumns.size(); } /** * Notify the listeners that all the list elements have changed their values. */ public void notifyListeners() { fireContentsChanged(this, 0, getSize()); } /** * Notify the listeners that a specific list element has changed its value. * @param pIndex the index that changed */ public void notifyListeners(final int pIndex) { fireContentsChanged(this, pIndex, pIndex); } } /** * Container for the information about one table column. * The attributes in this data container are all public for ease of access. */ private static class ColumnListElement { /** Text to display as the column name. */ public String mName; /** State associated with this column. */ public boolean mVisible; public ColumnListElement(final String pName, final boolean pVisible) { mName = pName; mVisible = pVisible; } public String toString() { return mName + " (" + (mVisible ?"":"in") + "visible)"; } } /** * Cell renderer with visibility icon and column name. * This cell renderer works with {@link ColumnListElement}s. *

* This class extends {@link javax.swing.DefaultListCellRenderer} in order to profit from its performance optimizations. */ private static class ColumnListCellRenderer extends DefaultListCellRenderer { /** Icon for visible columns. */ private static Icon sIconVisible = null; /** Icon for invisible columns. */ private static Icon sIconInvisible = null; /** * Constructor. */ public ColumnListCellRenderer() { loadIcons(); setVerticalTextPosition(CENTER); setHorizontalTextPosition(RIGHT); } /** * Initialize the class attributes in a threadsafe manner. * If the icons are already loaded this method does nothing. */ private static synchronized void loadIcons() { if (sIconVisible == null) { sIconVisible = SwingDecorator.getIcon("TABLEVIS_DIALOG_VISIBLE"); sIconInvisible = SwingDecorator.getIcon("TABLEVIS_DIALOG_INVISIBLE"); } } /** * Set up a renderer for a list entry. * @return fully configured renderer for the given value */ public Component getListCellRendererComponent(final JList pList, final Object pValue, final int pIndex, final boolean pIsSelected, final boolean pCellHasFocus) { // this code is modeled after the SwingSet demo for JListBox in the Java 2 SDK ColumnListElement elem = (ColumnListElement) pValue; super.getListCellRendererComponent(pList, elem.mName, pIndex, pIsSelected, pCellHasFocus); // just let our ancestor configure this object setIcon(elem.mVisible ? sIconVisible : sIconInvisible); return this; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy