my Apps: * COOL MOVIE BROWSER (sports, tv on net) here * MONEY ON THREAD (personal finance) here * HIT-BALL (cute game) here



GWT-Ext - How to implement a "Distinct Multiple Filter Columns" grid

In an old posting I've presented a nice multiple filtering for each column of the grid:


The main class is called DMCFGridPanel that implements all the above GUI, using  classes IvImgButton  and IvImage described in the previous articles:  how to extends image with mouse events, and how to simulate a button using images.

Here is the code to implement this:


import com.gwtext.client.core.EventObject;
import com.gwtext.client.core.RegionPosition;
import com.gwtext.client.data.Record;
import com.gwtext.client.data.Store;
import com.gwtext.client.data.StoreTraversalCallback;
import com.gwtext.client.widgets.BoxComponent;
import com.gwtext.client.widgets.Panel;
import com.gwtext.client.widgets.event.ContainerListenerAdapter;
import com.gwtext.client.widgets.event.KeyListener;
import com.gwtext.client.widgets.form.TextField;
import com.gwtext.client.widgets.grid.ColumnConfig;
import com.gwtext.client.widgets.grid.GridPanel;
import com.gwtext.client.widgets.grid.event.GridColumnListenerAdapter;
import com.gwtext.client.widgets.layout.BorderLayout;
import com.gwtext.client.widgets.layout.BorderLayoutData;
import com.gwtext.client.widgets.layout.TableLayout;
import com.gwtext.client.widgets.layout.TableLayoutData;


/**
 * The class DMCFGridPanel is a wrapper that attaches the text-field filters to
 * the grid panel.
 * 
 * @author SCC
 */
public class DMCFGridPanel extends Panel {


/**
* Constructor for the "DMCF" panel.

* @param grid
*            GridPanel that has all grid set up already.
* @param columnsSpec
*            ColumnConfig[] array with the grid columns descriptions
*            (because the store does return a new incomplete object).
*/
public DMCFGridPanel(final GridPanel grid, final ColumnConfig[] columnsSpec) {
/* basic graphical settings */
setBorder(false);
setLayout(new BorderLayout());


/* prepare the filter text-fields */
final Store store = grid.getStore();
final int nbCols = columnsSpec.length;


final TextField[] filters = new TextField[nbCols];
for (int i = 0; i < filters.length; i++) {
filters[i] = new TextField();
filters[i].setName(((ColumnConfig) columnsSpec[i]).getDataIndex());
filters[i].setTitle("Filter for "
+ ((ColumnConfig) columnsSpec[i]).getHeader());
filters[i].addKeyListener(new int[] { EventObject.ENTER },
new KeyListener() {
public void onKey(int key, EventObject e) {
performFiltering(store, filters);
}
});
}
/* add resize listener for the text-fields */
grid.addGridColumnListener(new GridColumnListenerAdapter() {
public void onColumnResize(GridPanel grid, int colIndex, int newSize) {
resizeFilters(filters, grid);
}
});
grid.addListener(new ContainerListenerAdapter() {
public void onResize(BoxComponent component, int adjWidth,
int adjHeight, int rawWidth, int rawHeight) {
resizeFilters(filters, grid);
}
});


/* add the text-fields to a table layout panel */
final Panel filtersPanel = new Panel();
filtersPanel.setPaddings(2, 0, 0, 0);
filtersPanel.setBorder(false);
filtersPanel.setLayout(new TableLayout(nbCols));


for (int i = 0; i < filters.length; i++) {
filters[i].setHeight("100%");
filtersPanel.add(filters[i], new TableLayoutData(1));
filters[i].setHeight(22);
}


final Panel overHeaderPanel = new Panel();
overHeaderPanel.setBorder(false);
overHeaderPanel.setLayout(new BorderLayout());
overHeaderPanel.setHeight(23);


overHeaderPanel.add(filtersPanel, new BorderLayoutData(
RegionPosition.CENTER));


/* prepare the cancel button */
final IvImgButton cancelFilter = new IvImgButton(
"../filter_remove2.png", "Cancel all filters") {
@Override
protected void handleLeftClickEvent(EventObject e) {
store.clearFilter();
for (int i = 0; i < filters.length; i++) {
filters[i].setValue("");
}
}
};
cancelFilter.setSize("21px", "21px");
final Panel p = new Panel();
p.setBorder(false);
p.add(cancelFilter);
p.setWidth(21);
overHeaderPanel.add(p, new BorderLayoutData(RegionPosition.EAST));


/* add the filters to the NORTH and the grid to the CENTER */
add(overHeaderPanel, new BorderLayoutData(RegionPosition.NORTH));
add(grid, new BorderLayoutData(RegionPosition.CENTER));
}


/**
* Performs the grid filtering.

* @param store
*            Store object of the grid.
* @param filters
*            TextField[] array of filter text-fields.
*/
private void performFiltering(final Store store, final TextField[] filters) {
store.clearFilter();
store.filterBy(new StoreTraversalCallback() {
public boolean execute(final Record record) {
for (int i = 0; i < filters.length; i++) {
final String fVal = filters[i].getRawValue().toLowerCase();
if (fVal.length() > 0) {
final String fName = filters[i].getName();
final String cellVal = record.getAsString(fName);
if (!cellVal.toLowerCase().contains(fVal)) {
return false;
}
}
}
return true;
}
});
}


/**
* Resizes the filter text-fields according with the column widths.

* @param filters
*            TextField[] array of filter text-fields.
* @param grid
*            GridPanel that has the grid panel.
*/
private void resizeFilters(final TextField[] filters, GridPanel grid) {
for (int i = 0; i < filters.length; i++) {
final int cw = grid.getColumnModel().getColumnWidth(i)
+ (5 - i - (i == 1 ? 1 : 0));
filters[i].setWidth(cw);
}
}


}

