diff --git a/maven/repository/org/oxbow/swing-bits/1.0.0-SNAPSHOT/maven-metadata-local.xml b/maven/repository/org/oxbow/swing-bits/1.0.0-SNAPSHOT/maven-metadata-local.xml
index b80f55e..75531de 100644
--- a/maven/repository/org/oxbow/swing-bits/1.0.0-SNAPSHOT/maven-metadata-local.xml
+++ b/maven/repository/org/oxbow/swing-bits/1.0.0-SNAPSHOT/maven-metadata-local.xml
@@ -33,4 +33,4 @@
-
+
\ No newline at end of file
diff --git a/maven/repository/org/oxbow/swing-bits/maven-metadata-local.xml b/maven/repository/org/oxbow/swing-bits/maven-metadata-local.xml
index f8f84c7..ae27bc0 100644
--- a/maven/repository/org/oxbow/swing-bits/maven-metadata-local.xml
+++ b/maven/repository/org/oxbow/swing-bits/maven-metadata-local.xml
@@ -10,4 +10,4 @@
20130102042349
-
+
\ No newline at end of file
diff --git a/swingbits/src/main/java/org/oxbow/swingbits/table/filter/AbstractTableFilter.java b/swingbits/src/main/java/org/oxbow/swingbits/table/filter/AbstractTableFilter.java
index 2793aa1..577d6f1 100644
--- a/swingbits/src/main/java/org/oxbow/swingbits/table/filter/AbstractTableFilter.java
+++ b/swingbits/src/main/java/org/oxbow/swingbits/table/filter/AbstractTableFilter.java
@@ -60,6 +60,7 @@ public abstract class AbstractTableFilter 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;
@@ -188,4 +189,12 @@ public void clear() {
fireFilterChange();
}
+ public boolean getSortable() {
+ return this.sortable;
+ }
+
+ public void setSortable(boolean sortable) {
+ this.sortable = sortable;
+ }
+
}
diff --git a/swingbits/src/main/java/org/oxbow/swingbits/table/filter/ExcelFilterTableHeaderRenderer.java b/swingbits/src/main/java/org/oxbow/swingbits/table/filter/ExcelFilterTableHeaderRenderer.java
new file mode 100644
index 0000000..7dd49a5
--- /dev/null
+++ b/swingbits/src/main/java/org/oxbow/swingbits/table/filter/ExcelFilterTableHeaderRenderer.java
@@ -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;
+ }
+
+}
diff --git a/swingbits/src/main/java/org/oxbow/swingbits/table/filter/FilterTableHeaderRenderer.java b/swingbits/src/main/java/org/oxbow/swingbits/table/filter/FilterTableHeaderRenderer.java
index b4263de..19a78c1 100644
--- a/swingbits/src/main/java/org/oxbow/swingbits/table/filter/FilterTableHeaderRenderer.java
+++ b/swingbits/src/main/java/org/oxbow/swingbits/table/filter/FilterTableHeaderRenderer.java
@@ -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
*
@@ -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;
@@ -72,7 +68,7 @@ public FilterTableHeaderRenderer(ITableFilter> tableFilter,
"SwingConstants.LEADING or SwingConstants.TRAILING");
}
}
-
+
private Icon getFilterIcon() {
if (icon == null) {
@@ -85,8 +81,8 @@ 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);
@@ -94,7 +90,7 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole
Icon oldIcon = label.getIcon();
Icon newIcon = null;
if (oldIcon == null) {
- newIcon = getFilterIcon();
+ newIcon = getFilterIcon();
} else {
ComponentOrientation orientation =
label.getComponentOrientation();
@@ -114,7 +110,7 @@ public Component getTableCellRendererComponent(JTable table, Object value, boole
}
label.setIcon(newIcon);
}
-
+
return label;
}
diff --git a/swingbits/src/main/java/org/oxbow/swingbits/table/filter/ITableFilter.java b/swingbits/src/main/java/org/oxbow/swingbits/table/filter/ITableFilter.java
index 7ecee12..40d27f4 100644
--- a/swingbits/src/main/java/org/oxbow/swingbits/table/filter/ITableFilter.java
+++ b/swingbits/src/main/java/org/oxbow/swingbits/table/filter/ITableFilter.java
@@ -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();
+
}
diff --git a/swingbits/src/main/java/org/oxbow/swingbits/table/filter/JTableFilter.java b/swingbits/src/main/java/org/oxbow/swingbits/table/filter/JTableFilter.java
index 1dbfec1..4cb8eab 100644
--- a/swingbits/src/main/java/org/oxbow/swingbits/table/filter/JTableFilter.java
+++ b/swingbits/src/main/java/org/oxbow/swingbits/table/filter/JTableFilter.java
@@ -112,8 +112,12 @@ public void modelChanged( TableModel model ) {
TableRowSorter sorter = new TableRowSorter( model );
sorter.setSortsOnUpdates(true);
getTable().setRowSorter( sorter );
+ if (!this.getSortable()) {
+ for (int i = 0; i < this.getTable().getColumnCount(); i++) {
+ sorter.setSortable(i, false);
+ }
+ }
}
}
-
}
diff --git a/swingbits/src/main/java/org/oxbow/swingbits/table/filter/TableFilterColumnPopup.java b/swingbits/src/main/java/org/oxbow/swingbits/table/filter/TableFilterColumnPopup.java
index d49aa83..40fd079 100644
--- a/swingbits/src/main/java/org/oxbow/swingbits/table/filter/TableFilterColumnPopup.java
+++ b/swingbits/src/main/java/org/oxbow/swingbits/table/filter/TableFilterColumnPopup.java
@@ -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;
@@ -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 ) {
@@ -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());
@@ -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) {
@@ -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);
@@ -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;
+ }
}
diff --git a/swingbits/src/main/java/org/oxbow/swingbits/table/filter/TableRowFilterSupport.java b/swingbits/src/main/java/org/oxbow/swingbits/table/filter/TableRowFilterSupport.java
index 154e9e2..01d5023 100644
--- a/swingbits/src/main/java/org/oxbow/swingbits/table/filter/TableRowFilterSupport.java
+++ b/swingbits/src/main/java/org/oxbow/swingbits/table/filter/TableRowFilterSupport.java
@@ -34,12 +34,11 @@
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
+import java.util.stream.Collectors;
-import javax.swing.JTable;
-import javax.swing.SwingConstants;
+import javax.swing.*;
+import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
@@ -58,6 +57,18 @@ public final class TableRowFilterSupport {
private boolean useTableRenderers = false;
private boolean autoclean = false;
+ public enum FilterType {
+ DEFAULT,
+ EXCEL
+ }
+ 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 FilterType filterType = FilterType.DEFAULT;
+ private boolean clearTableFilter = false;
+
private TableRowFilterSupport( ITableFilter> filter ) {
if ( filter == null ) throw new NullPointerException();
//this.table = table;
@@ -150,6 +161,11 @@ public JTable apply() {
filterPopup.setSearchFilter(searchFilter);
filterPopup.setSearchTranslator(translator);
filterPopup.setUseTableRenderers( useTableRenderers );
+ filterPopup.setSearchableColumns(searchableColumns);
+ filterPopup.setEnableRightClick(enableRightClick);
+ filterPopup.setFilteringIcon(filteringIcon);
+ filterPopup.setFilteredIcon(filteredIcon);
+ filterPopup.setClearFilterIcon(clearTableFilter);
setupTableHeader();
@@ -190,14 +206,40 @@ private void setupHeaderRenderers( TableModel newModel, boolean fullSetup ) {
JTable table = filter.getTable();
- FilterTableHeaderRenderer headerRenderer =
- new FilterTableHeaderRenderer(filter, filterIconPlacement);
filter.modelChanged( newModel );
- for( TableColumn c: Collections.list( table.getColumnModel().getColumns()) ) {
- c.setHeaderRenderer( headerRenderer );
+ //default icons
+ if (filteringIcon == null) {
+ filteringIcon = new ImageIcon(getClass().getResource("filtering.png"));
+ }
+ if (filteredIcon == null) {
+ filteredIcon = new ImageIcon(getClass().getResource("filtered.png"));
}
+ TableCellRenderer headerRenderer = null;
+ switch (filterType) {
+ case DEFAULT:
+ for( TableColumn c: Collections.list( table.getColumnModel().getColumns()) ) {
+ if (searchable && ((searchableColumns == null || searchableColumns.isEmpty())
+ || searchableColumns.contains(c.getHeaderValue()))) {
+ headerRenderer = new FilterTableHeaderRenderer(filter, filterIconPlacement);
+ c.setHeaderRenderer( headerRenderer );
+ }
+ }
+ break;
+ case EXCEL:
+ for( TableColumn c: Collections.list( table.getColumnModel().getColumns()) ) {
+ if (searchable && ((searchableColumns == null || searchableColumns.isEmpty())
+ || searchableColumns.contains(c.getHeaderValue()))) {
+ headerRenderer =
+ new ExcelFilterTableHeaderRenderer(filter, filterIconPlacement, (String) c.getHeaderValue(), filteringIcon, filteredIcon);
+ c.setHeaderRenderer( headerRenderer );
+ }
+ }
+ break;
+ }
+
+
if ( !fullSetup ) return;
table.addPropertyChangeListener("model", new PropertyChangeListener() {
@@ -210,5 +252,68 @@ public void propertyChange(PropertyChangeEvent e) {
}
+ /**
+ * Column filter list is searchable & supported columns for searching
+ * Any column is not listed in the table model will be ignored
+ *
+ * @param searchableColumns
+ * @return
+ */
+ public TableRowFilterSupport searchableColumns(Object... searchableColumns) {
+ return this.searchableColumns(Arrays.stream(searchableColumns).collect(Collectors.toSet()));
+ }
+
+ /**
+ * Column filter list is searchable & supported columns for searching
+ * Any column is not listed in the table model will be ignored
+ *
+ * @param searchableColumns
+ * @return
+ */
+ public TableRowFilterSupport searchableColumns(Set> searchableColumns) {
+ this.searchable = true;
+ this.searchableColumns = searchableColumns;
+ return this;
+ }
+ /**
+ * Column filter list is searchable & supported columns for searching
+ * Any column is not listed in the table model will be ignored
+ *
+ * @param searchableColumns
+ * @return
+ */
+ public TableRowFilterSupport searchableColumns(List> searchableColumns) {
+ return this.searchableColumns(new HashSet<>(searchableColumns));
+ }
+
+ public TableRowFilterSupport sortable(boolean sortable) {
+ this.filter.setSortable(sortable);
+ return this;
+ }
+
+ public TableRowFilterSupport enableRightClick(boolean enableRightClick) {
+ this.enableRightClick = enableRightClick;
+ return this;
+ }
+
+ public TableRowFilterSupport filteringIcon(Icon filteringIcon) {
+ this.filteringIcon = filteringIcon;
+ return this;
+ }
+
+ public TableRowFilterSupport filteredIcon(Icon filteredIcon) {
+ this.filteredIcon = filteredIcon;
+ return this;
+ }
+
+ public TableRowFilterSupport filterType(FilterType filterType) {
+ this.filterType = filterType;
+ return this;
+ }
+
+ public TableRowFilterSupport enableClearTableFilter(boolean clearTableFilter) {
+ this.clearTableFilter = clearTableFilter;
+ return this;
+ }
}
diff --git a/swingbits/src/main/resources/org/oxbow/swingbits/table/filter/filtered.png b/swingbits/src/main/resources/org/oxbow/swingbits/table/filter/filtered.png
new file mode 100644
index 0000000..4f204eb
Binary files /dev/null and b/swingbits/src/main/resources/org/oxbow/swingbits/table/filter/filtered.png differ
diff --git a/swingbits/src/main/resources/org/oxbow/swingbits/table/filter/filtering.png b/swingbits/src/main/resources/org/oxbow/swingbits/table/filter/filtering.png
new file mode 100644
index 0000000..08d4dbd
Binary files /dev/null and b/swingbits/src/main/resources/org/oxbow/swingbits/table/filter/filtering.png differ
diff --git a/swingbits/src/test/java/org/oxbow/swingbits/table/filter/TableFilterTest.java b/swingbits/src/test/java/org/oxbow/swingbits/table/filter/TableFilterTest.java
index f5347d0..3a1b11e 100644
--- a/swingbits/src/test/java/org/oxbow/swingbits/table/filter/TableFilterTest.java
+++ b/swingbits/src/test/java/org/oxbow/swingbits/table/filter/TableFilterTest.java
@@ -114,9 +114,15 @@ public void filterChanged(ITableFilter> filter) {
System.out.println("Filter Changed");
}
})
+ .filterIconPlacement(SwingConstants.TRAILING)
+ .filterType(TableRowFilterSupport.FilterType.EXCEL)
.actions(true)
+ .sortable(false)
+ .enableRightClick(false)
.searchable(true)
+ .searchableColumns("A123","B123")
.useTableRenderers(true)
+ .enableClearTableFilter(true)
.autoclean(true);
JTable table = filter.apply();