Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introducing Excel look and feel and column specified table filtering #76

Merged
merged 10 commits into from
Apr 7, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@
</snapshotVersion>
</snapshotVersions>
</versioning>
</metadata>
</metadata>
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
</versions>
<lastUpdated>20130102042349</lastUpdated>
</versioning>
</metadata>
</metadata>
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public abstract class AbstractTableFilter<T extends JTable> implements ITableFil
private final T table;
private final TableFilterState filterState = new TableFilterState();
private boolean autoclean;
private boolean sortable = true;

public AbstractTableFilter( T table ) {
this.table = table;
Expand Down Expand Up @@ -188,4 +189,12 @@ public void clear() {
fireFilterChange();
}

public boolean getSortable() {
return this.sortable;
}

public void setSortable(boolean sortable) {
this.sortable = sortable;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package org.oxbow.swingbits.table.filter;

import javax.swing.*;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class ExcelFilterTableHeaderRenderer extends JPanel implements TableCellRenderer {
private static final long serialVersionUID = 1L;

private final int filterIconPlacement;
private final ITableFilter<?> tableFilter;

private int column = -1;
private JTable table = null;
private JButton button;
private JLabel title;
private Icon filteringIcon;//icon which is displayed on column before any data filtered
private Icon filteredIcon;//icon which is displayed on column after any data filtered

public ExcelFilterTableHeaderRenderer(ITableFilter<?> tableFilter,
int filterIconPlacement,
String columnName,
Icon filteringIcon,
Icon filteredIcon) {
super(new BorderLayout());
this.filterIconPlacement = filterIconPlacement;
if (this.filterIconPlacement != SwingConstants.LEADING &&
this.filterIconPlacement != SwingConstants.TRAILING) {
throw new UnsupportedOperationException("The filter icon " +
"placement can only take the values of " +
"SwingConstants.LEADING or SwingConstants.TRAILING");
}

this.tableFilter = tableFilter;
this.filteringIcon = filteringIcon;
this.filteredIcon = filteredIcon;
this.tableFilter.addChangeListener(filter -> button.setIcon(filter.isFiltered(column)? filteredIcon : filteringIcon));

button = new JButton(this.filteringIcon);
button.setPreferredSize(new Dimension(25, 15));
button.setBorder(BorderFactory.createBevelBorder(1,Color.GRAY, Color.GRAY));
title = new JLabel(columnName);

switch (this.filterIconPlacement) {
case SwingConstants.LEADING:
add(button, BorderLayout.WEST);
add(title, BorderLayout.CENTER);
break;
case SwingConstants.TRAILING:
add(title, BorderLayout.CENTER);
add(button, BorderLayout.EAST);
break;
}
title.setHorizontalAlignment(JLabel.CENTER);
title.setVerticalAlignment(JLabel.CENTER);
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
}

@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
if (table != null && this.table != table) {
//commented to update the column with respective names
//title.setText(table.getColumnName(column));
this.table = table;
final JTableHeader header = table.getTableHeader();
if (header != null) {
header.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
int col = header.getTable().columnAtPoint(e.getPoint());
if (col != column || col == -1) return;

int index = header.getColumnModel().getColumnIndexAtX(e.getPoint().x);
if (index == -1) return;

setBounds(header.getHeaderRect(index));
header.add(ExcelFilterTableHeaderRenderer.this);
validate();

Rectangle buttonBounds = new Rectangle(button.getLocationOnScreen().x, button.getLocationOnScreen().y,
button.getBounds().width, button.getBounds().height);
if ((buttonBounds.contains(e.getLocationOnScreen()))) {
button.doClick();

for (MouseListener ml : header.getMouseListeners()) {
if (ml instanceof TableFilterColumnPopup) {
((TableFilterColumnPopup) ml).showPopupWindow(e);
}
}
}
header.remove(ExcelFilterTableHeaderRenderer.this);

header.repaint();
}
});
}
}
this.column = column;
return this;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,18 @@

package org.oxbow.swingbits.table.filter;

import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.Image;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.SwingConstants;

import org.oxbow.swingbits.table.TableHeaderRenderer;
import org.oxbow.swingbits.util.swing.CompoundIcon;

import javax.swing.*;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.awt.event.*;

