You are viewing a plain text version of this content. The canonical link for it is here.
Posted to general@logging.apache.org by sd...@apache.org on 2010/10/18 09:46:20 UTC

svn commit: r1023677 - in /logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw: ChainsawToolBarAndMenus.java LogPanel.java LoggingEventWrapper.java

Author: sdeboy
Date: Mon Oct 18 07:46:19 2010
New Revision: 1023677

URL: http://svn.apache.org/viewvc?rev=1023677&view=rev
Log:
Performance improvement & UI update
 - since color rules aren't different between search & main tables, just update the associated search event's color directly without re-running a rule evaluation
 - moved search field next to refine focus field

Modified:
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawToolBarAndMenus.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LoggingEventWrapper.java

Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawToolBarAndMenus.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawToolBarAndMenus.java?rev=1023677&r1=1023676&r2=1023677&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawToolBarAndMenus.java (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawToolBarAndMenus.java Mon Oct 18 07:46:19 2010
@@ -18,9 +18,7 @@
 package org.apache.log4j.chainsaw;
 
 import java.awt.BorderLayout;
-import java.awt.Component;
 import java.awt.Dimension;
-import java.awt.Font;
 import java.awt.Insets;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
@@ -36,7 +34,6 @@ import java.util.List;
 import javax.swing.AbstractAction;
 import javax.swing.Action;
 import javax.swing.Box;
-import javax.swing.BoxLayout;
 import javax.swing.ImageIcon;
 import javax.swing.JButton;
 import javax.swing.JCheckBoxMenuItem;
@@ -49,7 +46,6 @@ import javax.swing.JMenuBar;
 import javax.swing.JMenuItem;
 import javax.swing.JPanel;
 import javax.swing.JRadioButtonMenuItem;
-import javax.swing.JTextField;
 import javax.swing.JToolBar;
 import javax.swing.KeyStroke;
 import javax.swing.SwingConstants;
@@ -72,12 +68,9 @@ import org.apache.log4j.chainsaw.receive
  */
 class ChainsawToolBarAndMenus implements ChangeListener {
   private final SmallToggleButton showReceiversButton;
-  private final JTextField findField;
   private final Action changeModelAction;
   private final Action clearAction;
   private final Action toggleWelcomeVisibleAction;
-  private final Action findNextAction;
-  private final Action findPreviousAction;
   private final Action findPreviousColorizedEventAction;
   private final Action findNextColorizedEventAction;
   private final Action findNextMarkerAction;
@@ -122,7 +115,6 @@ class ChainsawToolBarAndMenus implements
   private final SmallToggleButton toggleCyclicButton = new SmallToggleButton();
   private final Action[] logPanelSpecificActions;
   private final JMenu activeTabMenu = new JMenu("Current tab");
-  private final JPanel findPanel;
 
     ChainsawToolBarAndMenus(final LogUI logui) {
     this.logui = logui;
@@ -131,9 +123,6 @@ class ChainsawToolBarAndMenus implements
     fileMenu = new FileMenu(logui);
     toggleWelcomeVisibleAction = toggleWelcomeVisibleAction();
     changeModelAction = createChangeModelAction();
-    findField = new JTextField();
-    findNextAction = getFindNextAction();
-    findPreviousAction = getFindPreviousAction();
     findNextMarkerAction = createFindNextMarkerAction();
     findPreviousColorizedEventAction = getFindPreviousColorizedEventAction();
     findNextColorizedEventAction = getFindNextColorizedEventAction();
@@ -153,28 +142,13 @@ class ChainsawToolBarAndMenus implements
     showReceiversAction = createShowReceiversAction();
     showReceiversButton = new SmallToggleButton(showReceiversAction);
 
-    findPanel = new JPanel();
-    findPanel.setLayout(new BoxLayout(findPanel, BoxLayout.X_AXIS));
-
-    Dimension findSize = new Dimension(260, 22);
-    Dimension findPanelSize = new Dimension(310, 30);
-    findPanel.setPreferredSize(findPanelSize);
-    findPanel.setMaximumSize(findPanelSize);
-    findPanel.setMinimumSize(findPanelSize);
-
-    findField.setPreferredSize(findSize);
-    findField.setMaximumSize(findSize);
-    findField.setMinimumSize(findSize);
-    findPanel.setAlignmentY(Component.CENTER_ALIGNMENT);
-    findField.setAlignmentY(Component.CENTER_ALIGNMENT);
-
     toggleDetailPaneAction = createToggleDetailPaneAction();
     createMenuBar();
     createToolbar();
 
     logPanelSpecificActions =
       new Action[] {
-        pauseAction, findNextAction, findPreviousAction, findNextColorizedEventAction, findPreviousColorizedEventAction,
+        pauseAction, findNextColorizedEventAction, findPreviousColorizedEventAction,
         findNextMarkerAction, findPreviousMarkerAction,
         toggleMarkerAction, clearAllMarkersAction, scrollToTopAction, clearAction,
         fileMenu.getFileSaveAction(), toggleDetailPaneAction,
@@ -817,39 +791,6 @@ class ChainsawToolBarAndMenus implements
     clearButton.setText("");
     toolbar.addSeparator();
 
-    JButton findNextButton = new SmallButton(findNextAction);
-    findNextButton.setText("");
-    findNextButton.getActionMap().put(
-      findNextAction.getValue(Action.NAME), findNextAction);
-    findNextButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
-      (KeyStroke) findNextAction.getValue(Action.ACCELERATOR_KEY),
-      findNextAction.getValue(Action.NAME));
-
-    JButton findPreviousButton = new SmallButton(findPreviousAction);
-    findPreviousButton.setText("");
-    findPreviousButton.getActionMap().put(
-      findPreviousAction.getValue(Action.NAME), findPreviousAction);
-    findPreviousButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
-      (KeyStroke) findPreviousAction.getValue(Action.ACCELERATOR_KEY),
-      findPreviousAction.getValue(Action.NAME));
-
-    JLabel searchLabel = new JLabel("Search:");
-    searchLabel.setDisplayedMnemonic('j');
-    searchLabel.setFont(searchLabel.getFont().deriveFont(Font.BOLD));
-    findPanel.add(searchLabel);
-    findPanel.add(Box.createHorizontalStrut(3));
-    findPanel.add(findField);
-    findPanel.add(Box.createRigidArea(new Dimension(5, 0)));
-    searchLabel.setLabelFor(findField);
-
-
-    toolbar.add(findPanel);
-    toolbar.addSeparator(new Dimension(7, 5));
-    toolbar.add(findNextButton);
-    toolbar.add(findPreviousButton);
-
-    toolbar.addSeparator();
-
     showReceiversButton.setText(null);
     toolbar.add(showReceiversButton);
 
@@ -907,17 +848,6 @@ class ChainsawToolBarAndMenus implements
 
     if (logPanel == null) {
       activateLogPanelActions = false;
-      findField.setEnabled(false);
-      findPanel.removeAll();
-      JLabel searchLabel = new JLabel("Search:");
-      searchLabel.setDisplayedMnemonic('j');
-      searchLabel.setFont(searchLabel.getFont().deriveFont(Font.BOLD));
-      findPanel.add(searchLabel);
-      findPanel.add(Box.createHorizontalStrut(3));
-
-      findPanel.add(findField);
-      findPanel.add(Box.createRigidArea(new Dimension(5, 0)));
-      searchLabel.setLabelFor(findField);
       activeTabMenu.setEnabled(false);
       toggleWelcomeVisibleAction.setEnabled(true);
       detailPaneButton.setSelected(false);
@@ -925,17 +855,6 @@ class ChainsawToolBarAndMenus implements
     } else {
       activeTabMenu.setEnabled(true);
       fileMenu.getFileSaveAction().setEnabled(true);
-      findPanel.removeAll();
-      JLabel searchLabel = new JLabel("Search:");
-      searchLabel.setDisplayedMnemonic('j');
-
-      searchLabel.setFont(searchLabel.getFont().deriveFont(Font.BOLD));
-      findPanel.add(searchLabel);
-      findPanel.add(Box.createHorizontalStrut(3));
-      findPanel.add(logPanel.getFindTextField());
-      findPanel.add(Box.createRigidArea(new Dimension(5, 0)));
-      searchLabel.setLabelFor(logPanel.getFindTextField());
-
       pauseButton.getModel().setSelected(logPanel.isPaused());
       toggleCyclicButton.setSelected(logPanel.isCyclic());
       logui.getStatusBar().setPaused(logPanel.isPaused(), logPanel.getIdentifier());
@@ -945,10 +864,6 @@ class ChainsawToolBarAndMenus implements
       toggleScrollToBottomMenuItem.setSelected(logPanel.isScrollToBottom());
     }
 
-    findPanel.invalidate();
-    findPanel.revalidate();
-    findPanel.repaint();
-
     for (int i = 0; i < logPanelSpecificActions.length; i++) {
       logPanelSpecificActions[i].setEnabled(activateLogPanelActions);
     }
@@ -966,52 +881,6 @@ class ChainsawToolBarAndMenus implements
     }
   }
 
