/* * $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>"; } }