/**
* Table header renderer to show the column filter state
*
* Table header renderer to show the column filter state
*
* Created on Feb 10, 2011
* @author Eugene Ryzhikov
*
Expand All @@ -59,9 +55,9 @@ class FilterTableHeaderRenderer extends TableHeaderRenderer {
private final int filterIconPlacement;
private final ITableFilter<?> tableFilter;


public FilterTableHeaderRenderer(ITableFilter<?> tableFilter,
int filterIconPlacement) {
int filterIconPlacement) {
this.tableFilter = tableFilter;
this.filterIconPlacement = filterIconPlacement;

Expand All @@ -72,7 +68,7 @@ public FilterTableHeaderRenderer(ITableFilter<?> tableFilter,
"SwingConstants.LEADING or SwingConstants.TRAILING");
}
}

private Icon getFilterIcon() {

if (icon == null) {
Expand All @@ -85,16 +81,16 @@ private Icon getFilterIcon() {

@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
boolean hasFocus, int row, int column) {

final JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

int modelColumn = table.convertColumnIndexToModel(column);
if (tableFilter.isFiltered(modelColumn)) {
Icon oldIcon = label.getIcon();
Icon newIcon = null;
if (oldIcon == null) {
newIcon = getFilterIcon();
newIcon = getFilterIcon();
} else {
ComponentOrientation orientation =
label.getComponentOrientation();
Expand All @@ -114,7 +110,7 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole
}
label.setIcon(newIcon);
}

return label;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,12 @@ public interface Row {
*/
void modelChanged( TableModel model );

/**
* Determines whether the table is sortable or not - Default true
* @return true by default
*/

void setSortable(boolean sortable);
boolean getSortable();

}
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,12 @@ public void modelChanged( TableModel model ) {
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>( model );
sorter.setSortsOnUpdates(true);
getTable().setRowSorter( sorter );
if (!this.getSortable()) {
for (int i = 0; i < this.getTable().getColumnCount(); i++) {
sorter.setSortable(i, false);
}
}
}
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,13 @@
import java.awt.event.MouseListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import java.util.*;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

import org.oxbow.swingbits.list.ActionCheckListModel;
Expand Down Expand Up @@ -92,6 +80,11 @@ static class ColumnAttrs {
private boolean actionsVisible = true;
private boolean useTableRenderers = false;
ResourceBundle bundle = ResourceBundle.getBundle( "task-dialog" ); // NOI18N
private Set<?> searchableColumns;
private boolean enableRightClick;
private Icon filteringIcon;//icon which is displayed on column before any data filtered
private Icon filteredIcon;//icon which is displayed on column after any data filtered
private boolean clearTableFilterIcon = false;

public TableFilterColumnPopup( ITableFilter<?> filter ) {

Expand Down Expand Up @@ -170,14 +163,16 @@ protected JComponent buildContent() {
JToolBar toolbar = new JToolBar();
toolbar.setFloatable(false);
toolbar.setOpaque(false);
toolbar.add( new PopupWindow.CommandAction(
bundle.getString( "Clear_ALL_COLUMN_FILTERS" ),
new ImageIcon(getClass().getResource("funnel_delete.png"))) {
@Override
protected boolean perform() {
return clearAllFilters();
}
});
if (clearTableFilterIcon) {

toolbar.add(new PopupWindow.CommandAction(bundle.getString("Clear_ALL_COLUMN_FILTERS"),
new ImageIcon(getClass().getResource("funnel_delete.png"))) {
@Override
protected boolean perform() {
return clearAllFilters();
}
});
}
commands.add( toolbar );

commands.add(Box.createHorizontalGlue());
Expand Down Expand Up @@ -231,12 +226,12 @@ public void setEnabled(boolean enabled) {

@Override
public void mousePressed(MouseEvent e) {
if ( enabled && e.isPopupTrigger() ) showFilterPopup(e);
if ( enabled && e.isPopupTrigger() && enableRightClick ) showFilterPopup(e);
}

@Override
public void mouseReleased(MouseEvent e) {
if ( enabled && e.isPopupTrigger() ) showFilterPopup(e);
if ( enabled && e.isPopupTrigger() && enableRightClick ) showFilterPopup(e);
}

private void showFilterPopup(MouseEvent e) {
Expand All @@ -247,6 +242,9 @@ private void showFilterPopup(MouseEvent e) {
int vColumnIndex = colModel.getColumnIndexAtX(e.getX());
if ( vColumnIndex < 0 ) return;

//if a set of columns provided for only those columns to be filtered, then ignore if the column name is not in the list.
TableColumn column = colModel.getColumn(vColumnIndex);
if (searchableColumns != null && !searchableColumns.isEmpty() && !searchableColumns.contains(column.getHeaderValue())) return;

// Determine if mouse was clicked between column heads
Rectangle headerRect = filter.getTable().getTableHeader().getHeaderRect(vColumnIndex);
Expand Down Expand Up @@ -320,6 +318,28 @@ public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}

public void setSearchableColumns(Set<?> searchableColumns) {
this.searchableColumns = searchableColumns;
}

public void setEnableRightClick(boolean enableRightClick) {
this.enableRightClick = enableRightClick;
}

protected void showPopupWindow(MouseEvent e) {
showFilterPopup(e);
}

public void setFilteringIcon(Icon filteringIcon) {
this.filteringIcon = filteringIcon;
}

public void setFilteredIcon(Icon filteredIcon) {
this.filteredIcon = filteredIcon;
}

public void setClearFilterIcon(boolean clearFilter) {
this.clearTableFilterIcon = clearFilter;
}
}

Loading