-  private Action getFindNextAction() {
-    final Action action =
-      new AbstractAction("Find next") {
-        public void actionPerformed(ActionEvent e) {
-          LogPanel p = logui.getCurrentLogPanel();
-
-          if (p != null) {
-            p.findNext();
-          }
-        }
-      };
-
-    //    action.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_F));
-    action.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("F3"));
-    action.putValue(
-      Action.SHORT_DESCRIPTION,
-      "Find the next occurrence of the rule from the current row");
-    action.putValue(Action.SMALL_ICON, new ImageIcon(ChainsawIcons.DOWN));
-
-    return action;
-  }
-
-  private Action getFindPreviousAction() {
-    final Action action =
-      new AbstractAction("Find previous") {
-        public void actionPerformed(ActionEvent e) {
-          LogPanel p = logui.getCurrentLogPanel();
-
-          if (p != null) {
-            p.findPrevious();
-          }
-        }
-      };
-
-    //    action.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_F));
-    action.putValue(
-      Action.ACCELERATOR_KEY,
-      KeyStroke.getKeyStroke(KeyEvent.VK_F3, InputEvent.SHIFT_MASK));
-    action.putValue(
-      Action.SHORT_DESCRIPTION,
-      "Find the previous occurrence of the rule from the current row");
-    action.putValue(Action.SMALL_ICON, new ImageIcon(ChainsawIcons.UP));
-
-    return action;
-  }
-
     private Action getFindNextColorizedEventAction() {
       final Action action =
         new AbstractAction("Find next colorized event") {

Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java?rev=1023677&r1=1023676&r2=1023677&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java Mon Oct 18 07:46:19 2010
@@ -27,6 +27,8 @@ import java.awt.FlowLayout;
 import java.awt.Font;
 import java.awt.FontMetrics;
 import java.awt.Graphics;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
 import java.awt.Point;
 import java.awt.Toolkit;
 import java.awt.Window;
@@ -61,8 +63,6 @@ import java.text.NumberFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
 import java.util.Enumeration;
 import java.util.EventObject;
 import java.util.HashMap;
@@ -243,8 +243,6 @@ public class LogPanel extends DockablePa
   private Rule findRule;
   private String currentFindRuleText;
   private Rule findMarkerRule;
-  private final JPanel findPanel;
-  private JTextField findField;
   private final int dividerSize;
   static final String TABLE_COLUMN_ORDER = "table.columns.order";
   static final String TABLE_COLUMN_WIDTHS = "table.columns.widths";
@@ -254,6 +252,7 @@ public class LogPanel extends DockablePa
   private final DateFormat timestampExpressionFormat = new SimpleDateFormat(Constants.TIMESTAMP_RULE_FORMAT);
   private final Logger logger = LogManager.getLogger(LogPanel.class);
   private AutoFilterComboBox filterCombo;
+  private AutoFilterComboBox findCombo;
   private JScrollPane eventsPane;
   private int currentSearchMatchCount;
   private ApplicationPreferenceModel applicationPreferenceModel;
@@ -287,12 +286,16 @@ public class LogPanel extends DockablePa
     logger.debug("creating logpanel for " + identifier);
 
     setLayout(new BorderLayout());
-    findPanel = new JPanel();
-    findPanel.setLayout(new BoxLayout(findPanel, BoxLayout.X_AXIS));
-    Dimension findPanelSize = new Dimension(310, 30);
-    findPanel.setPreferredSize(findPanelSize);
-    findPanel.setMaximumSize(findPanelSize);
-    findPanel.setMinimumSize(findPanelSize);
+
+    String prototypeValue = "1231231231231231231231";
+
+    filterCombo = new AutoFilterComboBox();
+    filterCombo.setPrototypeDisplayValue(prototypeValue);
+    buildCombo(filterCombo, true);
+
+    findCombo = new AutoFilterComboBox();
+    findCombo.setPrototypeDisplayValue(prototypeValue);
+    buildCombo(findCombo, false);
 
     final Map columnNameKeywordMap = new HashMap();
     columnNameKeywordMap.put(ChainsawConstants.CLASS_COL_NAME, LoggingEventFieldResolver.CLASS_FIELD);
@@ -792,7 +795,7 @@ public class LogPanel extends DockablePa
         public void propertyChange(PropertyChangeEvent evt)
         {
             if (evt.getPropertyName().equals("searchExpression")) {
-                findField.setText(evt.getNewValue().toString());
+                findCombo.setSelectedItem(evt.getNewValue().toString());
                 findNext();
             }
         }
@@ -846,11 +849,13 @@ public class LogPanel extends DockablePa
             LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper)iter.next();
             loggingEventWrapper.updateColorRuleColors(colorizer.getBackgroundColor(loggingEventWrapper.getLoggingEvent()), colorizer.getForegroundColor(loggingEventWrapper.getLoggingEvent()));
           }
