/* * $Id$ * * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle, * Santa Clara, California 95054, U.S.A. All rights reserved. */ package org.jdesktop.swingx; import java.awt.Color; import java.awt.Window; import java.awt.event.ActionEvent; import java.io.IOException; import java.net.URL; import java.util.logging.Logger; import java.util.regex.Pattern; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.Box; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JScrollPane; import javax.swing.SwingUtilities; import org.jdesktop.swingx.action.AbstractActionExt; import org.jdesktop.swingx.decorator.AbstractHighlighter; import org.jdesktop.swingx.decorator.ColorHighlighter; import org.jdesktop.swingx.decorator.CompoundHighlighter; import org.jdesktop.swingx.decorator.HighlightPredicate; import org.jdesktop.swingx.decorator.SearchPredicate; import org.jdesktop.swingx.renderer.DefaultTreeRenderer; import org.jdesktop.swingx.renderer.IconValues; import org.jdesktop.swingx.renderer.StringValues; import org.jdesktop.swingx.search.SearchFactory; import org.jdesktop.swingx.search.TableSearchable; import org.jdesktop.swingx.search.FindTest.TestListModel; import org.jdesktop.swingx.search.FindTest.TestTableModel; import org.jdesktop.swingx.treetable.FileSystemModel; import org.jdesktop.test.AncientSwingTeam; public class FindVisualCheck extends InteractiveTestCase { @SuppressWarnings("unused") private static final Logger LOG = Logger.getLogger(FindVisualCheck.class .getName()); public static void main(String args[]) { setSystemLF(true); // Locale.setDefault(new Locale("es")); FindVisualCheck test = new FindVisualCheck(); try { test.runInteractiveTests(); // test.runInteractiveTests("interactive.*Compare.*"); // test.runInteractiveTests("interactive.*Close.*"); } catch (Exception e) { System.err.println("exception when executing interactive tests:"); e.printStackTrace(); } } @Override protected void setUp() { editorURL = FindVisualCheck.class.getResource("resources/test.txt"); } private URL editorURL; public FindVisualCheck() { super("Find Action Test"); } public void interactiveTableSearchColumn() { JXTable table = new JXTable(); table.setSearchable(new SearchColumnTableSearchable(table, 0)); table.setModel(new TestTableModel()); SearchFactory.getInstance().setUseFindBar(true); showWithScrollingInFrame(table, "search restricted to first column"); } /** * Custom searchable which supports per-column searching in a JXTable. */ public static class SearchColumnTableSearchable extends TableSearchable { public final static int SEARCH_ALL_COLUMNS = -1; int searchColumn; /** * @param table */ public SearchColumnTableSearchable(JXTable table) { this(table, SEARCH_ALL_COLUMNS); } /** * @param table * @param searchAllColumns */ public SearchColumnTableSearchable(JXTable table, int searchColumn) { super(table); // TODO : add getters and setters for searchColumn this.searchColumn = searchColumn; } /** * {@inheritDoc} <p> * * Overridden to support per-column searching. */ @Override protected void findMatchAndUpdateState(Pattern pattern, int startRow, boolean backwards) { if (SEARCH_ALL_COLUMNS == searchColumn) { super.findMatchAndUpdateState(pattern, startRow, backwards); } else { SearchResult result = findMatchInSearchColumn(pattern, startRow, backwards); updateState(result); } } /** * @param pattern <code>Pattern</code> that we will try to locate * @param startRow position in the document in the appropriate * coordinates from which we will start search or -1 to start * from the beginning * @param backwards <code>true</code> if we should perform search * towards the beginning */ private SearchResult findMatchInSearchColumn(Pattern pattern, int startRow, boolean backwards) { SearchResult searchResult = null; if (backwards) { for (int index = startRow; index >= 0 && searchResult == null; index--) { searchResult = findMatchAt(pattern, index, searchColumn); } } else { for (int index = startRow; index < getSize() && searchResult == null; index++) { searchResult = findMatchAt(pattern, index, searchColumn); } } return searchResult; } /** * {@inheritDoc} <p> */ @Override protected int moveStartPosition(int startIndex, boolean backwards) { if (backwards) { return super.moveStartPosition(startIndex, backwards); } else { lastSearchResult.resetFoundColumn(); if (backwards) { startIndex--; } else { startIndex++; } return startIndex; } } } /** * Requirement: mark all matches. Working in incrememtal find mode only */ public void interactiveTableMarkAllMatches() { JXTable table = new JXTable(); table.setSearchable(new MarkAllTableSearchable(table)); table.setModel(new TestTableModel()); // SearchFactory.getInstance().setUseFindBar(true); showWithScrollingInFrame(table, "mark all matches - must enable incremental find mode"); } /** * Searchable which highlights all matches. */ public static class MarkAllTableSearchable extends TableSearchable { private ColorHighlighter cell; private ColorHighlighter base; /** * @param table */ public MarkAllTableSearchable(JXTable table) { super(table); } @Override protected AbstractHighlighter getConfiguredMatchHighlighter() { AbstractHighlighter hl = super.getConfiguredMatchHighlighter(); if (hasMatch()) { cell.setHighlightPredicate(super.createMatchPredicate()); } return hl; } @Override protected HighlightPredicate createMatchPredicate() { return hasMatch() ? new SearchPredicate(lastSearchResult.getPattern()) : HighlightPredicate.NEVER; } @Override protected AbstractHighlighter createMatchHighlighter() { base = new ColorHighlighter(Color.YELLOW.brighter(), null, Color.YELLOW.darker(), null); cell = new ColorHighlighter(Color.YELLOW.darker(), null); CompoundHighlighter match = new CompoundHighlighter(base, cell); return match; } } /** * Requirement: hook into close. * * Solution: put the custom action in the panel's action map with the * key JXDialog.CLOSE_ACTION_COMMAND. * * Nasty problem is that the custom action overwrites the default, * so the dialog is not closed. Nasty solution is to go up the until the * JXDialog is found and manually invoke its close. */ public void interactiveCustomClose() { final SearchFactory custom = new SearchFactory() { @Override public JXFindPanel createFindPanel() { final JXFindPanel panel = super.createFindPanel(); Action customClose = new AbstractAction() { public void actionPerformed(ActionEvent e) { LOG.info("my action"); // this is nasty ... Window window = SwingUtilities.getWindowAncestor(panel); if (window instanceof JXDialog) { ((JXDialog) window).doClose(); } } }; panel.getActionMap().put(JXDialog.CLOSE_ACTION_COMMAND, customClose); return panel; } }; final JXTable table = new JXTable(new AncientSwingTeam()); Action customFind = new AbstractAction() { public void actionPerformed(ActionEvent e) { custom.showFindDialog(table, table.getSearchable()); } }; table.getActionMap().put("find", customFind); showWithScrollingInFrame(table, "augment close action of dialog"); } /** * Issue #720, 692-swingx: findDialog on tree selection as match-marker lost * * Scenario (#692): open find via button * - press button to open find * - run a search with match, selects a node * - close findDialog, clears selection * * Scenario (#702): open find via ctrl-f * - focus tree * - ctrl-f to open findDialog * - run a search with match, selects a node * - close findDialog * - tab to button, clears selection */ public void interactiveFindDialogSelectionTree() { final JXTree table = new JXTree(); JComponent comp = Box.createVerticalBox(); comp.add(new JScrollPane(table)); Action action = new AbstractActionExt("open find dialog") { public void actionPerformed(ActionEvent e) { SearchFactory.getInstance().showFindDialog(table, table.getSearchable()); } }; comp.add(new JButton(action)); JXFrame frame = wrapInFrame(comp, "Tree FindDialog: selection lost"); frame.setVisible(true); } /** * Issue #718-swingx: finddialog not updated on LF switch. * * Hmm .. shouldn't a lf-switcher update all windows? Like the * setPlafAction in InteractiveTestCase does (since today <g>). * * Yeah, but the dialog had been disposed and the findPanel unparented * if focus is moved somewhere "outside" of the target. Needed to add something * focusable to reproduce here: * - open find in table * - click button * - toggle LF * - open find in table: the panel is not changed to new LF */ public void interactiveFindDialogUpdateLF() { JXTable table = new JXTable(new AncientSwingTeam()); table.setColumnControlVisible(true); JComponent comp = Box.createVerticalBox(); comp.add(new JScrollPane(table)); comp.add(new JButton("something to focus")); JXFrame frame = wrapInFrame(comp, "FindDialog on toggleLF", true); frame.setVisible(true); } public void interactiveShowTree() { JXTree tree = new JXTree(new FileSystemModel()); tree.setCellRenderer(new DefaultTreeRenderer(IconValues.FILE_ICON, StringValues.FILE_NAME)); tree.setRowHeight(30); tree.setLargeModel(true); showComponent(tree, "Search in XTree"); } public void interactiveShowList() { showComponent(new JXList(new TestListModel()), "Search in XList"); } public void interactiveShowTable() { showComponent(new JXTable(new TestTableModel()), "Search in XTable"); } public void interactiveCompareFindStrategy() { final JXTable first = new JXTable(new TestTableModel()); first.setColumnControlVisible(true); final JXTreeTable second = new JXTreeTable(new FileSystemModel()); JXFrame frame = wrapWithScrollingInFrame(first, second, "Batch/Incremental Search"); addSearchModeToggle(frame); addMessage(frame, "Press ctrl-F to open search widget"); frame.setVisible(true); } public void interactiveShowSplitPane() { showComponent(createEditor(), new JXTable(new TestTableModel()), "Targetable Search"); } public void interactiveShowEditor() { showComponent(createEditor(), "Search in XEditorPane"); } /** * @return * @throws IOException */ private JXEditorPane createEditor() { try { return new JXEditorPane(editorURL); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } public void showComponent(JComponent component, JComponent second, String title) { JXFrame frame; if (second != null) { frame = wrapWithScrollingInFrame(component, second, title); } else { frame= wrapWithScrollingInFrame(component, title); } addMessage(frame, "Press ctrl-F to open search widget"); frame.setSize(600, 400); frame.setVisible(true); } public void showComponent(JComponent component, String title) { showComponent(component, null, title); } /** * Do nothing, keep testRunner happy. */ public void testDummy() { } }