This post walks through adding filtering to the System Configuration page in the CM Client helping you track down a setting as quickly as possible.
We added the Settings Framework in Elastic Path Commerce 6.1 and it's proved incredibly useful in centralizing configuration and easing customization versus the previous XML based approach. The number of settings out-of-the-box continues to grow plus any additional ones that customers are free to add. So this tip will show you how to reign in that growing number of settings.
Here's a screenshot of what we'll be producing, if you've spent any time in the System Configuration (like our trusty QA guys) this will be a real time saver.
Changing the layout
I had to refresh my SWT widget layout knowledge a little and found this great page: http://www.eclipse.org/articles/article.php?file=Article-Understanding-Layouts/index.html. With that excellent refresher I decided I would need a three column GridLayout: a column each for the Edit button, filter label and the filter text widget. The table would then span all three columns.
First, simply change the number of columns on the SettingDefinitionComposite:
private void setupLayout() {
final int columns = 3;
this.setLayout(new GridLayout(columns, false));
}
Then add in a horizontal span to the table's LayoutData - this makes it span the three columns we just created.
final int horizontalSpan = 3;
table.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, horizontalSpan, 1));
Note: the final variables are to keep Checkstyle quiet about magic numbers.
Adding the new widgets
The code below adds the label and the filter Text widget. Take a close look at the style we are using to create the Text widget with: SWT.SEARCH | SWT.CANCEL. The SWT.SEARCH style gives us the rounded edges (at least on my Mac) which makes it look like a regular search/filter widget. The SWT.CANCEL style adds the small cross to the widget. When clicked it removes the currently entered text.
Label label = formToolkit.createLabel(this, AdminConfigurationMessages.filterLabel + ":"); //$NON-NLS-1$
GridData gridData = new GridData(SWT.END, SWT.CENTER, false, false);
label.setLayoutData(gridData);
Text settingNameFilter = formToolkit.createText(this, "", SWT.SEARCH | SWT.CANCEL); //$NON-NLS-1$
gridData = new GridData(SWT.FILL, SWT.CENTER, false, false);
final int verticalIndent = 10;
gridData.verticalIndent = verticalIndent;
settingNameFilter.setLayoutData(gridData);
We want this new addition to be localizable so we need to add AdminConfigurationMessages.filterLabel
public static String filterLabel;
And then we provide the English version of that in AdminConfigurationPluginResources.properties
filterLabel=Filter
Filtering
Now we'll take a look at how we will actually filter down the table's contents. The code's pretty simple:
/**
* Filter setting definitions against a specified string.
*/
private class SettingPathFilter extends ViewerFilter {
private final String filterText;
public SettingPathFilter(final String filterText) {
this.filterText = filterText;
}
@Override
public boolean select(final Viewer viewer, final Object parent, final Object element) {
SettingDefinition definition = (SettingDefinition) element;
return StringUtils.containsIgnoreCase(definition.getPath(), filterText);
}
}
We've simply extended the JFace ViewerFilter class and implemented the select method with a case-insensitive check against the setting definition's path. In the next step we'll create an instance of this class and pass it to the TableViewer that holds the setting definitions.
The following page helped me a bit with the ViewerFilter: http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/DemonstratesListViewer.htm
Hooking it together
The bits are all in place, let's tie them together and get the filtering going when a user types in the text box. We simply add a ModifyListener to the filter Text widget and when we receive a ModifyEvent we grab the user-entered string, create a new SettingPathFilter and set that on the tableViewer. That triggers the tableViewer to filter its contents. Note: I chose to use setFilters, rather than addFilter/removeFilter, to keep the code simple: I don't have to keep track of the filter to remove it afterwards I simply call setFilters again.
settingNameFilter.addModifyListener(new ModifyListener() {
public void modifyText(final ModifyEvent event) {
final Text source = (Text) event.getSource();
String filterText = source.getText();
if (StringUtils.isBlank(filterText)) {
tableViewer.setFilters(new ViewerFilter [0]);
} else {
tableViewer.setFilters(new ViewerFilter [] {new SettingPathFilter(filterText)});
}
}
});
Conclusion
So there you have it, all done, with a few small changes we can find settings without having to visually scan the table. Where else might this filtering function be useful? Anyone done any similar customizations they would like to share?
The code
The code changes and the attached patch are against the upcoming 6.2 release, but I'm pretty sure they will apply to any 6.1+ version. Leave a comment if you have any problems applying this and I'll do my best to help you out.
References
http://www.eclipse.org/swt/snippets/ - if you've not taken a look at the SWT snippets then you're missing out. There's a ton of useful examples of using SWT.
http://wiki.eclipse.org/index.php/JFaceSnippets - just like the SWT snippets, this page contains great snippets about using the JFace ui toolkit.