-
-          for (Iterator iter = searchModel.getAllEvents().iterator();iter.hasNext();) {
-             LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper)iter.next();
-             loggingEventWrapper.updateColorRuleColors(colorizer.getBackgroundColor(loggingEventWrapper.getLoggingEvent()), colorizer.getForegroundColor(loggingEventWrapper.getLoggingEvent()));
-           }
+//          no need to update searchmodel events since tablemodel and searchmodel share all events, and color rules aren't different between the two
+//          if that changes, un-do the color syncing in loggingeventwrapper & re-enable this code
+//
+//          for (Iterator iter = searchModel.getAllEvents().iterator();iter.hasNext();) {
+//             LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper)iter.next();
+//             loggingEventWrapper.updateColorRuleColors(colorizer.getBackgroundColor(loggingEventWrapper.getLoggingEvent()), colorizer.getForegroundColor(loggingEventWrapper.getLoggingEvent()));
+//           }
           colorizedEventAndSearchMatchThumbnail.configureColors();
           lowerPanel.invalidate();
           lowerPanel.revalidate();
@@ -1092,90 +1097,90 @@ public class LogPanel extends DockablePa
     /*
      * Upper panel definition
      */
-    JPanel upperPanel = new JPanel(new BorderLayout());
+    JPanel upperPanel = new JPanel();
+    upperPanel.setLayout(new BoxLayout(upperPanel, BoxLayout.X_AXIS));
     upperPanel.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 0));
 
     final JLabel filterLabel = new JLabel("Refine focus on: ");
     filterLabel.setFont(filterLabel.getFont().deriveFont(Font.BOLD));
     filterLabel.setDisplayedMnemonic('k');
+    filterLabel.setLabelFor(filterCombo);
 
-    JPanel upperLeftPanel = new JPanel();
-    upperLeftPanel.setLayout(new BoxLayout(upperLeftPanel, BoxLayout.X_AXIS));
-    upperLeftPanel.setAlignmentY(Component.CENTER_ALIGNMENT);
-    upperLeftPanel.setAlignmentY(Component.CENTER_ALIGNMENT);
-
-    upperLeftPanel.add(filterLabel);
+    upperPanel.add(filterLabel);
 
