TestChooser search functionality

Here's a patch against latest cvs to upgrade TestChooser with a little regex search box. Makes finding the test you are looking for less of a hide 'n' seek game…


# This patch file was generated by NetBeans IDE
# Following Index: paths are relative to: D:develjmesrcjmetest
# This patch can be applied using context Tools: Patch action on respective folder.
# It uses platform neutral UTF-8 encoding and n newlines.
# Above lines and this line are ignored by the patching process.
Index: TestChooser.java
*** D:develjmesrcjmetestTestChooser.java Base (1.15)
--- D:develjmesrcjmetestTestChooser.java Locally Modified (Based On 1.15)
***************
*** 298,303 ****
--- 298,342 ----
          }
      }
 
+     private JPanel createSearchPanel(final JList classes){
+         JPanel search = new JPanel();
+         search.setLayout(new BorderLayout());
+         search.add(new JLabel("Choose a Demo to start:      Find regex: "), BorderLayout.WEST);
+         final javax.swing.JTextField jtf = new javax.swing.JTextField();
+         jtf.setToolTipText("<html>Search starts at the current selection, and ends at the last list item. " +
+                 "<br>Use <b>.*</b> to match any character, <b>\.</b> to match a period character.");
+        
+         jtf.addActionListener(new ActionListener(){
+             public void actionPerformed(ActionEvent e) {
+                 int start = classes.getSelectedIndex();
+                
+                 if(start > classes.getModel().getSize()-1){
+                     start = -1;
+                 }
+                
+                 for(int i = start+1; i < classes.getModel().getSize(); i++){
+                     Class c = (Class) classes.getModel().getElementAt(i);
+                     try{
+                         if(c.getName().matches(jtf.getText())){
+                             classes.setSelectedIndex(i);
+                             classes.ensureIndexIsVisible(i);
+                             break;
+                         }
+                     }catch(java.util.regex.PatternSyntaxException exc){
+                         exc.printStackTrace();
+                         JOptionPane.showMessageDialog(TestChooser.this,
+                                 "There was a problem with your search expression! " +
+                                 "See stdout stacktrace for details.");
+                         return;
+                     }
+                 }
+             }
+         });
+        
+         search.add(jtf);
+         return search;
+     }
+    
      /**
       * Code to create components and action listeners.
       *
***************
*** 310,321 ****
          getContentPane().add( mainPanel, BorderLayout.CENTER );
          mainPanel.setBorder( new EmptyBorder( 10, 10, 10, 10 ) );
 
-         mainPanel.add( new JLabel( "Choose a Demo to start: " ), BorderLayout.NORTH );
-
          final JList list = new JList( classes );
          mainPanel.add( new JScrollPane( list ), BorderLayout.CENTER );
 
--- 349,357 ----
          getContentPane().add( mainPanel, BorderLayout.CENTER );
          mainPanel.setBorder( new EmptyBorder( 10, 10, 10, 10 ) );
 
          final JList list = new JList( classes );
+                
+         mainPanel.add( createSearchPanel( list ), BorderLayout.NORTH );
          mainPanel.add( new JScrollPane( list ), BorderLayout.CENTER );
 
          list.getSelectionModel().addListSelectionListener( new ListSelectionListener() {

that would be an absolutely wonderful feature to have.  :smiley:

I second that.

That would make life so much easier…  XD

I'll look over and apply the patch today.  Thanks. :slight_smile:

I've applied this, but I'd suggest that instead of a pattern it was a bit more like iTunes search box (basically just narrowed the list down to items that contained the string in the box (case insensitive)

Sounds like a good idea. Dunno when I'll be able to implement that, but it sure sounds like it has some reusability, so I might donate some work time for it  :smiley: Of course I totally wouldn't mind if somebody decides to beat me to it!

renanse said:

I've applied this, but I'd suggest that instead of a pattern it was a bit more like iTunes search box (basically just narrowed the list down to items that contained the string in the box (case insensitive)

There ya go. Diff'd against latest cvs.


# This patch file was generated by NetBeans IDE
# Following Index: paths are relative to: D:develjmesrcjmetest
# This patch can be applied using context Tools: Patch action on respective folder.
# It uses platform neutral UTF-8 encoding and n newlines.
# Above lines and this line are ignored by the patching process.
Index: TestChooser.java
*** D:develjmesrcjmetestTestChooser.java Base (1.16)
--- D:develjmesrcjmetestTestChooser.java Locally Modified (Based On 1.16)
***************
*** 56,61 ****
--- 56,62 ----
  import java.util.logging.Level;
  import java.util.logging.Logger;
  import java.util.zip.ZipEntry;
+ import javax.swing.DefaultListModel;
 
  import javax.swing.JButton;
  import javax.swing.JDialog;
***************
*** 65,72 ****
--- 66,76 ----
  import javax.swing.JOptionPane;
  import javax.swing.JPanel;
  import javax.swing.JScrollPane;
+ import javax.swing.ListModel;
  import javax.swing.UIManager;
  import javax.swing.border.EmptyBorder;
+ import javax.swing.event.DocumentEvent;
+ import javax.swing.event.DocumentListener;
  import javax.swing.event.ListSelectionEvent;
  import javax.swing.event.ListSelectionListener;
 
***************
*** 323,329 ****
          getContentPane().add(mainPanel, BorderLayout.CENTER);
          mainPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
 
!         final JList list = new JList(classes);
         
          mainPanel.add( createSearchPanel( list ), BorderLayout.NORTH );
          mainPanel.add(new JScrollPane(list), BorderLayout.CENTER);
--- 327,338 ----
          getContentPane().add(mainPanel, BorderLayout.CENTER);
          mainPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
 
!         final FilteredJList list = new FilteredJList();
!         DefaultListModel model = new DefaultListModel();
!         for(Class c : classes){
!             model.addElement(c);
!         }
!         list.setModel(model);
         
          mainPanel.add( createSearchPanel( list ), BorderLayout.NORTH );
          mainPanel.add(new JScrollPane(list), BorderLayout.CENTER);
***************
*** 362,367 ****
--- 371,412 ----
          center();
      }
     
+     private class FilteredJList extends JList{
+         private String filter;
+         private ListModel originalModel;
+
+         public void setModel(ListModel m){
+             originalModel = m;
+             super.setModel(m);
+         }
+
+         private void update(){
+             if(filter == null || filter.length() == 0){
+                 super.setModel(originalModel);
+             }
+
+             DefaultListModel v = new DefaultListModel();
+             for(int i=0; i<originalModel.getSize(); i++){
+                 Object o = originalModel.getElementAt(i);
+                 String s = String.valueOf(o).toLowerCase();
+                 if(s.contains(filter)){
+                     v.addElement(o);
+                 }
+             }
+             super.setModel(v);
+             revalidate();
+         }
+
+         public String getFilter() {
+             return filter;
+         }
+
+         public void setFilter(String filter) {
+             this.filter = filter.toLowerCase();
+             update();
+         }
+     }
+
      /**
       * center the frame.
       */