And here's  how to use it:

import com.google.gwt.core.client.EntryPoint;
import com.gwtext.client.data.SimpleStore;
import com.gwtext.client.data.Store;
import com.gwtext.client.widgets.Panel;
import com.gwtext.client.widgets.Viewport;
import com.gwtext.client.widgets.grid.ColumnConfig;
import com.gwtext.client.widgets.grid.ColumnModel;
import com.gwtext.client.widgets.grid.GridPanel;
import com.gwtext.client.widgets.layout.FitLayout;

/**
 * Entry point classes define onModuleLoad().
 *
 * @author SCC
 */
public class Nicegrid implements EntryPoint {

/**
* This is the entry point method.
*/
public void onModuleLoad() {
/* preparing the grid */
final ColumnConfig[] columnsSpec = new ColumnConfig[] {
new ColumnConfig("Name", "name", 0, true, null, "name"),
new ColumnConfig("Value", "value", 0, true, null, "value"),
new ColumnConfig("Description", "description", 0, true, null, "description"),
new ColumnConfig("Type", "type", 0, true, null, "type"), 
};

final ColumnModel colModel = new ColumnModel(columnsSpec);

final Object[][] data = new Object[100][columnsSpec.length];
for (int i = 0; i < data.length; i++) {
data[i][0] = "name " + i;
data[i][1] = "value " + i;
data[i][2] = "description " + i;
data[i][3] = "type " + i;
}
final String[] columnIds = new String[columnsSpec.length];
for (int i = 0; i < columnIds.length; i++) {
columnIds[i] = columnsSpec[i].getDataIndex();
}
final Store store = new SimpleStore(columnIds, data);
store.load();

final GridPanel grid = new GridPanel(store, colModel);
grid.setAutoScroll(true);

grid.getView().fitColumns(true);
grid.getView().setForceFit(true);
grid.getView().setAutoFill(true);
grid.getView().setEmptyText("No rows");
/* add the grid to a "wrapper" DMCF panel & viewport*/
final Panel container = new Panel(
"DMCF - Distinct Multiple Column Filters test");
container.setLayout(new FitLayout());
container.setPaddings(20);
container.add(new DMCFGridPanel(grid, columnsSpec));
new Viewport(container);
}
}

Cheers!

No comments:

Post a Comment