/*
* $Id$
*
* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*/
package org.jdesktop.swingx.demos.decorator;
import java.awt.Color;
import java.beans.IntrospectionException;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.regex.Pattern;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListModel;
import javax.swing.RowFilter;
import javax.swing.border.Border;
import javax.swing.table.TableModel;
import javax.swing.tree.TreeModel;
import org.jdesktop.swingx.JXList;
import org.jdesktop.swingx.JXPanel;
import org.jdesktop.swingx.JXRadioGroup;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.JXTree;
import org.jdesktop.swingx.action.BoundAction;
import org.jdesktop.swingx.decorator.BorderHighlighter;
import org.jdesktop.swingx.decorator.ColorHighlighter;
import org.jdesktop.swingx.decorator.CompoundHighlighter;
import org.jdesktop.swingx.decorator.HighlightPredicate;
import org.jdesktop.swingx.decorator.Highlighter;
import org.jdesktop.swingx.decorator.SearchPredicate;
import org.jdesktop.swingx.renderer.DefaultTreeRenderer;
import org.jdesktop.swingx.search.PatternModel;
import org.jdesktop.swingx.sort.RowFilters;
import org.jdesktop.swingx.util.ActionMapTableModel;
import org.jdesktop.swingx.util.ActionMapTreeTableModel;
import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.factories.Borders;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.sun.swingset3.DemoProperties;
/**
* Demonstrates usage of Decorators.
*
* @author Jeanette Winzenburg
*/
@DemoProperties(
value = "Decorator Demo",
category = "Functionality",
description = "Demonstrates the usage of SwingX renderer decorations.",
sourceFiles = {
"org/jdesktop/swingx/demos/decorator/DecoratorDemo.java",
"org/jdesktop/swingx/demos/decorator/HighlighterClient.java"
}
)
public class DecoratorDemo extends JPanel {
/**
* the border to use for lists. Set top/bottom only
*/
protected Border listBorder = BorderFactory.createEmptyBorder(3, 0, 3, 0);
/**
* border to use for left/right margin in list.
*/
protected Border marginBorder = BorderFactory.createEmptyBorder(0, 3, 0, 3);
/**
* the border to use for trees.
*/
protected Border treeBorder = BorderFactory.createEmptyBorder(3, 3, 3, 3);
// ----------------- demo components
private JXTree tree;
private JXList list;
private JXTable table;
// ----------------- demo decorators
/** shared highlighter for rollover effect. */
private Highlighter rolloverHighlighter;
/** shared highlighter for matches. */
// private SearchHighlighter searchHighlighter;
private ColorHighlighter matchHighlighter;
private CompoundHighlighter tableHighlighters;
private CompoundHighlighter listHighlighters;
/** hacking highlighter for list's border adjustment. */
private Highlighter marginHighlighter;
/** Filter for matching entries used in list. */
private RowFilter listPatternFilter;
/** Filter for matching entries used in table. */
private RowFilter tablePatternFilter;
// ---------------- controlling components/models
private JXRadioGroup radioGroup;
private JTextField inputText;
private JButton nextButton;
private JTextField patternText;
private PatternModel patternModel;
private String[] findModi = new String[] { "highlight", "filter", "search" };
private String findModus = findModi[0];
private BoundAction findNextAction;
private JLabel radioGroupLabel;
private JLabel inputTextLabel;
private JLabel patternLabel;
/** Creates new form DecoratorDemoPanel */
public DecoratorDemo() {
setName("Decorator Demo");
createDecorators();
initComponents();
configureComponents();
build();
bind();
}
/**
* called after pattern changed.
*
* @param pattern
*/
protected void updatePattern(Pattern pattern) {
HighlightPredicate predicate = new SearchPredicate(pattern, -1, -1);
matchHighlighter.setHighlightPredicate(predicate);
tablePatternFilter = RowFilters.regexFilter(pattern);
listPatternFilter = RowFilters.regexFilter(pattern);
}
/**
* called after find modus changed.
*
*/
private void updateDecorators() {
boolean highlightMatches = findModi[0].equals(getFindModus());
// update the highlighter pipelines
updatePipeline(tableHighlighters, highlightMatches);
updatePipeline(listHighlighters, highlightMatches);
// tree does not support filtering
tree.setEnabled(!findModi[1].equals(getFindModus()));
// filter/search support is implemented for JXList
RowFilter listFilters = findModi[1].equals(getFindModus()) ?
getFilterPipeline("list"): null;
list.setRowFilter(listFilters);
// filter/search support is implemented for JXTable only
RowFilter filters = findModi[1].equals(getFindModus()) ?
getFilterPipeline("table"): null;
table.setRowFilter(filters);
findNextAction.setEnabled(findModi[2].equals(getFindModus()));
// repaint();
}
private void updatePipeline(CompoundHighlighter highlighters, boolean highlightMatches) {
if (highlightMatches) {
highlighters.addHighlighter(rolloverHighlighter, true);
highlighters.addHighlighter(matchHighlighter, true);
} else {
highlighters.removeHighlighter(matchHighlighter);
highlighters.removeHighlighter(rolloverHighlighter);
}
}
//--------------------------- init decorators
private void createDecorators() {
createHighlighters();
findNextAction = new BoundAction("Find Next");
}
//--------------------------- Highlighters
/**
* create all highlighters.
*
*
*/
private void createHighlighters() {
// <snip>rollover effect - light gray background
rolloverHighlighter = new ColorHighlighter(HighlightPredicate.ROLLOVER_ROW,
Color.LIGHT_GRAY, null
);
// </snip>
matchHighlighter = new ColorHighlighter(HighlightPredicate.NEVER,
null, Color.MAGENTA
);
// hacking a right/left margin
marginHighlighter = new BorderHighlighter(marginBorder);
// compoundHighlighter to share between table and tree
tableHighlighters = new CompoundHighlighter();
listHighlighters = new CompoundHighlighter();
}
//----------------------- Filters
private RowFilter getFilterPipeline(String viewKey) {
if ("table".equals(viewKey)) {
return tablePatternFilter;
} else if ("list".equals(viewKey)) {
return listPatternFilter;
}
return null;
}
// ----------------------- initial configure components
private void configureComponents() {
// show column control
table.setColumnControlVisible(true);
table.setVisibleColumnCount(3);
// <snip>enable rollover in collection views
list.setRolloverEnabled(true);
tree.setRolloverEnabled(true);
// </snip>
// share compoundHighlighter in table/tree
table.setHighlighters(tableHighlighters);
tree.setHighlighters(tableHighlighters);
// use different pipeline for list
listHighlighters.addHighlighter(marginHighlighter);
list.setHighlighters(listHighlighters);
// enable list filtering
list.setAutoCreateRowSorter(true);
// initial update of decorations for collection views
updateDecorators();
}
// ------------------------ control find modus
/**
* PRE: getFindModi() contains value.
*/
public void setFindModus(String value) {
if (value.equals(getFindModus()))
return;
Object old = getFindModus();
this.findModus = value;
updateDecorators();
firePropertyChange("findModus", old, getFindModus());
}
/**
* returns the current find modus.
*
* @return the current find modus
*/
public String getFindModus() {
return findModus;
}
/**
* returns array of available find modi.
*
* @return array of available find modi
*/
public String[] getFindModi() {
// @todo: return copy!
return findModi;
}
/**
* callback for findNext action.
*
*/
public void findNext() {
int foundIndex = table.getSearchable().search(patternModel.getPattern(), patternModel
.getFoundIndex());
patternModel.setFoundIndex(foundIndex);
}
// ----------------- create control bindings
private void bind() {
// BindingHandler bindings = new BindingHandler();
// bindings.setAutoCommit(true);
// bindModusControl(bindings);
// bindPatternModel(bindings);
// bindActions(bindings);
// bindings.pull();
}
// private void bindActions(BindingHandler bindings) {
// findNextAction.registerCallback(this, "findNext");
// nextButton.setAction(findNextAction);
// }
//
// private void bindModusControl(BindingHandler bindings) {
//
// // Enumeration not working correctly with classes
// // different from string (?)
// JavaBeanDataModel dataModel = null;
// try {
// EnumeratedMetaData meta = new EnumeratedMetaData("findModus",
// String.class, "Find Modus");
// meta.setEnumeration(getFindModi());
// dataModel = new JavaBeanDataModel(getClass(), this,
// new MetaData[] { meta });
// } catch (IntrospectionException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
//
// bindings.add(BindingFactory.getInstance().createBinding(
// radioGroup, dataModel, "findModus"));
// bindings.add(BindingFactory.getInstance().createMetaBinding(
// radioGroupLabel, dataModel, "findModus"));
// }
// private void bindPatternModel(BindingHandler bindings) {
// patternModel = new PatternModel();
//
// // init DataModel
// JavaBeanDataModel dataModel = null;
// try {
// dataModel = new JavaBeanDataModel(patternModel);
// dataModel.getMetaData("pattern").setReadOnly(true);
// dataModel.getMetaData("pattern").setLabel("Pattern");
// dataModel.getMetaData("rawText").setLabel("Input Text");
// } catch (IntrospectionException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// // ------------------------ create control bindings
//
// bindings.add(BindingFactory.getInstance().createBinding(
// inputText, dataModel, "rawText"));
// bindings.add(BindingFactory.getInstance().createMetaBinding(
// inputTextLabel, dataModel, "rawText"));
// bindings.add(BindingFactory.getInstance().createBinding(
// patternText, dataModel, "pattern"));
// bindings.add(BindingFactory.getInstance().createMetaBinding(
// patternLabel, dataModel, "pattern"));
//
// // ------- wire control value changes to presentation changes
// patternModel.addPropertyChangeListener(new PropertyChangeListener() {
//
// public void propertyChange(PropertyChangeEvent evt) {
// if ("pattern".equals(evt.getPropertyName())) {
// updatePattern((Pattern) evt.getNewValue());
// }
//
// }
//
// });
// }
// ----------------------- create models
private TableModel createTableModel() {
return new ActionMapTableModel(new JXTable().getActionMap());
}
private ListModel createListModel() {
JXList list = new JXList();
return new DefaultComboBoxModel(list.getActionMap().allKeys());
}
private TreeModel createTreeModel() {
// return new FileSystemModel();
return new ActionMapTreeTableModel(new JXTree());
}
// ---------------------- init UI
/**
* This method is called from within the constructor to initialize the form.
*/
private void initComponents() {
table = new JXTable(createTableModel());
// table = new JXTreeTable(new ActionMapTreeTableModel(new
// JXTreeTable()));
list = new JXList(createListModel());
tree = new JXTree(createTreeModel());
// control components
nextButton = new JButton("Find next");
radioGroup = new JXRadioGroup();
inputText = new JTextField();
patternText = new JTextField();
}
private void build() {
// COLUMN SPECS:
// f:p:g, l:4dluX:n, f:d:g, l:4dluX:n, f:d:g
// ROW SPECS:
// c:d:n, t:3dluY:n, f:d:g, t:4dluY:n, c:d:n
//
// COLUMN GROUPS: {}
// ROW GROUPS: {}
//
// COMPONENT CONSTRAINTS
// ( 1, 1, 1, 1, "d=f, d=c"); javax.swing.JLabel "table";
// name=tableLabel
// ( 3, 1, 1, 1, "d=f, d=c"); javax.swing.JLabel "list"; name=listLabel
// ( 5, 1, 1, 1, "d=f, d=c"); javax.swing.JLabel "tree"; name=treeLabel
// ( 1, 3, 1, 1, "d=f, d=f"); javax.swing.JScrollPane; name=table
// ( 3, 3, 1, 1, "d=f, d=f"); javax.swing.JScrollPane; name=list
// ( 5, 3, 1, 1, "d=f, d=f"); javax.swing.JScrollPane; name=tree
// ( 1, 5, 5, 1, "d=f, d=c"); javax.swing.JPanel; name=decoratorcontrol2
//
FormLayout formLayout = new FormLayout(
"f:p:g, l:4dlu:n, f:d:g, l:4dlu:n, f:d:g", // columns
"c:d:n, t:3dlu:n, f:d:g, t:4dlu:n, c:d:n"); // rows
PanelBuilder builder = new PanelBuilder(formLayout, this);
builder.setDefaultDialogBorder();
CellConstraints cc = new CellConstraints();
CellConstraints cl = new CellConstraints();
// builder.add(new JLabel("JXTable:"), cl.xywh(1, 1, 1, 1));
builder.addLabel("JXTable:", cl.xywh(1, 1, 1, 1),
new JScrollPane(table), cc.xywh(1, 3, 1, 1));
builder.addLabel("JXList:", cl.xywh(3, 1, 1, 1), new JScrollPane(list),
cc.xywh(3, 3, 1, 1));
builder.addLabel("JXTree:", cl.xywh(5, 1, 1, 1), new JScrollPane(tree),
cc.xywh(5, 3, 1, 1));
builder.add(buildControl(), cc.xywh(1, 5, 5, 1));
list.setBorder(listBorder);
tree.setBorder(treeBorder);
}
private JComponent buildControl() {
// COLUMN SPECS:
// r:p:n, l:4dluX:n, f:max(p;100dluX):n, l:4dluX:n, f:max(p;50dluX):n
// ROW SPECS:
// c:d:n, t:4dluY:n, c:d:n
//
// COLUMN GROUPS: {}
// ROW GROUPS: {}
//
// COMPONENT CONSTRAINTS
// ( 1, 1, 1, 1, "d=r, d=c"); javax.swing.JLabel "Modus"; name=modus
// ( 3, 1, 3, 1, "d=f, d=c"); javax.swing.JPanel; name=moduscontrol
// ( 1, 3, 1, 1, "d=r, d=c"); javax.swing.JLabel "Input"; name=input
// ( 3, 3, 1, 1, "d=f, d=c"); javax.swing.JTextField; name=searchText
// ( 5, 3, 1, 1, "d=f, d=c"); de.kleopatra.view.JButton; name=next
//
FormLayout formLayout = new FormLayout(
"r:p:n, l:4dlu:n, f:max(p;100dlu):n, l:4dlu:n, f:max(p;50dlu):n", // columns
"c:d:n, t:4dlu:n, c:d:n, t:4dlu:n, c:d:n"); // rows
JXPanel control = new JXPanel();
PanelBuilder builder = new PanelBuilder(formLayout, control);
builder.setBorder(Borders.BUTTON_BAR_GAP_BORDER);
CellConstraints cl = new CellConstraints();
CellConstraints cc = new CellConstraints();
radioGroupLabel = builder.addLabel("", cl.xywh(1, 1, 1, 1), radioGroup, cc.xywh(3,
1, 3, 1));
inputTextLabel = builder.addLabel("", cl.xywh(1, 3, 1, 1), inputText, cc
.xywh(3, 3, 1, 1));
patternLabel = builder.addLabel("", cl.xywh(1, 5, 1, 1), patternText, cc.xywh(
3, 5, 1, 1));
builder.add(nextButton, cc.xywh(5, 3, 1, 1));
return control;
}
// --------------- super overrides
public String getName() {
return "Decorators";
}
public String getInformationTitle() {
return "Highlighters :: Filters";
}
public String getHtmlDescription() {
return "<html> "
+ " Demonstrates the use Decorators (Highlighters, Filters)"
+ " and searching "
+ " in collection components JXTable, JXList, JXTree. "
+ " "
+ "<p> <b>Find matching text </b> - this demo supports three find modes: "
+ " <ul>"
+ " <li> highlight all matching occurrences "
+ " <li> filter away all non-matching rows (JXTable only - match is tested on first "
+ " column)"
+ " <li> search and select next occurrence (JXTable only) "
+ " </ul>"
+ "<p> <b>Mouse rollover</b> - this demo highlights the foreground in the row below "
+ " the current mouse position if the find mode is set to highlight. "
+ " </html>";
}
}