@Override public void tableChanged(TableModelEvent arg0) { lblMovieCountFiltered.setText(String.valueOf(movieTableModel.getRowCount())); // select first movie if nothing is selected ListSelectionModel selectionModel = table.getSelectionModel(); if (selectionModel.isSelectionEmpty() && movieTableModel.getRowCount() > 0) { selectionModel.setSelectionInterval(0, 0); } if (selectionModel.isSelectionEmpty() && movieTableModel.getRowCount() == 0) { movieSelectionModel.setSelectedMovie(null); } } });
/** * Creates a new table model that extracts column data from the given * <code>source</code> using the the given <code>tableFormat</code>. * * <p>The returned table model is <strong>not thread-safe</strong>. Unless otherwise * noted, all methods are only safe to be called from the event dispatch thread. * To do this programmatically, use {@link SwingUtilities#invokeAndWait(Runnable)} and * wrap the source list (or some part of the source list's pipeline) using * {@link GlazedListsSwing#swingThreadProxyList(EventList)}.</p> * * @param source the EventList that provides the row objects * @param tableFormat the object responsible for extracting column data * from the row objects */ public static <E> AdvancedTableModel<E> eventTableModel(EventList<E> source, TableFormat<? super E> tableFormat) { return new DefaultEventTableModel<E>(source, tableFormat); }
/** * Releases the resources consumed by this {@link EventTableModel} so that it * may eventually be garbage collected. * * <p>An {@link EventTableModel} will be garbage collected without a call to * {@link #dispose()}, but not before its source {@link EventList} is garbage * collected. By calling {@link #dispose()}, you allow the {@link EventTableModel} * to be garbage collected before its source {@link EventList}. This is * necessary for situations where an {@link EventTableModel} is short-lived but * its source {@link EventList} is long-lived. * * <p><strong><font color="#FF0000">Warning:</font></strong> It is an error * to call any method on an {@link EventTableModel} after it has been disposed. * As such, this {@link EventTableModel} should be detached from its * corresponding Component <strong>before</strong> it is disposed. */ @Override public void dispose() { // if we created the swingThreadSource then we must also dispose it if (swingThreadSource != null) swingThreadSource.dispose(); swingThreadSource = null; super.dispose(); } }
/** * Creates a new table model that extracts column data from the given * <code>source</code> using the the given <code>tableFormat</code>. * * <p>The <code>eventAdapterFactory</code> is used to create a {@link TableModelEventAdapter}, * which is then used by the created table model to convert list events to table model events.</p> * * <p>The returned table model is <strong>not thread-safe</strong>. Unless otherwise * noted, all methods are only safe to be called from the event dispatch thread. * To do this programmatically, use {@link SwingUtilities#invokeAndWait(Runnable)} and * wrap the source list (or some part of the source list's pipeline) using * {@link GlazedListsSwing#swingThreadProxyList(EventList)}.</p> * * @param source the EventList that provides the row objects * @param tableFormat the object responsible for extracting column data * from the row objects * @param eventAdapterFactory factory for creating a {@link TableModelEventAdapter} */ public static <E> AdvancedTableModel<E> eventTableModel(EventList<E> source, TableFormat<? super E> tableFormat, TableModelEventAdapter.Factory<E> eventAdapterFactory) { final DefaultEventTableModel<E> result = new DefaultEventTableModel<E>(source, tableFormat); final TableModelEventAdapter<E> eventAdapter = eventAdapterFactory.create(result); result.setEventAdapter(eventAdapter); return result; }
private void autoResizeRow(final int row, int defaultHeight) { if (row < 0 || row > getEventTableModel().getRowCount()) { return; } int height = 0; final Object rowValue = getEventTableModel().getElementAt(row); if (rowValue instanceof SeparatorList.Separator) { //Calculate the Separator row height //This is done every time, because Separator can never be identified 100% //Because elements is changed by filters and sorting //If saved: the list keep growing with useless hash keys Component component = separatorRenderer.getTableCellRendererComponent(this, getValueAt(row, 0), false, false, row, 0); height = component.getPreferredSize().height; } else { //Calculate the row height height = defaultHeight; } //Set row height, if needed (is expensive because repaint is needed) if (this.getRowHeight(row) != height) { this.setRowHeight(row, height); } }
panelContent.add(splitPane, "2, 2, fill, fill"); movieTableModel = new DefaultEventTableModel<>(GlazedListsSwing.swingThreadProxyList(results), new ResultTableFormat()); tableMovies = new ZebraJTable(movieTableModel); tableMovies.setSelectionModel(tableSelectionModel); movieTableModel.addTableModelListener(new TableModelListener() { @Override public void tableChanged(TableModelEvent arg0) { oldMediaFileTableModel = new DefaultEventTableModel<>(GlazedListsSwing.swingThreadProxyList(oldMediaFileEventList), new MediaFileTableFormat()); tableMediaFilesOld = new ZebraJTable(oldMediaFileTableModel); newMediaFileTableModel = new DefaultEventTableModel<>(GlazedListsSwing.swingThreadProxyList(newMediaFileEventList), new MediaFileTableFormat()); tableMediaFilesNew = new ZebraJTable(newMediaFileTableModel);
/** * For implementing the ListEventListener interface. This sends changes * to the table which repaints the table cells. Because this class is * backed by {@link GlazedListsSwing#swingThreadProxyList}, all natural * calls to this method are guaranteed to occur on the Swing EDT. */ @Override public void listChanged(ListEvent<E> listChanges) { handleListChange(listChanges); }
/** * {@inheritDoc} */ public void setTableFormat(TableFormat<? super E> tableFormat) { this.tableFormat = tableFormat; tableModelEvent.setStructureChanged(); fireTableChanged(tableModelEvent); }
/** {@inheritDoc} */ @Override public void valueChanged(final ListSelectionEvent e) { if (e.getValueIsAdjusting()) { for (int row = e.getFirstIndex(); row <= e.getLastIndex(); row++) { if (this.isRowSelected(row)) { if (!selectedRows.contains(row)) { selectedRows.add(row); } } else { if (selectedRows.contains(row)) { selectedRows.remove(selectedRows.indexOf(row)); } } } } if (!selectedRows.isEmpty() && selectedRows.get(selectedRows.size() - 1) < getEventTableModel().getRowCount() && (getEventTableModel().getElementAt(selectedRows.get(selectedRows.size() - 1)) instanceof SeparatorList.Separator)) { setAutoscrolls(false); } else { setAutoscrolls(true); } super.valueChanged(e); }
/** * Creates a new table model that extracts column data from the given <code>source</code> * using the the given <code>tableFormat</code>. * * <p>While holding a read lock, this method wraps the source list using * {@link GlazedListsSwing#swingThreadProxyList(EventList)}.</p> * * <p>The <code>eventAdapterFactory</code> is used to create a {@link TableModelEventAdapter}, * which is then used by the created table model to convert list events to table model events.</p> * * <p> * The returned table model is <strong>not thread-safe</strong>. Unless otherwise noted, all * methods are only safe to be called from the event dispatch thread. * </p> * * @param source the EventList that provides the row objects * @param tableFormat the object responsible for extracting column data from the row objects * @param eventAdapterFactory factory for creating a {@link TableModelEventAdapter} */ public static <E> AdvancedTableModel<E> eventTableModelWithThreadProxyList(EventList<E> source, TableFormat<? super E> tableFormat, TableModelEventAdapter.Factory<E> eventAdapterFactory) { final EventList<E> proxySource = createSwingThreadProxyList(source); final DefaultEventTableModel<E> result = new DefaultEventTableModel<E>(proxySource, true, tableFormat); final TableModelEventAdapter<E> eventAdapter = eventAdapterFactory.create(result); result.setEventAdapter(eventAdapter); return result; }
textFilteredMovies = new FilterList<>(extendedFilteredMovies, textMatcherEditor); movieSelectionModel = new MovieSelectionModel(sortedMovies, textFilteredMovies, movieMatcherEditor); movieTableModel = new DefaultEventTableModel<>(GlazedListsSwing.swingThreadProxyList(textFilteredMovies), new MovieTableFormat()); table = new ZebraJTable(movieTableModel); movieTableModel.addTableModelListener(new TableModelListener() { @Override public void tableChanged(TableModelEvent arg0) {
/** * For implementing the ListEventListener interface. This sends changes * to the table which repaints the table cells. Because this class is * backed by {@link GlazedListsSwing#swingThreadProxyList}, all natural * calls to this method are guaranteed to occur on the Swing EDT. */ public void listChanged(ListEvent<E> listChanges) { handleListChange(listChanges); }
/** * {@inheritDoc} */ public void setTableFormat(TableFormat<? super E> tableFormat) { this.tableFormat = tableFormat; tableModelEvent.setStructureChanged(); fireTableChanged(tableModelEvent); }
/** * Creates a new table model that extracts column data from the given * <code>source</code> using the the given <code>tableFormat</code>. * * <p>The returned table model is <strong>not thread-safe</strong>. Unless otherwise * noted, all methods are only safe to be called from the event dispatch thread. * To do this programmatically, use {@link SwingUtilities#invokeAndWait(Runnable)} and * wrap the source list (or some part of the source list's pipeline) using * {@link GlazedListsSwing#swingThreadProxyList(EventList)}.</p> * * @param source the EventList that provides the row objects * @param tableFormat the object responsible for extracting column data * from the row objects */ public static <E> AdvancedTableModel<E> eventTableModel(EventList<E> source, TableFormat<? super E> tableFormat) { return new DefaultEventTableModel<E>(source, tableFormat); }
@Override public void tableChanged(TableModelEvent arg0) { // select first movie if nothing is selected ListSelectionModel selectionModel = tableMovies.getSelectionModel(); if (selectionModel.isSelectionEmpty() && movieTableModel.getRowCount() > 0) { selectionModel.setSelectionInterval(0, 0); } if (selectionModel.isSelectionEmpty() && movieTableModel.getRowCount() == 0) { resultSelectionModel.setSelectedResult(null); } } });
/** {@inheritDoc} */ @Override public Rectangle getCellRect(final int row, final int column, final boolean includeSpacing) { final DefaultEventTableModel<?> eventTableModel = getEventTableModel(); // sometimes JTable asks for a cellrect that doesn't exist anymore, due // to an editor being installed before a bunch of rows were removed. // In this case, just return an empty rectangle, since it's going to // be discarded anyway if (row >= eventTableModel.getRowCount() || row < 0) { return new Rectangle(); } // if it's the separator row, return the entire row as one big rectangle Object rowValue = eventTableModel.getElementAt(row); if (rowValue instanceof SeparatorList.Separator) { Rectangle firstColumn = super.getCellRect(row, 0, includeSpacing); Rectangle lastColumn = super.getCellRect(row, getColumnCount() - 1, includeSpacing); return firstColumn.union(lastColumn); // otherwise it's business as usual } else { return super.getCellRect(row, column, includeSpacing); } }
/** * For implementing the ListEventListener interface. This sends changes * to the table which repaints the table cells. Because this class is * backed by {@link GlazedListsSwing#swingThreadProxyList}, all natural * calls to this method are guaranteed to occur on the Swing EDT. */ public void listChanged(ListEvent<E> listChanges) { handleListChange(listChanges); }
/** * Releases the resources consumed by this {@link EventTableModel} so that it * may eventually be garbage collected. * * <p>An {@link EventTableModel} will be garbage collected without a call to * {@link #dispose()}, but not before its source {@link EventList} is garbage * collected. By calling {@link #dispose()}, you allow the {@link EventTableModel} * to be garbage collected before its source {@link EventList}. This is * necessary for situations where an {@link EventTableModel} is short-lived but * its source {@link EventList} is long-lived. * * <p><strong><font color="#FF0000">Warning:</font></strong> It is an error * to call any method on an {@link EventTableModel} after it has been disposed. * As such, this {@link EventTableModel} should be detached from its * corresponding Component <strong>before</strong> it is disposed. */ @Override public void dispose() { // if we created the swingThreadSource then we must also dispose it if (swingThreadSource != null) { swingThreadSource.dispose(); } swingThreadSource = null; super.dispose(); } }
/** * Default implementation for converting a {@link ListEvent} to * TableModelEvents. There will be one TableModelEvent per ListEvent block. * Subclasses may choose to implement a different conversion. * * @param listChanges ListEvent to translate */ protected void handleListChange(ListEvent<E> listChanges) { if (!EventQueue.isDispatchThread()) throw new IllegalStateException("Events to " + this.getClass().getSimpleName() + " must arrive on the EDT - consider adding GlazedListsSwing.swingThreadProxyList(source) somewhere in your list pipeline"); // for all changes, one block at a time while (listChanges.nextBlock()) { // get the current change info int startIndex = listChanges.getBlockStartIndex(); int endIndex = listChanges.getBlockEndIndex(); int changeType = listChanges.getType(); // create a table model event for this block tableModelEvent.setValues(startIndex, endIndex, changeType); fireTableChanged(tableModelEvent); } }
/** * Creates a new table model that extracts column data from the given * <code>source</code> using the the given <code>tableFormat</code>. * * <p>The returned table model is <strong>not thread-safe</strong>. Unless otherwise * noted, all methods are only safe to be called from the event dispatch thread. * To do this programmatically, use {@link SwingUtilities#invokeAndWait(Runnable)} and * wrap the source list (or some part of the source list's pipeline) using * GlazedListsSwing#swingThreadProxyList(EventList).</p> * * @param source the EventList that provides the row objects * @param tableFormat the object responsible for extracting column data * from the row objects */ public static <E> AdvancedTableModel<E> eventTableModel(EventList<E> source, TableFormat<? super E> tableFormat) { return new DefaultEventTableModel<E>(source, tableFormat); }