***************
*** 490,530 ****
          find("jmetest", true, classes);
      }
 
!     private JPanel createSearchPanel(final JList classes) {
          JPanel search = new JPanel();
          search.setLayout(new BorderLayout());
!         search.add(new JLabel("Choose a Demo to start:      Find regex: "),
                  BorderLayout.WEST);
          final javax.swing.JTextField jtf = new javax.swing.JTextField();
-         jtf
-                 .setToolTipText("<html>Search starts at the current selection, and ends at the last list item. "
-                         + "<br>Use <b>.*</b> to match any character, <b>\.</b> to match a period character.");
 
!         jtf.addActionListener(new ActionListener() {
!             public void actionPerformed(ActionEvent e) {
!                 int start = classes.getSelectedIndex();
!
!                 if (start > classes.getModel().getSize() - 1) {
!                     start = -1;
                  }
!
!                 for (int i = start + 1; i < classes.getModel().getSize(); i++) {
!                     Class c = (Class) classes.getModel().getElementAt(i);
!                     try {
!                         if (c.getName().matches(jtf.getText())) {
!                             classes.setSelectedIndex(i);
!                             classes.ensureIndexIsVisible(i);
!                             break;
                          }
!                     } catch (java.util.regex.PatternSyntaxException exc) {
!                         exc.printStackTrace();
!                         JOptionPane.showMessageDialog(TestChooser.this,
!                                 "There was a problem with your search expression! "
!                                         + "See stdout stacktrace for details.");
!                         return;
                      }
-                 }
-             }
          });
 
          search.add(jtf);
--- 535,560 ----
          find("jmetest", true, classes);
      }
 
!     private JPanel createSearchPanel(final FilteredJList classes) {
          JPanel search = new JPanel();
          search.setLayout(new BorderLayout());
!         search.add(new JLabel("Choose a Demo to start:      Find: "),
                  BorderLayout.WEST);
          final javax.swing.JTextField jtf = new javax.swing.JTextField();
         
!         jtf.getDocument().addDocumentListener(new DocumentListener(){
!             public void removeUpdate(DocumentEvent e) {
!                 classes.setFilter(jtf.getText());
              }
!             public void insertUpdate(DocumentEvent e) {
!                 classes.setFilter(jtf.getText());
              }
!             public void changedUpdate(DocumentEvent e) {
!                 classes.setFilter(jtf.getText());
              }           
          }); 


As you see FilteredJList is an inner class in this patch, which is arguably bad style. Feel free to make it a class of it's own, I just wanted the patch to be as compact as possible.

In, plus a few more tweaks to avoid redundant entries.  Works great.  Thanks again, hevee!

I just noticed that the seach field's tooltip is still there in the cvs version. The text doesn't apply to the new and easy way of searching, so the tooltip should be either changed, or removed.

removed