-    //add (hopefully useful) default filters
-    Vector filterExpressionVector = new Vector();
-    filterExpressionVector.add("LEVEL == TRACE");
-    filterExpressionVector.add("LEVEL >= DEBUG");
-    filterExpressionVector.add("LEVEL >= INFO");
-    filterExpressionVector.add("LEVEL >= WARN");
-    filterExpressionVector.add("LEVEL >= ERROR");
-    filterExpressionVector.add("LEVEL == FATAL");
-    
-    filterCombo = new AutoFilterComboBox(filterExpressionVector);
-    final JTextField filterText =(JTextField) filterCombo.getEditor().getEditorComponent();
-    filterText.getDocument().addDocumentListener(new DelayedFilterTextDocumentListener(filterText));
-    filterText.setToolTipText("Enter an expression, press enter to add to list");
-    filterText.addKeyListener(new ExpressionRuleContext(filterModel, filterText));
-
-    if (filterCombo.getEditor().getEditorComponent() instanceof JTextField) {
-      filterCombo.addActionListener(
-        new AbstractAction() {
-          public void actionPerformed(ActionEvent e) {
-            if (e.getActionCommand().equals("comboBoxEdited")) {
-              try {
-                //verify the expression is valid
-                  Object item = filterCombo.getSelectedItem();
-                  if (item != null && !item.toString().trim().equals("")) {
-                    ExpressionRule.getRule(item.toString());
-                    //add entry as first row of the combo box
-                    filterCombo.insertItemAt(item, 0);
-                  }
-                //valid expression, reset background color in case we were previously an invalid expression
-                filterText.setBackground(UIManager.getColor("TextField.background"));
-              } catch (IllegalArgumentException iae) {
-                  //don't add expressions that aren't valid
-                  //invalid expression, change background of the field
-                  filterText.setToolTipText(iae.getMessage());
-                  filterText.setBackground(ChainsawConstants.INVALID_EXPRESSION_BACKGROUND);
-                return;
-              }
-            }
-          }
-        });
-    }
-      upperPanel.add(filterCombo, BorderLayout.CENTER);
-      filterLabel.setLabelFor(filterCombo);
-
-    upperPanel.add(upperLeftPanel, BorderLayout.WEST);
-
-    JPanel upperRightPanel =
-      new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
+    upperPanel.add(filterCombo);
 
     //Adding a button to clear filter expressions which are currently remembered by Chainsaw...
-    final JButton clearButton = new JButton(" Clear expression ");
-    clearButton.setToolTipText("Click here to remove the selected expression from the list");
-    clearButton.addActionListener(
+    final JButton removeFilterButton = new JButton(" Remove ");
+    final JTextField filterText =(JTextField) filterCombo.getEditor().getEditorComponent();
+    removeFilterButton.setToolTipText("Click here to remove the selected expression from the list");
+    removeFilterButton.addActionListener(
             new AbstractAction() {
                 public void actionPerformed(ActionEvent e){
                 	Object selectedItem = filterCombo.getSelectedItem();
-                    if (e.getSource() == clearButton && selectedItem != null && !selectedItem.toString().trim().equals("")){
-                        //don't just remove the entry from the store, clear the refine focus field
-                        filterText.setText(null);
+                    if (e.getSource() == removeFilterButton && selectedItem != null && !selectedItem.toString().trim().equals("")){
+                        //don't just remove the entry from the store, clear the field
                         int index = filterCombo.getSelectedIndex();
+                        filterText.setText(null);
                         filterCombo.setSelectedIndex(-1);
                         filterCombo.removeItemAt(index);
                     }
                 }
             }
     );
+    upperPanel.add(removeFilterButton);
+
+    final JLabel findLabel = new JLabel("Search: ");
+    findLabel.setFont(filterLabel.getFont().deriveFont(Font.BOLD));
+    findLabel.setDisplayedMnemonic('j');
+    findLabel.setLabelFor(findCombo);
+
+    upperPanel.add(findLabel);
+
+    upperPanel.add(findCombo);
+
+    Action findNextAction = getFindNextAction();
+    Action findPreviousAction = getFindPreviousAction();
+    //add up & down search
+    JButton findNextButton = new SmallButton(findNextAction);
+    findNextButton.setText("");
+    findNextButton.getActionMap().put(
+      findNextAction.getValue(Action.NAME), findNextAction);
+    findNextButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
+      (KeyStroke) findNextAction.getValue(Action.ACCELERATOR_KEY),
+      findNextAction.getValue(Action.NAME));
+
+    JButton findPreviousButton = new SmallButton(findPreviousAction);
+    findPreviousButton.setText("");
+    findPreviousButton.getActionMap().put(
+      findPreviousAction.getValue(Action.NAME), findPreviousAction);
+    findPreviousButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
+      (KeyStroke) findPreviousAction.getValue(Action.ACCELERATOR_KEY),
+      findPreviousAction.getValue(Action.NAME));
 
-    upperRightPanel.add(clearButton);
+    upperPanel.add(findNextButton);
 
