package org.limewire.ui.swing.search.resultpanel; import java.awt.event.MouseEvent; import javax.swing.JPopupMenu; import javax.swing.table.JTableHeader; import org.limewire.ui.swing.listener.MousePopupListener; import org.limewire.ui.swing.search.model.VisualSearchResult; import org.limewire.ui.swing.table.ColumnStateHandler; import org.limewire.ui.swing.table.MouseableTable; import org.limewire.ui.swing.table.TableColumnSelector; import ca.odell.glazedlists.EventList; import ca.odell.glazedlists.TransformedList; import ca.odell.glazedlists.swing.DefaultEventTableModel; /** * Table used to display search results. ResultsTable is an extension of * MouseableTable that provides the following features: * <ul> * <li>Ability to set the table model using Glazed List objects by calling * <code>setEventListFormat()</code>.</li> * <li>Support for saving and restoring column settings using * <code>ColumnStateHandler</code>.</li> * <li>Table header popup menu to display/hide columns using * <code>TableColumnSelector</code>.</li> * </ul> */ public class ResultsTable<E extends VisualSearchResult> extends MouseableTable { private EventList<E> eventList; private ResultsTableFormat<E> tableFormat; private DefaultEventTableModel<E> tableModel; private ColumnStateHandler columnStateHandler; private MousePopupListener mousePopupListener; /** * Constructs a ResultsTable with no data. */ public ResultsTable() { super(); // Initialize table properties. setShowHorizontalLines(false); setShowGrid(false, true); } /** * Returns the EventTableModel used by the table. The returned value may * be null if the table has been disposed. */ public DefaultEventTableModel<E> getEventTableModel() { return tableModel; } /** * Sets the event list, table format, and header display indicator for the * table. This method creates a new TableModel for the table, and updates * the column model to reflect the new format. */ public void setEventListFormat(EventList<E> eventList, ResultsTableFormat<E> tableFormat, boolean showHeader) { // Remove old listeners. uninstallListeners(); // Dispose old table model and event list. if (tableModel != null) { tableModel.dispose(); } if (this.eventList instanceof TransformedList) { ((TransformedList) this.eventList).dispose(); } // Save event list and table format. this.eventList = eventList; this.tableFormat = tableFormat; // Create new table model. tableModel = new DefaultEventTableModel<E>(eventList, tableFormat); setModel(tableModel); // Install new listeners. installListeners(showHeader); } /** * Initializes the table header based on the specified indicator, and * installs listeners on the table header and column model. */ private void installListeners(boolean showHeader) { if (showHeader) { JTableHeader tableHeader = getTableHeader(); // Create table header if necessary. if (tableHeader == null) { tableHeader = createDefaultTableHeader(); setTableHeader(tableHeader); } // Set up table header to have a context menu that configures // which columns are visible. We use MousePopupListener to detect // the popup trigger, which differs on Windows, Mac, and Linux. mousePopupListener = new MousePopupListener() { @Override public void handlePopupMouseEvent(MouseEvent e) { JPopupMenu popupMenu = createHeaderPopupMenu(); popupMenu.show(e.getComponent(), e.getX(), e.getY()); } }; tableHeader.addMouseListener(mousePopupListener); // Install column state handler. columnStateHandler = new ColumnStateHandler(this, tableFormat); } else { // Reset listeners and table header. columnStateHandler = null; mousePopupListener = null; setTableHeader(null); } } /** * Uninstalls listeners on the table header and column model. */ private void uninstallListeners() { if (getTableHeader() != null) { getTableHeader().removeMouseListener(mousePopupListener); } if (columnStateHandler != null) { columnStateHandler.removeListeners(); } } /** * Creates the popup menu for the table header. */ private JPopupMenu createHeaderPopupMenu() { TableColumnSelector columnSelector = new TableColumnSelector(this, tableFormat); return columnSelector.getPopupMenu(); } /** * Loads the saved state of the columns. * * <p>NOTE: This method must be called after the renderers and editors * have been loaded. The settings must be applied in this order: * width/visibility/order.</p> */ public void applySavedColumnSettings(){ if (columnStateHandler != null) { columnStateHandler.setupColumnWidths(); columnStateHandler.setupColumnVisibility(false); columnStateHandler.setupColumnOrder(); } } }