-    upperPanel.add(upperRightPanel, BorderLayout.EAST);
+    upperPanel.add(findPreviousButton);
+
+    //Adding a button to clear filter expressions which are currently remembered by Chainsaw...
+    final JButton removeFindButton = new JButton(" Remove ");
+    final JTextField findText =(JTextField) findCombo.getEditor().getEditorComponent();
+    removeFindButton.setToolTipText("Click here to remove the selected expression from the list");
+    removeFindButton.addActionListener(
+            new AbstractAction() {
+                public void actionPerformed(ActionEvent e){
+                	Object selectedItem = findCombo.getSelectedItem();
+                    if (e.getSource() == removeFindButton && selectedItem != null && !selectedItem.toString().trim().equals("")){
+                        //don't just remove the entry from the store, clear the field
+                        int index = findCombo.getSelectedIndex();
+                        findText.setText(null);
+                        findCombo.setSelectedIndex(-1);
+                        findCombo.removeItemAt(index);
+                    }
+                }
+            }
+    );
+    upperPanel.add(removeFindButton);
 
     /*
      * Detail pane definition
@@ -1312,7 +1317,7 @@ public class LogPanel extends DockablePa
                 //no-op empty searches
                 return;
             }
-            findField.setText("msg ~= '" + selectedText + "'");
+            findCombo.setSelectedItem("msg ~= '" + selectedText + "'");
             findNext();
         }
     };
@@ -1732,7 +1737,7 @@ public class LogPanel extends DockablePa
             }
 
             if (columnNameKeywordMap.containsKey(colName)) {
-              findField.setText(
+              findCombo.setSelectedItem(
                 columnNameKeywordMap.get(colName).toString() + " " + operator
                 + " '" + value + "'");
               findNext();
@@ -1748,7 +1753,7 @@ public class LogPanel extends DockablePa
          super("Clear search field");
        }
           public void actionPerformed(ActionEvent e) {
-            findField.setText(null);
+            findCombo.setSelectedItem(null);
             updateFindRule(null);
           }
         }
@@ -1869,6 +1874,87 @@ public class LogPanel extends DockablePa
     detailPane.addMouseListener(searchTablePopupListener);
   }
 
+    private Action getFindNextAction() {
+    final Action action =
+      new AbstractAction("Find next") {
+        public void actionPerformed(ActionEvent e) {
+          findNext();
+        }
+      };
+
+    //    action.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_F));
+    action.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("F3"));
+    action.putValue(
+      Action.SHORT_DESCRIPTION,
+      "Find the next occurrence of the rule from the current row");
+    action.putValue(Action.SMALL_ICON, new ImageIcon(ChainsawIcons.DOWN));
+
+    return action;
+  }
+
+  private Action getFindPreviousAction() {
+    final Action action =
+      new AbstractAction("Find previous") {
+        public void actionPerformed(ActionEvent e) {
+            findPrevious();
+        }
+      };
+
+    //    action.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_F));
+    action.putValue(
+      Action.ACCELERATOR_KEY,
+      KeyStroke.getKeyStroke(KeyEvent.VK_F3, InputEvent.SHIFT_MASK));
+    action.putValue(
+      Action.SHORT_DESCRIPTION,
+      "Find the previous occurrence of the rule from the current row");
+    action.putValue(Action.SMALL_ICON, new ImageIcon(ChainsawIcons.UP));
+
+    return action;
+  }
+
+  private  void buildCombo(final JComboBox combo, boolean isFiltering) {
+    //add (hopefully useful) default filters
+    combo.addItem("LEVEL == TRACE");
+    combo.addItem("LEVEL >= DEBUG");
+    combo.addItem("LEVEL >= INFO");
+    combo.addItem("LEVEL >= WARN");
+    combo.addItem("LEVEL >= ERROR");
+    combo.addItem("LEVEL == FATAL");
+
+    final JTextField filterText =(JTextField) combo.getEditor().getEditorComponent();
+    if (isFiltering) {
+      filterText.getDocument().addDocumentListener(new DelayedTextDocumentListener(filterText));
+    }
+    filterText.setToolTipText("Enter an expression, press enter to add to list");
+    filterText.addKeyListener(new ExpressionRuleContext(filterModel, filterText));
+
+    if (combo.getEditor().getEditorComponent() instanceof JTextField) {
+      combo.addActionListener(
+        new AbstractAction() {
+          public void actionPerformed(ActionEvent e) {
+            if (e.getActionCommand().equals("comboBoxEdited")) {
+              try {
+                //verify the expression is valid
+                  Object item = combo.getSelectedItem();
+                  if (item != null && !item.toString().trim().equals("")) {
+                    ExpressionRule.getRule(item.toString());
+                    //add entry as first row of the combo box
+                    combo.insertItemAt(item, 0);
+                  }
+                //valid expression, reset background color in case we were previously an invalid expression
+                filterText.setBackground(UIManager.getColor("TextField.background"));
+              } catch (IllegalArgumentException iae) {
+                  //don't add expressions that aren't valid
+                  //invalid expression, change background of the field
+                  filterText.setToolTipText(iae.getMessage());
+                  filterText.setBackground(ChainsawConstants.INVALID_EXPRESSION_BACKGROUND);
+              }
+            }
+          }
+        });
+    }
+  }
+
   /**
    * Accessor
    *
@@ -2080,6 +2166,7 @@ public class LogPanel extends DockablePa
                     Object item = savedVector.get(i);
                     //insert each row at index zero (so last row in vector will be row zero)
                     filterCombo.insertItemAt(item, 0);
+                    findCombo.insertItemAt(item, 0);
                 }
                 if (versionNumber > 1) {
                     //update prefModel columns to include defaults
@@ -2212,7 +2299,11 @@ public class LogPanel extends DockablePa
         //this is a version number written to the file to identify that there is a Vector serialized after this
         s.writeInt(LOG_PANEL_SERIALIZATION_VERSION_NUMBER);
         //don't write filterexpressionvector, write the combobox's model's backing vector
-        s.writeObject(filterCombo.getModelData());
+        Vector combinedVector = new Vector();
+        combinedVector.addAll(filterCombo.getModelData());
+        combinedVector.addAll(findCombo.getModelData());
+        //duplicates will be removed when loaded..
+        s.writeObject(combinedVector);
     } catch (Exception ex) {
         ex.printStackTrace();
         // TODO need to log this..
@@ -2342,18 +2433,6 @@ public class LogPanel extends DockablePa
   	final int row = table.getSelectedRow();
     setDocked(false);
     externalPanel.removeAll();
-    findPanel.removeAll();
-
-    JLabel searchLabel = new JLabel("Search:");
-    searchLabel.setDisplayedMnemonic('j');
-
-    searchLabel.setFont(searchLabel.getFont().deriveFont(Font.BOLD));
-    findPanel.add(searchLabel);
-    findPanel.add(Box.createHorizontalStrut(3));
-
-    findPanel.add(findField);
-    findPanel.add(Box.createRigidArea(new Dimension(5, 0)));
-    searchLabel.setLabelFor(findField);
 
     externalPanel.add(undockedToolbar, BorderLayout.NORTH);
     externalPanel.add(nameTreeAndMainPanelSplit, BorderLayout.CENTER);
@@ -2455,8 +2534,8 @@ public class LogPanel extends DockablePa
       tableRuleMediator.setFindRule(null);
       searchRuleMediator.setFindRule(null);
       //reset background color in case we were previously an invalid expression
-      findField.setBackground(UIManager.getColor("TextField.background"));
-      findField.setToolTipText(
+      findCombo.setBackground(UIManager.getColor("TextField.background"));
+      findCombo.setToolTipText(
         "Enter expression - right click or ctrl-space for menu");
       currentSearchMatchCount = 0;
       currentFindRuleText = null;
@@ -2474,7 +2553,7 @@ public class LogPanel extends DockablePa
       }
       currentFindRuleText = ruleText;
       try {
-        findField.setToolTipText(
+        findCombo.setToolTipText(
           "Enter expression - right click or ctrl-space for menu");
         findRule = ExpressionRule.getRule(ruleText);
         currentSearchMatchCount = tableModel.updateEventsWithFindRule(findRule);
@@ -2483,15 +2562,15 @@ public class LogPanel extends DockablePa
         tableRuleMediator.setFindRule(findRule);
         searchRuleMediator.setFindRule(findRule);
         //valid expression, reset background color in case we were previously an invalid expression
-        findField.setBackground(UIManager.getColor("TextField.background"));
+        findCombo.setBackground(UIManager.getColor("TextField.background"));
         statusBar.setSearchMatchCount(currentSearchMatchCount, getIdentifier());
         if (isSearchResultsVisible()) {
           showSearchResults();
         }
       } catch (IllegalArgumentException re) {
         findRule = null;
-        findField.setToolTipText(re.getMessage());
-        findField.setBackground(ChainsawConstants.INVALID_EXPRESSION_BACKGROUND);
+        findCombo.setToolTipText(re.getMessage());
+        findCombo.setBackground(ChainsawConstants.INVALID_EXPRESSION_BACKGROUND);
         colorizer.setFindRule(null);
         tableRuleMediator.setFindRule(null);
         searchRuleMediator.setFindRule(null);
@@ -2510,8 +2589,19 @@ public class LogPanel extends DockablePa
   private void hideSearchResults() {
     if (searchResultsDisplayed) {
       detailPanel.removeAll();
+      JPanel leftSpacePanel = new JPanel();
+      Integer scrollBarWidth = (Integer) UIManager.get("ScrollBar.width");
+      leftSpacePanel.setPreferredSize(new Dimension(scrollBarWidth.intValue() -4, -1));
+
+      JPanel rightSpacePanel = new JPanel();
+      rightSpacePanel.setPreferredSize(new Dimension(scrollBarWidth.intValue() -4, -1));
+
       detailPanel.add(detailToolbar, BorderLayout.NORTH);
       detailPanel.add(detailPane, BorderLayout.CENTER);
+
+      detailPanel.add(leftSpacePanel, BorderLayout.WEST);
+      detailPanel.add(rightSpacePanel, BorderLayout.EAST);
+ 
       detailPanel.invalidate();
       detailPanel.revalidate();
       detailPanel.repaint();
@@ -2744,91 +2834,15 @@ public class LogPanel extends DockablePa
       toggleScrollToBottomButton.setText("");
       toolbar.add(toggleScrollToBottomButton);
       toolbar.addSeparator();
-    
-    findField = new JTextField();
-    Dimension findSize = new Dimension(260, 22);
-    findField.setPreferredSize(findSize);
-    findField.setMaximumSize(findSize);
-    findField.setMinimumSize(findSize);
-    findPanel.setAlignmentY(Component.CENTER_ALIGNMENT);
-    findField.setAlignmentY(Component.CENTER_ALIGNMENT);
-    findField.addActionListener(new ActionListener(){
-        public void actionPerformed(ActionEvent e) {
-            findNext();
-        }
-    });
-    findField.addKeyListener(
-      new ExpressionRuleContext(filterModel, findField));
 
-    final Action undockedFindNextAction =
-      new AbstractAction() {
-        public void actionPerformed(ActionEvent e) {
-          findNext();
-        }
-      };
-
-    undockedFindNextAction.putValue(Action.NAME, "Find next");
-    undockedFindNextAction.putValue(
-      Action.SHORT_DESCRIPTION,
-      "Find the next search occurrence");
-    undockedFindNextAction.putValue(
-      Action.SMALL_ICON, new ImageIcon(ChainsawIcons.DOWN));
-
-    SmallButton undockedFindNextButton =
-      new SmallButton(undockedFindNextAction);
-
-    undockedFindNextButton.setAction(undockedFindNextAction);
-    undockedFindNextButton.setText("");
-    undockedFindNextButton.getActionMap().put(
-      undockedFindNextAction.getValue(Action.NAME), undockedFindNextAction);
-    undockedFindNextButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
-      KeyStroke.getKeyStroke("F3"),
-      undockedFindNextAction.getValue(Action.NAME));
-
-    final Action undockedFindPreviousAction =
-      new AbstractAction() {
+    findCombo.addActionListener(new ActionListener(){
         public void actionPerformed(ActionEvent e) {
-          findPrevious();
+          //comboboxchanged event received when text is modified in the field..when enter is pressed, it's comboboxedited
+          if (e.getActionCommand().equalsIgnoreCase("comboBoxEdited")) {
+              findNext();
+          }
         }
-      };
-
-    undockedFindPreviousAction.putValue(Action.NAME, "Find previous");
-    undockedFindPreviousAction.putValue(
-      Action.SHORT_DESCRIPTION,
-      "Find the previous search occurrence");
-    undockedFindPreviousAction.putValue(
-      Action.SMALL_ICON, new ImageIcon(ChainsawIcons.UP));
-
-    SmallButton undockedFindPreviousButton =
-      new SmallButton(undockedFindPreviousAction);
-
-    undockedFindPreviousButton.setAction(undockedFindPreviousAction);
-    undockedFindPreviousButton.setText("");
-    undockedFindPreviousButton.getActionMap().put(
-      undockedFindPreviousAction.getValue(Action.NAME),
-      undockedFindPreviousAction);
-    undockedFindPreviousButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
-            KeyStroke.getKeyStroke(KeyEvent.VK_F3, InputEvent.SHIFT_MASK),
-      undockedFindPreviousAction.getValue(Action.NAME));
-
-    Dimension findPanelSize = new Dimension(310, 30);
-    findPanel.setPreferredSize(findPanelSize);
-    findPanel.setMaximumSize(findPanelSize);
-    findPanel.setMinimumSize(findPanelSize);
-    findField.setPreferredSize(findSize);
-    findField.setMaximumSize(findSize);
-    findField.setMinimumSize(findSize);
-    findPanel.setAlignmentY(Component.CENTER_ALIGNMENT);
-    findField.setAlignmentY(Component.CENTER_ALIGNMENT);
-    
-    toolbar.add(findPanel);
-    toolbar.addSeparator(new Dimension(7, 5));
-      
-    toolbar.add(undockedFindNextButton);
-    toolbar.add(undockedFindPreviousButton);
-
-    toolbar.addSeparator();
-
+    });
     Action redockAction =
       new AbstractAction("", ChainsawIcons.ICON_DOCK) {
         public void actionPerformed(ActionEvent arg0) {
@@ -2927,7 +2941,8 @@ public class LogPanel extends DockablePa
    *
    */
   public void findNext() {
-    updateFindRule(findField.getText());
+    Object item = findCombo.getSelectedItem();
+    updateFindRule(item == null ? null: item.toString());
 
     if (findRule != null) {
         EventQueue.invokeLater(new Runnable() {
@@ -2943,10 +2958,10 @@ public class LogPanel extends DockablePa
 
                   if (nextRow > -1) {
                     table.scrollToRow(nextRow);
-                    findField.setToolTipText("Enter an expression");
+                    findCombo.setToolTipText("Enter an expression");
                   }
                 } catch (IllegalArgumentException iae) {
-                  findField.setToolTipText(iae.getMessage());
+                  findCombo.setToolTipText(iae.getMessage());
                   colorizer.setFindRule(null);
                   tableRuleMediator.setFindRule(null);
                   searchRuleMediator.setFindRule(null);
@@ -2962,7 +2977,8 @@ public class LogPanel extends DockablePa
    *
    */
   public void findPrevious() {
-    updateFindRule(findField.getText());
+    Object item = findCombo.getSelectedItem();
+    updateFindRule(item == null ? null: item.toString());
 
     if (findRule != null) {
         EventQueue.invokeLater(new Runnable() {
@@ -2977,10 +2993,10 @@ public class LogPanel extends DockablePa
 
                     if (previousRow > -1) {
                         table.scrollToRow(previousRow);
-                        findField.setToolTipText("Enter an expression");
+                        findCombo.setToolTipText("Enter an expression");
                     }
                 } catch (IllegalArgumentException iae) {
-                  findField.setToolTipText(iae.getMessage());
+                  findCombo.setToolTipText(iae.getMessage());
                 }
             }
         });
@@ -3098,10 +3114,6 @@ public class LogPanel extends DockablePa
       repaint();
     }
 
-  public JTextField getFindTextField() {
-    return findField;
-  }
-
   /**
    * Iterate over all values in the column and return the longest width
    *
@@ -3217,26 +3229,26 @@ public class LogPanel extends DockablePa
     }
 
   /**
-   * This class receives notification when the Refine focus text field is
-   * updated, where a backgrounh thread periodically wakes up and checks if
+   * This class receives notification when the Refine focus or find field is
+   * updated, where a background thread periodically wakes up and checks if
    * they have stopped typing yet. This ensures that the filtering of the
    * model is not done for every single character typed.
    *
    * @author Paul Smith psmith
    */
-  private final class DelayedFilterTextDocumentListener
+  private final class DelayedTextDocumentListener
     implements DocumentListener {
     private static final long CHECK_PERIOD = 1000;
-    private final JTextField filterText;
+    private final JTextField textField;
     private long lastTimeStamp = System.currentTimeMillis();
     private final Thread delayThread;
     private final String defaultToolTip;
-    private String lastFilterText = "";
+    private String lastText = "";
 
-    private DelayedFilterTextDocumentListener(final JTextField filterText) {
+    private DelayedTextDocumentListener(final JTextField textFeld) {
       super();
-      this.filterText = filterText;
-      this.defaultToolTip = filterText.getToolTipText();
+      this.textField = textFeld;
+      this.defaultToolTip = textFeld.getToolTipText();
 
       this.delayThread =
         new Thread(
@@ -3258,13 +3270,13 @@ public class LogPanel extends DockablePa
                   // they stopped typing recently, but have stopped for at least
                   // 1 sample period. lets apply the filter
                   //                logger.debug("Typed something recently applying filter");
-                  if (!(filterText.getText().trim().equals(lastFilterText.trim()))) {
-                    lastFilterText = filterText.getText();
+                  if (!(textFeld.getText().trim().equals(lastText.trim()))) {
+                    lastText = textFeld.getText();
                     EventQueue.invokeLater(new Runnable()
                     {
                         public void run()
                         {
-                            setFilter();
+                          setFilter();
                         }
                     });
                   }
@@ -3319,23 +3331,45 @@ public class LogPanel extends DockablePa
      * Update refinement rule based on the entered expression.
      */
     private void setFilter() {
-      if (filterText.getText().trim().equals("")) {
+      if (textField.getText().trim().equals("")) {
         //reset background color in case we were previously an invalid expression
-        filterText.setBackground(UIManager.getColor("TextField.background"));
+        textField.setBackground(UIManager.getColor("TextField.background"));
         tableRuleMediator.setFilterRule(null);
         searchRuleMediator.setFilterRule(null);
-        filterText.setToolTipText(defaultToolTip);
+        textField.setToolTipText(defaultToolTip);
+      } else {
+        try {
+          tableRuleMediator.setFilterRule(ExpressionRule.getRule(textField.getText()));
+          searchRuleMediator.setFilterRule(ExpressionRule.getRule(textField.getText()));
+          textField.setToolTipText(defaultToolTip);
+          //valid expression, reset background color in case we were previously an invalid expression
+          textField.setBackground(UIManager.getColor("TextField.background"));
+        } catch (IllegalArgumentException iae) {
+          //invalid expression, change background of the field
+          textField.setToolTipText(iae.getMessage());
+          textField.setBackground(ChainsawConstants.INVALID_EXPRESSION_BACKGROUND);
+        }
+      }
+    }
+
+    private void setFind() {
+      if (textField.getText().trim().equals("")) {
+        //reset background color in case we were previously an invalid expression
+        textField.setBackground(UIManager.getColor("TextField.background"));
+        tableRuleMediator.setFindRule(null);
+        searchRuleMediator.setFindRule(null);
+        textField.setToolTipText(defaultToolTip);
       } else {
         try {
-          tableRuleMediator.setFilterRule(ExpressionRule.getRule(filterText.getText()));
-          searchRuleMediator.setFilterRule(ExpressionRule.getRule(filterText.getText()));
-          filterText.setToolTipText(defaultToolTip);
+          tableRuleMediator.setFindRule(ExpressionRule.getRule(textField.getText()));
+          searchRuleMediator.setFindRule(ExpressionRule.getRule(textField.getText()));
+          textField.setToolTipText(defaultToolTip);
           //valid expression, reset background color in case we were previously an invalid expression
-          filterText.setBackground(UIManager.getColor("TextField.background"));
+          textField.setBackground(UIManager.getColor("TextField.background"));
         } catch (IllegalArgumentException iae) {
           //invalid expression, change background of the field
-          filterText.setToolTipText(iae.getMessage());
-          filterText.setBackground(ChainsawConstants.INVALID_EXPRESSION_BACKGROUND);
+          textField.setToolTipText(iae.getMessage());
+          textField.setBackground(ChainsawConstants.INVALID_EXPRESSION_BACKGROUND);
         }
       }
     }
@@ -4142,7 +4176,7 @@ public class LogPanel extends DockablePa
         }
     }
 
-    static class AutoFilterComboBox extends JComboBox {
+    class AutoFilterComboBox extends JComboBox {
         private boolean bypassFiltering;
         private List allEntries = new ArrayList();
         private List displayedEntries = new ArrayList();
@@ -4151,13 +4185,7 @@ public class LogPanel extends DockablePa
         private final JTextField textField = new JTextField();
         private String lastTextToMatch;
 
-        public AutoFilterComboBox(Collection entries) {
-            if (entries != null) {
-                for (Iterator iter=entries.iterator();iter.hasNext();) {
-                    Object nextObject = iter.next();
-                    model.addElement(nextObject);
-                }
-            }
+        public AutoFilterComboBox() {
             setModel(model);
             setEditor(new AutoFilterEditor());
             ((JTextField)getEditor().getEditorComponent()).getDocument().addDocumentListener(new AutoFilterDocumentListener());
@@ -4290,6 +4318,7 @@ public class LogPanel extends DockablePa
                 //assuming removal is from displayed list..remove from full list
                 Object obj = displayedEntries.get(index);
                 allEntries.remove(obj);
+                displayedEntries.remove(obj);
                 fireContentsChanged(this, 0, displayedEntries.size());
                 bypassFiltering = false;
                 refilter();

Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LoggingEventWrapper.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LoggingEventWrapper.java?rev=1023677&r1=1023676&r2=1023677&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LoggingEventWrapper.java (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LoggingEventWrapper.java Mon Oct 18 07:46:19 2010
@@ -108,9 +108,17 @@ public class LoggingEventWrapper {
     if (backgroundColor != null && foregroundColor != null) {
       this.colorRuleBackground = backgroundColor;
       this.colorRuleForeground = foregroundColor;
+      if (syncWrapper != null) {
+        syncWrapper.colorRuleBackground = this.colorRuleBackground;
+        syncWrapper.colorRuleForeground = this.colorRuleForeground;
+      }
     } else {
       this.colorRuleBackground = ChainsawConstants.COLOR_DEFAULT_BACKGROUND;
       this.colorRuleForeground = ChainsawConstants.COLOR_DEFAULT_FOREGROUND;
+      if (syncWrapper != null) {
+        syncWrapper.colorRuleBackground = this.colorRuleBackground;
+        syncWrapper.colorRuleForeground = this.colorRuleForeground;
+      }
     }
   }