/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.log4j.chainsaw;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.EOFException;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.StringReader;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.NumberFormat;
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;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.AbstractListModel;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.ComboBoxEditor;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.MutableComboBoxModel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.event.TableColumnModelEvent;
import javax.swing.event.TableColumnModelListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.text.Document;

import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.chainsaw.color.ColorPanel;
import org.apache.log4j.chainsaw.color.RuleColorizer;
import org.apache.log4j.chainsaw.filter.FilterModel;
import org.apache.log4j.chainsaw.helper.SwingHelper;
import org.apache.log4j.chainsaw.icons.ChainsawIcons;
import org.apache.log4j.chainsaw.icons.LineIconFactory;
import org.apache.log4j.chainsaw.layout.DefaultLayoutFactory;
import org.apache.log4j.chainsaw.layout.EventDetailLayout;
import org.apache.log4j.chainsaw.layout.LayoutEditorPane;
import org.apache.log4j.chainsaw.messages.MessageCenter;
import org.apache.log4j.chainsaw.prefs.LoadSettingsEvent;
import org.apache.log4j.chainsaw.prefs.Profileable;
import org.apache.log4j.chainsaw.prefs.SaveSettingsEvent;
import org.apache.log4j.chainsaw.prefs.SettingsManager;
import org.apache.log4j.chainsaw.xstream.TableColumnConverter;
import org.apache.log4j.helpers.Constants;
import org.apache.log4j.rule.ColorRule;
import org.apache.log4j.rule.ExpressionRule;
import org.apache.log4j.rule.Rule;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.LoggingEventFieldResolver;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;


/**
 * A LogPanel provides a view to a collection of LoggingEvents.<br>
 * <br>
 * As events are received, the keywords in the 'tab identifier' application
 * preference  are replaced with the values from the received event.  The
 * main application uses  this expression to route received LoggingEvents to
 * individual LogPanels which  match each event's resolved expression.<br>
 * <br>
 * The LogPanel's capabilities can be broken up into four areas:<br>
 * <ul><li> toolbar - provides 'find' and 'refine focus' features
 * <li> logger tree - displays a tree of the logger hierarchy, which can be used
 * to filter the display
 * <li> table - displays the events which pass the filtering rules
 * <li>detail panel - displays information about the currently selected event
 * </ul>
 * Here is a complete list of LogPanel's capabilities:<br>
 * <ul><li>display selected LoggingEvent row number and total LoggingEvent count
 * <li>pause or unpause reception of LoggingEvents
 * <li>configure, load and save column settings (displayed columns, order, width)
 * <li>configure, load and save color rules
 * filter displayed LoggingEvents based on the logger tree settings
 * <li>filter displayed LoggingEvents based on a 'refine focus' expression
 * (evaluates only those LoggingEvents which pass the logger tree filter
 * <li>colorize LoggingEvents based on expressions
 * <li>hide, show and configure the detail pane and tooltip
 * <li>configure the formatting of the logger, level and timestamp fields
 * <li>dock or undock
 * <li>table displays first line of exception, but when cell is clicked, a
 * popup opens to display the full stack trace
 * <li>find
 * <li>scroll to bottom
 * <li>sort
 * <li>provide a context menu which can be used to build color or display expressions
 * <li>hide or show the logger tree
 * <li>toggle the container storing the LoggingEvents to use either a
 * CyclicBuffer (defaults to max size of 5000,  but configurable  through
 * CHAINSAW_CAPACITY system property) or ArrayList (no max size)
 * <li>use the mouse context menu to 'best-fit' columns, define display
 * expression filters based on mouse location and access other capabilities
 *</ul>
 *
 *@see org.apache.log4j.chainsaw.color.ColorPanel
 *@see org.apache.log4j.rule.ExpressionRule
 *@see org.apache.log4j.spi.LoggingEventFieldResolver
 *
 *@author Scott Deboy (sdeboy at apache.org)
 *@author Paul Smith (psmith at apache.org)
 *@author Stephen Pain
 *@author Isuru Suriarachchi
 *
 */
public class LogPanel extends DockablePanel implements EventBatchListener, Profileable {
  private static final double DEFAULT_DETAIL_SPLIT_LOCATION = 0.71d;
  private static final double DEFAULT_LOG_TREE_SPLIT_LOCATION = 0.2d;
  private final String identifier;
  private final ChainsawStatusBar statusBar;
  private final JFrame logPanelPreferencesFrame = new JFrame();
  private ColorPanel colorPanel;
  private final JFrame colorFrame = new JFrame();
  private final JFrame undockedFrame;
  private final DockablePanel externalPanel;
  private final Action dockingAction;
  private final JToolBar undockedToolbar;
  private final JSortTable table;
  private final TableColorizingRenderer renderer;
  private final EventContainer tableModel;
  private final JEditorPane detail;
  private final JSplitPane lowerPanel;
  private final DetailPaneUpdater detailPaneUpdater;
  private final JPanel detailPanel = new JPanel(new BorderLayout());
  private final JSplitPane nameTreeAndMainPanelSplit;
  private final LoggerNameTreePanel logTreePanel;
  private final LogPanelPreferenceModel preferenceModel = new LogPanelPreferenceModel();
  private final LogPanelPreferencePanel logPanelPreferencesPanel = new LogPanelPreferencePanel(preferenceModel);
  private final FilterModel filterModel = new FilterModel();
  private final RuleColorizer colorizer = new RuleColorizer();
  private final RuleMediator tableRuleMediator = new RuleMediator(false);
  private final RuleMediator searchRuleMediator = new RuleMediator(true);
  private final EventDetailLayout detailLayout = new EventDetailLayout();
  private double lastDetailPanelSplitLocation = DEFAULT_DETAIL_SPLIT_LOCATION;
  private double lastLogTreePanelSplitLocation = DEFAULT_LOG_TREE_SPLIT_LOCATION;
  private Point currentPoint;
  private JTable currentTable;
  private boolean paused = false;
  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";
  static final String COLORS_EXTENSION = ".colors";
  private static final int LOG_PANEL_SERIALIZATION_VERSION_NUMBER = 2; //increment when format changes
  private int previousLastIndex = -1;
  private final DateFormat timestampExpressionFormat = new SimpleDateFormat(Constants.TIMESTAMP_RULE_FORMAT);
  private final Logger logger = LogManager.getLogger(LogPanel.class);
  private AutoFilterComboBox filterCombo;
  private JScrollPane eventsPane;
  private int currentSearchMatchCount;
  private ApplicationPreferenceModel applicationPreferenceModel;
  private Rule clearTableExpressionRule;
  private int lowerPanelDividerLocation;
  private EventContainer searchModel;
  private JSortTable searchTable;
  private TableColorizingRenderer searchRenderer;
  private ToggleToolTips mainToggleToolTips;
  private ToggleToolTips searchToggleToolTips;
  private JScrollPane detailPane;
  private JScrollPane searchPane;
  //only one tableCellEditor, shared by both tables
  private TableCellEditor markerCellEditor;
  private JToolBar detailToolbar;
  private boolean searchResultsDisplayed;

  /**
   * Creates a new LogPanel object.  If a LogPanel with this identifier has
   * been loaded previously, reload settings saved on last exit.
   *
   * @param statusBar shared status bar, provided by main application
   * @param identifier used to load and save settings
   */
  public LogPanel(final ChainsawStatusBar statusBar, final String identifier, int cyclicBufferSize,
                  Map allColorizers, ApplicationPreferenceModel applicationPreferenceModel) {
    this.identifier = identifier;
    this.statusBar = statusBar;
    this.applicationPreferenceModel = applicationPreferenceModel;
    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);

    final Map columnNameKeywordMap = new HashMap();
    columnNameKeywordMap.put(ChainsawConstants.CLASS_COL_NAME, LoggingEventFieldResolver.CLASS_FIELD);
    columnNameKeywordMap.put(ChainsawConstants.FILE_COL_NAME, LoggingEventFieldResolver.FILE_FIELD);
    columnNameKeywordMap.put(ChainsawConstants.LEVEL_COL_NAME, LoggingEventFieldResolver.LEVEL_FIELD);
    columnNameKeywordMap.put(ChainsawConstants.LINE_COL_NAME, LoggingEventFieldResolver.LINE_FIELD);
    columnNameKeywordMap.put(ChainsawConstants.LOGGER_COL_NAME, LoggingEventFieldResolver.LOGGER_FIELD);
    columnNameKeywordMap.put(ChainsawConstants.NDC_COL_NAME, LoggingEventFieldResolver.NDC_FIELD);
    columnNameKeywordMap.put(ChainsawConstants.MESSAGE_COL_NAME, LoggingEventFieldResolver.MSG_FIELD);
    columnNameKeywordMap.put(ChainsawConstants.THREAD_COL_NAME, LoggingEventFieldResolver.THREAD_FIELD);
    columnNameKeywordMap.put(ChainsawConstants.THROWABLE_COL_NAME, LoggingEventFieldResolver.EXCEPTION_FIELD);
    columnNameKeywordMap.put(ChainsawConstants.TIMESTAMP_COL_NAME, LoggingEventFieldResolver.TIMESTAMP_FIELD);
    columnNameKeywordMap.put(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE.toUpperCase(), LoggingEventFieldResolver.PROP_FIELD + ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE);
    columnNameKeywordMap.put(ChainsawConstants.MILLIS_DELTA_COL_NAME_LOWERCASE.toUpperCase(), LoggingEventFieldResolver.PROP_FIELD + ChainsawConstants.MILLIS_DELTA_COL_NAME_LOWERCASE);

    logPanelPreferencesFrame.setTitle("'" + identifier + "' Log Panel Preferences");
    logPanelPreferencesFrame.setIconImage(
      ((ImageIcon) ChainsawIcons.ICON_PREFERENCES).getImage());
    logPanelPreferencesFrame.getContentPane().add(new JScrollPane(logPanelPreferencesPanel));

    logPanelPreferencesFrame.setSize(740, 520);

    logPanelPreferencesPanel.setOkCancelActionListener(
      new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          logPanelPreferencesFrame.setVisible(false);
        }
      });

        KeyStroke escape = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false);
            Action closeLogPanelPreferencesFrameAction = new AbstractAction() {
                public void actionPerformed(ActionEvent e) {
                  logPanelPreferencesFrame.setVisible(false);
                }
            };
            logPanelPreferencesFrame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(escape, "ESCAPE"); logPanelPreferencesFrame.getRootPane().
                    getActionMap().put("ESCAPE", closeLogPanelPreferencesFrameAction);


    setDetailPaneConversionPattern(
      DefaultLayoutFactory.getDefaultPatternLayout());
      detailLayout.setConversionPattern(
      DefaultLayoutFactory.getDefaultPatternLayout());

    undockedFrame = new JFrame(identifier);
    undockedFrame.setDefaultCloseOperation(
      WindowConstants.DO_NOTHING_ON_CLOSE);

    if (ChainsawIcons.UNDOCKED_ICON != null) {
      undockedFrame.setIconImage(
        new ImageIcon(ChainsawIcons.UNDOCKED_ICON).getImage());
    }

    externalPanel = new DockablePanel();
    externalPanel.setLayout(new BorderLayout());

    undockedFrame.addWindowListener(
      new WindowAdapter() {
        public void windowClosing(WindowEvent e) {
          dock();
        }
      });

    undockedToolbar = createDockwindowToolbar();
    externalPanel.add(undockedToolbar, BorderLayout.NORTH);
    undockedFrame.getContentPane().add(externalPanel);
    undockedFrame.setSize(new Dimension(1024, 768));
    undockedFrame.pack();

    /*
     * Menus on which the preferencemodels rely
     */

    /**
     * Setup a popup menu triggered for Timestamp column to allow time stamp
     * format changes
     */
    final JPopupMenu dateFormatChangePopup = new JPopupMenu();
    final JRadioButtonMenuItem isoButton =
      new JRadioButtonMenuItem(
        new AbstractAction("Use ISO8601Format") {
          public void actionPerformed(ActionEvent e) {
            preferenceModel.setDateFormatPattern("ISO8601");
          }
        });
    final JRadioButtonMenuItem simpleTimeButton =
      new JRadioButtonMenuItem(
        new AbstractAction("Use simple time") {
          public void actionPerformed(ActionEvent e) {
            preferenceModel.setDateFormatPattern("HH:mm:ss");
          }
        });

    ButtonGroup dfBG = new ButtonGroup();
    dfBG.add(isoButton);
    dfBG.add(simpleTimeButton);
    simpleTimeButton.setSelected(true);
    dateFormatChangePopup.add(isoButton);
    dateFormatChangePopup.add(simpleTimeButton);

    final JCheckBoxMenuItem menuItemLoggerTree =
      new JCheckBoxMenuItem("Show Logger Tree");
    menuItemLoggerTree.addActionListener(
      new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          preferenceModel.setLogTreePanelVisible(
            menuItemLoggerTree.isSelected());
        }
      });
    menuItemLoggerTree.setIcon(new ImageIcon(ChainsawIcons.WINDOW_ICON));

    final JMenuItem menuItemScrollToTop = new JMenuItem("Scroll to top");
    menuItemScrollToTop.addActionListener(
      new ActionListener() {
          public void actionPerformed(ActionEvent evt)
          {
              scrollToTop();
          }
      });
    final JCheckBoxMenuItem menuItemScrollBottom =
      new JCheckBoxMenuItem("Scroll to bottom");
    menuItemScrollBottom.addActionListener(
      new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
          preferenceModel.setScrollToBottom(menuItemScrollBottom.isSelected());
        }
      });
    menuItemScrollBottom.setSelected(isScrollToBottom());

    menuItemScrollBottom.setIcon(
      new ImageIcon(ChainsawIcons.SCROLL_TO_BOTTOM));

    final JCheckBoxMenuItem menuItemToggleDetails =
      new JCheckBoxMenuItem("Show Detail Pane");
    menuItemToggleDetails.addActionListener(
      new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          preferenceModel.setDetailPaneVisible(
            menuItemToggleDetails.isSelected());
        }
      });

    menuItemToggleDetails.setIcon(new ImageIcon(ChainsawIcons.INFO));

    /*
     * add preferencemodel listeners
     */
    preferenceModel.addPropertyChangeListener("levelIcons",
      new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
          boolean useIcons = ((Boolean) evt.getNewValue()).booleanValue();
          renderer.setLevelUseIcons(useIcons);
          table.tableChanged(new TableModelEvent(tableModel));
          searchRenderer.setLevelUseIcons(useIcons);
          searchTable.tableChanged(new TableModelEvent(searchModel));
        }
      });

    /*
     * add preferencemodel listeners
     */
    preferenceModel.addPropertyChangeListener("wrapMessage",
      new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
          boolean wrap = ((Boolean) evt.getNewValue()).booleanValue();
          renderer.setWrapMessage(wrap);
          table.tableChanged(new TableModelEvent(tableModel));
          searchRenderer.setWrapMessage(wrap);
          searchTable.tableChanged(new TableModelEvent(searchModel));
        }
      });

    preferenceModel.addPropertyChangeListener("searchResultsVisible",
      new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
          boolean displaySearchResultsInDetailsIfAvailable = ((Boolean) evt.getNewValue()).booleanValue();
          if (displaySearchResultsInDetailsIfAvailable) {
            showSearchResults();
          } else {
            hideSearchResults();
          }
        }
      });

      preferenceModel.addPropertyChangeListener("highlightSearchMatchText",
        new PropertyChangeListener() {
          public void propertyChange(PropertyChangeEvent evt) {
            boolean highlightText = ((Boolean) evt.getNewValue()).booleanValue();
            renderer.setHighlightSearchMatchText(highlightText);
            table.tableChanged(new TableModelEvent(tableModel));
            searchRenderer.setHighlightSearchMatchText(highlightText);
            searchTable.tableChanged(new TableModelEvent(searchModel));
          }
        });

    preferenceModel.addPropertyChangeListener(
      "detailPaneVisible",
      new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
          boolean detailPaneVisible = ((Boolean) evt.getNewValue()).booleanValue();

          if (detailPaneVisible) {
            showDetailPane();
          } else {
            //don't hide the detail pane if search results are being displayed
            if (!searchResultsDisplayed) {
              hideDetailPane();
            }
          }
        }
      });

    preferenceModel.addPropertyChangeListener(
      "logTreePanelVisible",
      new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
          boolean newValue = ((Boolean) evt.getNewValue()).booleanValue();

          if (newValue) {
            showLogTreePanel();
          } else {
            hideLogTreePanel();
          }
        }
      });
    
    preferenceModel.addPropertyChangeListener("toolTips",
      new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
          boolean toolTips = ((Boolean) evt.getNewValue()).booleanValue();
          renderer.setToolTipsVisible(toolTips);
          searchRenderer.setToolTipsVisible(toolTips);
        }
      });

    preferenceModel.addPropertyChangeListener("visibleColumns",
      new PropertyChangeListener() {
    	public void propertyChange(PropertyChangeEvent evt) {
    		//remove all columns and re-add visible
            TableColumnModel columnModel = table.getColumnModel();
            while (columnModel.getColumnCount() > 0) {
                columnModel.removeColumn(columnModel.getColumn(0));
        		}
            for (Iterator iter = preferenceModel.getVisibleColumnOrder().iterator();iter.hasNext();) {
              TableColumn c = (TableColumn)iter.next();
              if (c.getHeaderValue().toString().toLowerCase().equals(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE))
              {
                c.setCellEditor(markerCellEditor);
              }
              columnModel.addColumn(c);
        		}
          TableColumnModel searchColumnModel = searchTable.getColumnModel();
          while (searchColumnModel.getColumnCount() > 0) {
              searchColumnModel.removeColumn(searchColumnModel.getColumn(0));
          }
          for (Iterator iter = preferenceModel.getVisibleColumnOrder().iterator();iter.hasNext();) {
            TableColumn c = (TableColumn)iter.next();
            searchColumnModel.addColumn(c);
          }
      	}
      });

    PropertyChangeListener datePrefsChangeListener =
      new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
          LogPanelPreferenceModel model = (LogPanelPreferenceModel) evt.getSource();

          isoButton.setSelected(model.isUseISO8601Format());
          simpleTimeButton.setSelected(!model.isUseISO8601Format() && !model.isCustomDateFormat());

          if (model.getTimeZone() != null) {
            renderer.setTimeZone(model.getTimeZone());
            searchRenderer.setTimeZone(model.getTimeZone());
          }
          
          if (model.isUseISO8601Format()) {
            renderer.setDateFormatter(new SimpleDateFormat(Constants.ISO8601_PATTERN));
            searchRenderer.setDateFormatter(new SimpleDateFormat(Constants.ISO8601_PATTERN));
          } else {
      		try {
              renderer.setDateFormatter(new SimpleDateFormat(model.getDateFormatPattern()));
          } catch (IllegalArgumentException iae) {
            model.setDefaultDatePatternFormat();
            renderer.setDateFormatter(new SimpleDateFormat(Constants.ISO8601_PATTERN));
          }
  		    try {
              searchRenderer.setDateFormatter(new SimpleDateFormat(model.getDateFormatPattern()));
          } catch (IllegalArgumentException iae) {
            model.setDefaultDatePatternFormat();
            searchRenderer.setDateFormatter(new SimpleDateFormat(Constants.ISO8601_PATTERN));
          }
        }

        table.tableChanged(new TableModelEvent(tableModel));
        searchTable.tableChanged(new TableModelEvent(searchModel));
        }
      };

    preferenceModel.addPropertyChangeListener("dateFormatPattern", datePrefsChangeListener);
    preferenceModel.addPropertyChangeListener("dateFormatTimeZone", datePrefsChangeListener);

    preferenceModel.addPropertyChangeListener("clearTableExpression", new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
            LogPanelPreferenceModel model = (LogPanelPreferenceModel)evt.getSource();
            String expression = model.getClearTableExpression();
            try {
                clearTableExpressionRule = ExpressionRule.getRule(expression);
                logger.info("clearTableExpressionRule set to: " + expression);
            } catch (Exception e) {
                logger.info("clearTableExpressionRule invalid - ignoring: " + expression);
                clearTableExpressionRule = null;
            }
        }
    });

    preferenceModel.addPropertyChangeListener("loggerPrecision",
      new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
          LogPanelPreferenceModel model = (LogPanelPreferenceModel) evt.getSource();

          renderer.setLoggerPrecision(model.getLoggerPrecision());
          table.tableChanged(new TableModelEvent(tableModel));

          searchRenderer.setLoggerPrecision(model.getLoggerPrecision());
          searchTable.tableChanged(new TableModelEvent(searchModel));
        }
      });

    preferenceModel.addPropertyChangeListener("toolTips",
      new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
          boolean value = ((Boolean) evt.getNewValue()).booleanValue();
          searchToggleToolTips.setSelected(value);
          mainToggleToolTips.setSelected(value);
        }
      });

    preferenceModel.addPropertyChangeListener(
      "logTreePanelVisible",
      new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
          boolean value = ((Boolean) evt.getNewValue()).booleanValue();
          menuItemLoggerTree.setSelected(value);
        }
      });

    preferenceModel.addPropertyChangeListener(
      "scrollToBottom",
      new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
          boolean value = ((Boolean) evt.getNewValue()).booleanValue();
          menuItemScrollBottom.setSelected(value);
          if (value) {
            scrollToBottom();
          }
        }
      });

    preferenceModel.addPropertyChangeListener(
      "detailPaneVisible",
      new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
          boolean value = ((Boolean) evt.getNewValue()).booleanValue();
          menuItemToggleDetails.setSelected(value);
        }
      });

    applicationPreferenceModel.addPropertyChangeListener("searchColor", new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt)
        {
            if (table != null) {
              table.repaint();
            }
            if (searchTable != null) {
              searchTable.repaint();
            }
        }
    });

    applicationPreferenceModel.addPropertyChangeListener("alternatingColor", new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt)
        {
            if (table != null) {
              table.repaint();
            }
            if (searchTable != null) {
              searchTable.repaint();
           }
        }
    });

    /*
     *End of preferenceModel listeners
     */
    tableModel = new ChainsawCyclicBufferTableModel(cyclicBufferSize, colorizer, "main");
    table = new JSortTable(tableModel);

    markerCellEditor = new MarkerCellEditor();
    table.setName("main");
    table.setColumnSelectionAllowed(false);
    table.setRowSelectionAllowed(true);

    searchModel = new ChainsawCyclicBufferTableModel(cyclicBufferSize, colorizer, "search");
    searchTable = new JSortTable(searchModel);

    searchTable.setName("search");
    searchTable.setColumnSelectionAllowed(false);
    searchTable.setRowSelectionAllowed(true);

    //we've mapped f2, shift f2 and ctrl-f2 to marker-related actions, unmap them from the table
    table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("F2"), "none");
    table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, InputEvent.SHIFT_MASK), "none");
    table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, InputEvent.CTRL_MASK), "none");
    table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, InputEvent.CTRL_MASK | InputEvent.SHIFT_MASK), "none");

    //we're also mapping ctrl-a to scroll-to-top, unmap from the table
    table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_MASK), "none");
        
    searchTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("F2"), "none");
    searchTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, InputEvent.SHIFT_MASK), "none");
    searchTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, InputEvent.CTRL_MASK), "none");
    searchTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, InputEvent.CTRL_MASK | InputEvent.SHIFT_MASK), "none");

    //we're also mapping ctrl-a to scroll-to-top, unmap from the table
    searchTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_MASK), "none");

    //add a listener to update the 'refine focus'
    tableModel.addNewKeyListener(new NewKeyListener() {
		public void newKeyAdded(NewKeyEvent e) {
          columnNameKeywordMap.put(e.getKey(), "PROP." + e.getKey());
		}
    });

    /*
     * Set the Display rule to use the mediator, the model will add itself as
     * a property change listener and update itself when the rule changes.
     */
    tableModel.setRuleMediator(tableRuleMediator);
    searchModel.setRuleMediator(searchRuleMediator);

    tableModel.addEventCountListener(
      new EventCountListener() {
        public void eventCountChanged(int currentCount, int totalCount) {
          if (LogPanel.this.isVisible()) {
            statusBar.setSelectedLine(
              table.getSelectedRow() + 1, currentCount, totalCount, getIdentifier());
          }
        }
      });

    tableModel.addEventCountListener(
      new EventCountListener() {
        final NumberFormat formatter = NumberFormat.getPercentInstance();
        boolean warning75 = false;
        boolean warning100 = false;

        public void eventCountChanged(int currentCount, int totalCount) {
          if (preferenceModel.isCyclic()) {
            double percent =
              ((double) totalCount) / ((ChainsawCyclicBufferTableModel) tableModel)
              .getMaxSize();
            String msg = null;
            boolean wasWarning = warning75 || warning100;
            if ((percent > 0.75) && (percent < 1.0) && !warning75) {
              msg =
                "Warning :: " + formatter.format(percent) + " of the '"
                + getIdentifier() + "' buffer has been used";
              warning75 = true;
            } else if ((percent >= 1.0) && !warning100) {
              msg =
                "Warning :: " + formatter.format(percent) + " of the '"
                + getIdentifier()
                + "' buffer has been used.  Older events are being discarded.";
              warning100 = true;
            } else {
                //clear msg
                msg = "";
                warning75 = false;
                warning100 = false;
            }

            if (msg != null && wasWarning) {
              MessageCenter.getInstance().getLogger().info(msg);
            }
          }
        }
      });

    /*
     * Logger tree panel
     *
     */
    LogPanelLoggerTreeModel logTreeModel = new LogPanelLoggerTreeModel();
    logTreePanel = new LoggerNameTreePanel(logTreeModel, preferenceModel, this, colorizer, filterModel);
    logTreePanel.getLoggerVisibilityRule().addPropertyChangeListener(new PropertyChangeListener()
    {
        public void propertyChange(PropertyChangeEvent evt)
        {
            if (evt.getPropertyName().equals("searchExpression")) {
                findField.setText(evt.getNewValue().toString());
                findNext();
            }
        }
    });
      
    tableModel.addLoggerNameListener(logTreeModel);
    tableModel.addLoggerNameListener(logTreePanel);

    /**
     * Set the LoggerRule to be the LoggerTreePanel, as this visual component
     * is a rule itself, and the RuleMediator will automatically listen when
     * it's rule state changes.
     */
    tableRuleMediator.setLoggerRule(logTreePanel.getLoggerVisibilityRule());
    searchRuleMediator.setLoggerRule(logTreePanel.getLoggerVisibilityRule());

    colorizer.setLoggerRule(logTreePanel.getLoggerColorRule());

    /*
     * Color rule frame and panel
     */
    colorFrame.setTitle("'" + identifier + "' color settings");
    colorFrame.setIconImage(
      ((ImageIcon) ChainsawIcons.ICON_PREFERENCES).getImage());

    allColorizers.put(identifier, colorizer);
    colorPanel = new ColorPanel(colorizer, filterModel, allColorizers, applicationPreferenceModel);

    colorFrame.getContentPane().add(colorPanel);

        Action closeColorPanelAction = new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
              colorPanel.hidePanel();
            }
        };
        colorFrame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(escape, "ESCAPE"); colorFrame.getRootPane().
                getActionMap().put("ESCAPE", closeColorPanelAction);

    colorPanel.setCloseActionListener(
      new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          colorFrame.setVisible(false);
        }
      });

    colorizer.addPropertyChangeListener(
      "colorrule",
      new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
          if (table != null) {
            table.repaint();
          }
          if (searchTable != null) {
            searchTable.repaint();
          }
        }
      });

    /*
     * Table definition.  Actual construction is above (next to tablemodel)
     */
    table.setRowHeight(ChainsawConstants.DEFAULT_ROW_HEIGHT);
    table.setRowMargin(0);
    table.getColumnModel().setColumnMargin(0);
    table.setShowGrid(false);
    table.getColumnModel().addColumnModelListener(new ChainsawTableColumnModelListener(table));
    table.setAutoCreateColumnsFromModel(false);
    table.addMouseMotionListener(new TableColumnDetailMouseListener(table, tableModel));
    table.addMouseListener(new TableMarkerListener(table, tableModel, searchModel));
    table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

    searchTable.setRowHeight(ChainsawConstants.DEFAULT_ROW_HEIGHT);
    searchTable.setRowMargin(0);
    searchTable.getColumnModel().setColumnMargin(0);
    searchTable.setShowGrid(false);
    searchTable.getColumnModel().addColumnModelListener(new ChainsawTableColumnModelListener(searchTable));
    searchTable.setAutoCreateColumnsFromModel(false);
    searchTable.addMouseMotionListener(new TableColumnDetailMouseListener(searchTable, searchModel));
    searchTable.addMouseListener(new TableMarkerListener(searchTable, searchModel, tableModel));
    searchTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);


    //set valueisadjusting if holding down a key - don't process setdetail events
    table.addKeyListener(
      new KeyListener() {
        public void keyTyped(KeyEvent e) {
        }

        public void keyPressed(KeyEvent e) {
          synchronized (detail) {
            table.getSelectionModel().setValueIsAdjusting(true);
            detail.notify();
          }
        }

        public void keyReleased(KeyEvent e) {
          synchronized (detail) {
            table.getSelectionModel().setValueIsAdjusting(false);
            detail.notify();
          }
        }
      });

    table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    searchTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

    table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
        public void valueChanged(ListSelectionEvent evt) {
            if (((evt.getFirstIndex() == evt.getLastIndex())
                && (evt.getFirstIndex() > 0) && previousLastIndex != -1) || (evt.getValueIsAdjusting())) {
              return;
            }
            boolean lastIndexOnLastRow = (evt.getLastIndex() == (table.getRowCount() - 1));
            boolean lastIndexSame = (previousLastIndex == evt.getLastIndex());

            /*
             * when scroll-to-bottom is active, here is what events look like:
             * rowcount-1: 227, last: 227, previous last: 191..first: 191
             *
             * when the user has unselected the bottom row, here is what the events look like:
             * rowcount-1: 227, last: 227, previous last: 227..first: 222
             *
             * note: previouslast is set after it is evaluated in the bypass scroll check
            */
           //System.out.println("rowcount: " + (table.getRowCount() - 1) + ", last: " + evt.getLastIndex() +", previous last: " + previousLastIndex + "..first: " + evt.getFirstIndex() + ", isadjusting: " + evt.getValueIsAdjusting());

            boolean disableScrollToBottom = (lastIndexOnLastRow && lastIndexSame && previousLastIndex != evt.getFirstIndex());
            if (disableScrollToBottom && isScrollToBottom() && table.getRowCount() > 0) {
              preferenceModel.setScrollToBottom(false);
            }
            previousLastIndex = evt.getLastIndex();
          }
        }
    );

    table.getSelectionModel().addListSelectionListener(
      new ListSelectionListener() {
        public void valueChanged(ListSelectionEvent evt) {
          if (((evt.getFirstIndex() == evt.getLastIndex())
              && (evt.getFirstIndex() > 0) && previousLastIndex != -1) || (evt.getValueIsAdjusting())) {
            return;
          }

          final ListSelectionModel lsm = (ListSelectionModel) evt.getSource();

          if (lsm.isSelectionEmpty()) {
            if (isVisible()) {
              statusBar.setNothingSelected();
            }

            if (detail.getDocument().getDefaultRootElement() != null) {
              detailPaneUpdater.setSelectedRow(-1);
            }
          } else {
            if (table.getSelectedRow() > -1) {
              int selectedRow = table.getSelectedRow();

              if (isVisible()) {
                updateStatusBar();
              }

              try {
                if (tableModel.getRowCount() >= selectedRow) {
                  detailPaneUpdater.setSelectedRow(table.getSelectedRow());
                } else {
                  detailPaneUpdater.setSelectedRow(-1);
                }
              } catch (Exception e) {
                e.printStackTrace();
                detailPaneUpdater.setSelectedRow(-1);
              }
            }
          }
        }
      });

    renderer = new TableColorizingRenderer(colorizer, applicationPreferenceModel, tableModel, preferenceModel, true);
    renderer.setToolTipsVisible(preferenceModel.isToolTips());

    table.setDefaultRenderer(Object.class, renderer);

    searchRenderer = new TableColorizingRenderer(colorizer, applicationPreferenceModel, searchModel, preferenceModel, false);
    searchRenderer.setToolTipsVisible(preferenceModel.isToolTips());

    searchTable.setDefaultRenderer(Object.class, searchRenderer);

    /*
     * Throwable popup
     */
    table.addMouseListener(new ThrowableDisplayMouseAdapter(table, tableModel));
    searchTable.addMouseListener(new ThrowableDisplayMouseAdapter(searchTable, searchModel));

    //select a row in the main table when a row in the search table is selected
    searchTable.addMouseListener(new MouseAdapter() {
      public void mouseClicked(MouseEvent e) {
        LoggingEventWrapper loggingEventWrapper = searchModel.getRow(searchTable.getSelectedRow());
        if (loggingEventWrapper != null) {
          int id = new Integer(loggingEventWrapper.getLoggingEvent().getProperty("log4jid")).intValue();
          //preserve the table's viewble column
          setSelectedEvent(id);
        }
      }
    });

    /*
     * We listen for new Key's coming in so we can get them automatically
     * added as columns
     */
    tableModel.addNewKeyListener(
      new NewKeyListener() {
        public void newKeyAdded(final NewKeyEvent e) {
        	SwingHelper.invokeOnEDT(new Runnable() {
        		public void run() {
           // don't add the column if we already know about it, this could be if we've seen it before and saved the column preferences
            //this may throw an illegalargexception - ignore it because we need to add only if not already added
        	//if the column is already added, don't add again
        	
        	try {
        	if(table.getColumn(e.getKey())!=null){
                return;
            }
            //no need to check search table - we use the same columns
        	} catch (IllegalArgumentException iae) {}
          TableColumn col = new TableColumn(e.getNewModelIndex());
          col.setHeaderValue(e.getKey());

          if (preferenceModel.addColumn(col)) {
        	  table.addColumn(col);
              searchTable.addColumn(col);
        	  preferenceModel.setColumnVisible(e.getKey().toString(), true);
          }
        		}
        	});
        }
      });

    //if the table is refiltered, try to reselect the last selected row
    //refilter with a newValue of TRUE means refiltering is about to begin
    //refilter with a newValue of FALSE means refiltering is complete
    //assuming notification is called on the EDT so we can in the current EDT call update the scroll & selection
    tableModel.addPropertyChangeListener("refilter", new PropertyChangeListener() {
        private LoggingEventWrapper currentEvent;
        public void propertyChange(PropertyChangeEvent evt) {
            //if new value is true, filtering is about to begin
            //if new value is false, filtering is complete
            if (evt.getNewValue().equals(Boolean.TRUE)) {
                int currentRow = table.getSelectedRow();
                if (currentRow > -1) {
                    currentEvent = tableModel.getRow(currentRow);
                }
            } else {
                if (currentEvent != null) {
                    table.scrollToRow(tableModel.getRowIndex(currentEvent));
                }
            }
        }
    });

    table.getTableHeader().addMouseListener(
      new MouseAdapter() {
        public void mouseClicked(MouseEvent e) {
          checkEvent(e);
        }

        public void mousePressed(MouseEvent e) {
          checkEvent(e);
        }

        public void mouseReleased(MouseEvent e) {
          checkEvent(e);
        }

        private void checkEvent(MouseEvent e) {
          if (e.isPopupTrigger()) {
            TableColumnModel colModel = table.getColumnModel();
            int index = colModel.getColumnIndexAtX(e.getX());
            int modelIndex = colModel.getColumn(index).getModelIndex();

            if ((modelIndex + 1) == ChainsawColumns.INDEX_TIMESTAMP_COL_NAME) {
              dateFormatChangePopup.show(e.getComponent(), e.getX(), e.getY());
            }
          }
        }
      });

    /*
     * Upper panel definition
     */
    JPanel upperPanel = new JPanel(new BorderLayout());
    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');

    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);

    //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));

    //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(
            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);
                        int index = filterCombo.getSelectedIndex();
                        filterCombo.setSelectedIndex(-1);
                        filterCombo.removeItemAt(index);
                    }
                }
            }
    );

    upperRightPanel.add(clearButton);

    upperPanel.add(upperRightPanel, BorderLayout.EAST);

    /*
     * Detail pane definition
     */
    detail = new JEditorPane(ChainsawConstants.DETAIL_CONTENT_TYPE, "");
    detail.setEditable(false);

    detailPaneUpdater = new DetailPaneUpdater();

    //if the panel gets focus, update the detail pane
    addFocusListener(new FocusListener() {

        public void focusGained(FocusEvent e) {
            detailPaneUpdater.updateDetailPane();
        }

        public void focusLost(FocusEvent e) {
            
        }
    });
    findMarkerRule = ExpressionRule.getRule("prop." + ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE + " exists");
        
    tableModel.addTableModelListener(new TableModelListener() {
		public void tableChanged(TableModelEvent e) {
            int currentRow = table.getSelectedRow();
            if (e.getFirstRow() <= currentRow && e.getLastRow() >= currentRow) {
                //current row has changed - update
                detailPaneUpdater.setAndUpdateSelectedRow(table.getSelectedRow());
            }
		}
    });
    addPropertyChangeListener("detailPaneConversionPattern", detailPaneUpdater);

    searchPane = new JScrollPane(searchTable);
    searchPane.getVerticalScrollBar().setUnitIncrement(ChainsawConstants.DEFAULT_ROW_HEIGHT * 2);
    searchPane.setPreferredSize(new Dimension(900, 50));

    //default detail panel to contain detail panel - if searchResultsVisible is true, when a search if triggered, update detail pane to contain search results
    detailPane = new JScrollPane(detail);
    detailPane.setPreferredSize(new Dimension(900, 50));

    detailPanel.add(detailPane, BorderLayout.CENTER);

    JPanel eventsAndStatusPanel = new JPanel(new BorderLayout());

    eventsPane = new JScrollPane(table);
    eventsPane.getVerticalScrollBar().setUnitIncrement(ChainsawConstants.DEFAULT_ROW_HEIGHT * 2);

    eventsAndStatusPanel.add(eventsPane, BorderLayout.CENTER);

    Integer scrollBarWidth = (Integer) UIManager.get("ScrollBar.width");

    JPanel rightPanel = new JPanel();
    rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS));
    JPanel rightThumbNailPanel = new ColorizedEventAndSearchMatchThumbnail();
    rightPanel.add(rightThumbNailPanel);
    //set thumbnail width to be a bit narrower than scrollbar width
    if (scrollBarWidth != null) {
        rightThumbNailPanel.setPreferredSize(new Dimension(scrollBarWidth.intValue() -4, -1));
    }
    eventsAndStatusPanel.add(rightPanel, BorderLayout.EAST);

    JPanel leftPanel = new JPanel();
    leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS));
    JPanel leftThumbNailPanel = new EventTimeDeltaMatchThumbnail();
    leftPanel.add(leftThumbNailPanel);
    //set thumbnail width to be a bit narrower than scrollbar width
    if (scrollBarWidth != null) {
        leftThumbNailPanel.setPreferredSize(new Dimension(scrollBarWidth.intValue() -4, -1));
    }
    eventsAndStatusPanel.add(leftPanel, BorderLayout.WEST);

    final JPanel statusLabelPanel = new JPanel();
    statusLabelPanel.setLayout(new BorderLayout());

    statusLabelPanel.add(upperPanel, BorderLayout.CENTER);
    eventsAndStatusPanel.add(statusLabelPanel, BorderLayout.NORTH);

    /*
     * Detail panel layout editor
     */
    detailToolbar = new JToolBar(SwingConstants.HORIZONTAL);
    detailToolbar.setFloatable(false);

    final LayoutEditorPane layoutEditorPane = new LayoutEditorPane();
    final JDialog layoutEditorDialog =
      new JDialog((JFrame) null, "Pattern Editor");
    layoutEditorDialog.getContentPane().add(layoutEditorPane);
    layoutEditorDialog.setSize(640, 480);

    layoutEditorPane.addCancelActionListener(
      new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          layoutEditorDialog.setVisible(false);
        }
      });

    layoutEditorPane.addOkActionListener(
      new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          setDetailPaneConversionPattern(
            layoutEditorPane.getConversionPattern());
          layoutEditorDialog.setVisible(false);
        }
      });

    Action copyToRefineFocusAction = new AbstractAction("Set 'refine focus' field") {
        public void actionPerformed(ActionEvent e) {
            String selectedText = detail.getSelectedText();
            if (selectedText == null || selectedText.equals("")) {
                //no-op empty searches
                return;
            }
            filterText.setText("msg ~= '" + selectedText + "'");
        }
    };

    Action copyToSearchAction = new AbstractAction("Find next") {
        public void actionPerformed(ActionEvent e) {
            String selectedText = detail.getSelectedText();
            if (selectedText == null || selectedText.equals("")) {
                //no-op empty searches
                return;
            }
            findField.setText("msg ~= '" + selectedText + "'");
            findNext();
        }
    };

    Action editDetailAction =
      new AbstractAction(
        "Edit...", new ImageIcon(ChainsawIcons.ICON_EDIT_RECEIVER)) {
        public void actionPerformed(ActionEvent e) {
          layoutEditorPane.setConversionPattern(
            getDetailPaneConversionPattern());

          Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
          Point p =
            new Point(
              ((int) ((size.getWidth() / 2)
              - (layoutEditorDialog.getSize().getWidth() / 2))),
              ((int) ((size.getHeight() / 2)
              - (layoutEditorDialog.getSize().getHeight() / 2))));
          layoutEditorDialog.setLocation(p);

          layoutEditorDialog.setVisible(true);
        }
      };

    editDetailAction.putValue(
      Action.SHORT_DESCRIPTION,
      "opens a Dialog window to Edit the Pattern Layout text");

    final SmallButton editDetailButton = new SmallButton(editDetailAction);
    editDetailButton.setText(null);
    detailToolbar.add(Box.createHorizontalGlue());
    detailToolbar.add(editDetailButton);
    detailToolbar.addSeparator();
    detailToolbar.add(Box.createHorizontalStrut(5));

    Action closeDetailAction =
      new AbstractAction(null, LineIconFactory.createCloseIcon()) {
        public void actionPerformed(ActionEvent arg0) {
          preferenceModel.setDetailPaneVisible(false);
        }
      };

    closeDetailAction.putValue(
      Action.SHORT_DESCRIPTION, "Hides the Detail Panel");

    SmallButton closeDetailButton = new SmallButton(closeDetailAction);
    detailToolbar.add(closeDetailButton);

    detailPanel.add(detailToolbar, BorderLayout.NORTH);

    lowerPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, eventsAndStatusPanel, detailPanel);

    dividerSize = lowerPanel.getDividerSize();
    lowerPanel.setDividerLocation(-1);

    lowerPanel.setResizeWeight(1.0);
    lowerPanel.setBorder(null);
    lowerPanel.setContinuousLayout(true);

    JPopupMenu editDetailPopupMenu = new JPopupMenu();

    editDetailPopupMenu.add(copyToRefineFocusAction);
    editDetailPopupMenu.add(copyToSearchAction);
    editDetailPopupMenu.addSeparator();

    editDetailPopupMenu.add(editDetailAction);
    editDetailPopupMenu.addSeparator();

    final ButtonGroup layoutGroup = new ButtonGroup();

    JRadioButtonMenuItem defaultLayoutRadio =
      new JRadioButtonMenuItem(
        new AbstractAction("Set to Default Layout") {
          public void actionPerformed(ActionEvent e) {
            setDetailPaneConversionPattern(
              DefaultLayoutFactory.getDefaultPatternLayout());
          }
        });

        JRadioButtonMenuItem fullLayoutRadio =
          new JRadioButtonMenuItem(
            new AbstractAction("Set to Full Layout") {
              public void actionPerformed(ActionEvent e) {
                setDetailPaneConversionPattern(
                  DefaultLayoutFactory.getFullPatternLayout());
              }
            });

    editDetailPopupMenu.add(defaultLayoutRadio);
    editDetailPopupMenu.add(fullLayoutRadio);

    layoutGroup.add(defaultLayoutRadio);
    layoutGroup.add(fullLayoutRadio);
    defaultLayoutRadio.setSelected(true);

    JRadioButtonMenuItem tccLayoutRadio =
      new JRadioButtonMenuItem(
        new AbstractAction("Set to TCCLayout") {
          public void actionPerformed(ActionEvent e) {
            setDetailPaneConversionPattern(
              PatternLayout.TTCC_CONVERSION_PATTERN);
          }
        });
    editDetailPopupMenu.add(tccLayoutRadio);
    layoutGroup.add(tccLayoutRadio);

    PopupListener editDetailPopupListener =
      new PopupListener(editDetailPopupMenu);
    detail.addMouseListener(editDetailPopupListener);

    /*
     * Logger tree splitpane definition
     */
    nameTreeAndMainPanelSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, logTreePanel, lowerPanel);
    nameTreeAndMainPanelSplit.setDividerLocation(-1);

    add(nameTreeAndMainPanelSplit, BorderLayout.CENTER);

    if (isLogTreeVisible()) {
        showLogTreePanel();
    } else {
        hideLogTreePanel();
    }

    /*
     * Other menu items
     */
    class BestFit extends JMenuItem {
      public BestFit() {
        super("Best fit column");
    addActionListener(
      new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
          if (currentPoint != null) {
            int column = currentTable.columnAtPoint(currentPoint);
            int maxWidth = getMaxColumnWidth(column);
            currentTable.getColumnModel().getColumn(column).setPreferredWidth(
              maxWidth);
          }
        }
      });
      }
    }

    class ColorPanel extends JMenuItem {
      public ColorPanel() {
        super("Color settings...");
        setIcon(ChainsawIcons.ICON_PREFERENCES);
  addActionListener(
      new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
          showColorPreferences();
        }
      });
      }
    }

    class LogPanelPreferences extends JMenuItem {
      public LogPanelPreferences() {
        super("Tab Preferences...");
        setIcon(ChainsawIcons.ICON_PREFERENCES);
    addActionListener(
      new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
          showPreferences();
        }
      });
    }
  }

    class FocusOn extends JMenuItem {
      public FocusOn() {
        super("Set 'refine focus' field to value under pointer");
    addActionListener(
      new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
          if (currentPoint != null) {
            String operator = "==";
            int column = currentTable.columnAtPoint(currentPoint);
            int row = currentTable.rowAtPoint(currentPoint);
            String colName = currentTable.getColumnName(column).toUpperCase();
            String value = "";

            if (colName.equalsIgnoreCase(ChainsawConstants.TIMESTAMP_COL_NAME)) {
            	value = timestampExpressionFormat.format(new Date(currentTable.getValueAt(row, column).toString()));
            } else {
              Object o = table.getValueAt(row, column);

              if (o != null) {
                if (o instanceof String[] && ((String[])o).length > 0) {
                  value = ((String[]) o)[0];
                  operator = "~=";
                } else {
                  value = o.toString();
                }
              }
            }

            if (columnNameKeywordMap.containsKey(colName)) {
              filterText.setText(
                columnNameKeywordMap.get(colName).toString() + " " + operator
                + " '" + value + "'");
            }
          }
        }
      });
      }
    }

    class DefineAddCustomFilter extends JMenuItem {
      public DefineAddCustomFilter() {
        super("Add value under pointer to 'refine focus' field");
  addActionListener(
      new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
          if (currentPoint != null) {
            String operator = "==";
            int column = currentTable.columnAtPoint(currentPoint);
            int row = currentTable.rowAtPoint(currentPoint);
            String colName = currentTable.getColumnName(column).toUpperCase();
            String value = "";

            if (colName.equalsIgnoreCase(ChainsawConstants.TIMESTAMP_COL_NAME)) {
              JComponent comp =
                (JComponent) currentTable.getCellRenderer(row, column);

              if (comp instanceof JLabel) {
                value = ((JLabel) comp).getText();
              }
            } else {
              Object o = currentTable.getValueAt(row, column);

              if (o instanceof String[] && ((String[])o).length > 0) {
                value = ((String[]) o)[0];
                operator = "~=";
              } else {
                value = o.toString();
              }
            }

            if (columnNameKeywordMap.containsKey(colName)) {
              filterText.setText(
                filterText.getText() + " && "
                + columnNameKeywordMap.get(colName).toString() + " "
                + operator + " '" + value + "'");
            }
          }
        }
      });
      }
    }

    class BuildColorRule extends JMenuItem {
      public BuildColorRule() {
        super("Define color rule for value under pointer");
      addActionListener(
      new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
          if (currentPoint != null) {
            String operator = "==";
            int column = currentTable.columnAtPoint(currentPoint);
            int row = currentTable.rowAtPoint(currentPoint);
            String colName = currentTable.getColumnName(column).toUpperCase();
            String value = "";

            if (colName.equalsIgnoreCase(ChainsawConstants.TIMESTAMP_COL_NAME)) {
              JComponent comp =
                (JComponent) currentTable.getCellRenderer(row, column);

              if (comp instanceof JLabel) {
                value = ((JLabel) comp).getText();
              }
            } else {
              Object o = currentTable.getValueAt(row, column);

              if (o instanceof String[] && ((String[])o).length > 0) {
                value = ((String[]) o)[0];
              } else {
                value = o.toString();
              }
            }

            if (columnNameKeywordMap.containsKey(colName)) {
                Color c = JColorChooser.showDialog(getRootPane(), "Choose a color", Color.red);
                if (c != null) {
                    String expression = columnNameKeywordMap.get(colName).toString() + " " + operator + " '" + value + "'";
                    colorizer.addRule(ChainsawConstants.DEFAULT_COLOR_RULE_NAME, new ColorRule(expression,
                            ExpressionRule.getRule(expression), c, ChainsawConstants.COLOR_DEFAULT_FOREGROUND));
                }
            }
          }
        }
      });
      }
    }

    final JPopupMenu mainPopup = new JPopupMenu();
    final JPopupMenu searchPopup = new JPopupMenu();

    class ClearFocus extends AbstractAction {
      public ClearFocus() {
        super("Clear 'refine focus' field");
      }
        public void actionPerformed(ActionEvent e) {
          filterText.setText(null);
          tableRuleMediator.setFilterRule(null);
          searchRuleMediator.setFilterRule(null);
        }
      }

    class Copy extends AbstractAction {
      public Copy() {
        super("Copy value under pointer to clipboard");
      }

        public void actionPerformed(ActionEvent e) {
          if (currentPoint != null) {
            int column = currentTable.columnAtPoint(currentPoint);
            int row = currentTable.rowAtPoint(currentPoint);
            String colName = currentTable.getColumnName(column).toUpperCase();
            String value = "";

            if (colName.equalsIgnoreCase(ChainsawConstants.TIMESTAMP_COL_NAME)) {
              JComponent comp =
                (JComponent) currentTable.getCellRenderer(row, column);

              if (comp instanceof JLabel) {
                value = ((JLabel) comp).getText();
              }
            } else {
              Object o = currentTable.getValueAt(row, column);
              //exception - build message + throwable
              if (o != null) {
                  if (o instanceof String[]) {
                      String[] ti = (String[])o;
                      if (ti.length > 0 && (!(ti.length == 1 && ti[0].equals("")))) {
                        LoggingEventWrapper loggingEventWrapper = ((ChainsawCyclicBufferTableModel)(currentTable.getModel())).getRow(row);
                        value = loggingEventWrapper.getLoggingEvent().getMessage().toString();
                        for (int i=0;i<((String[])o).length;i++) {
                            value = value + "\n" + ((String[]) o)[i];
                        }
                      }
                  } else {
                    value = o.toString();
                  }
              }
            }
            StringSelection selection = new StringSelection(value);
            Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
            clipboard.setContents(selection, null);
        }
      }
      }
    final JMenuItem menuItemToggleDock = new JMenuItem("Undock/dock");

    dockingAction =
      new AbstractAction("Undock") {
          public void actionPerformed(ActionEvent evt) {
            if (isDocked()) {
              undock();
            } else {
              dock();
            }
          }
        };
    dockingAction.putValue(
      Action.SMALL_ICON, new ImageIcon(ChainsawIcons.UNDOCK));
    menuItemToggleDock.setAction(dockingAction);

    /*
     * Popup definition
     */
    mainPopup.add(new FocusOn());
    searchPopup.add(new FocusOn());
    mainPopup.add(new DefineAddCustomFilter());
    searchPopup.add(new DefineAddCustomFilter());
    mainPopup.add(new ClearFocus());
    searchPopup.add(new ClearFocus());

    mainPopup.add(new JSeparator());
    searchPopup.add(new JSeparator());

    class Search extends JMenuItem {
      public Search() {
        super("Search for value under pointer");

    addActionListener(
      new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
          if (currentPoint != null) {
            String operator = "~=";
            int column = currentTable.columnAtPoint(currentPoint);
            int row = currentTable.rowAtPoint(currentPoint);
            String colName = currentTable.getColumnName(column).toUpperCase();
            String value = "";

            if (colName.equalsIgnoreCase(ChainsawConstants.TIMESTAMP_COL_NAME)) {
            	value = timestampExpressionFormat.format(new Date(currentTable.getValueAt(row, column).toString()));
            } else {
              Object o = currentTable.getValueAt(row, column);

              if (o != null) {
                if (o instanceof String[] && ((String[])o).length > 0) {
                  value = ((String[]) o)[0];
                } else {
                  value = o.toString();
                }
              }
            }

            if (columnNameKeywordMap.containsKey(colName)) {
              findField.setText(
                columnNameKeywordMap.get(colName).toString() + " " + operator
                + " '" + value + "'");
              findNext();
            }
          }
        }
      });
      }
    }

     class ClearSearch extends AbstractAction {
       public ClearSearch() {
         super("Clear search field");
       }
          public void actionPerformed(ActionEvent e) {
            findField.setText(null);
            updateFindRule(null);
          }
        }

    mainPopup.add(new Search());
    searchPopup.add(new Search());
    mainPopup.add(new ClearSearch());
    searchPopup.add(new ClearSearch());

    mainPopup.add(new JSeparator());
    searchPopup.add(new JSeparator());

    mainPopup.add(new BestFit());
    searchPopup.add(new BestFit());

    mainPopup.add(new JSeparator());
    searchPopup.add(new JSeparator());

    class DisplayNormalTimes extends JMenuItem {
      public DisplayNormalTimes() {
        super("Hide relative times");
  addActionListener(
      new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          if (currentPoint != null) {
            ((TableColorizingRenderer)currentTable.getDefaultRenderer(Object.class)).setUseNormalTimes();
            ((ChainsawCyclicBufferTableModel)currentTable.getModel()).reFilter();
            setEnabled(false);
          }
        }
    });
      }
    }

    class DisplayRelativeTimesToRowUnderCursor extends JMenuItem {
    public DisplayRelativeTimesToRowUnderCursor() {
      super("Show times relative to this event");
      addActionListener(
      new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            if (currentPoint != null) {
              int row = currentTable.rowAtPoint(currentPoint);
              ChainsawCyclicBufferTableModel cyclicBufferTableModel = (ChainsawCyclicBufferTableModel) currentTable.getModel();
              LoggingEventWrapper loggingEventWrapper = cyclicBufferTableModel.getRow(row);
              if (loggingEventWrapper != null)
              {
                  ((TableColorizingRenderer)currentTable.getDefaultRenderer(Object.class)).setUseRelativeTimes(loggingEventWrapper.getLoggingEvent().getTimeStamp());
                  cyclicBufferTableModel.reFilter();
              }
              setEnabled(true);
            }
        }
      });
    }
    }

    class DisplayRelativeTimesToPreviousRow extends JMenuItem {
      public DisplayRelativeTimesToPreviousRow() {
        super("Show times relative to previous rows");
      addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
              if (currentPoint != null) {
                ((TableColorizingRenderer)currentTable.getDefaultRenderer(Object.class)).setUseRelativeTimesToPreviousRow();
                ((ChainsawCyclicBufferTableModel)currentTable.getModel()).reFilter();
                setEnabled(true);
              }
          }
        });
      }
    }

    mainPopup.add(new DisplayRelativeTimesToRowUnderCursor());
    searchPopup.add(new DisplayRelativeTimesToRowUnderCursor());
    mainPopup.add(new DisplayRelativeTimesToPreviousRow());
    searchPopup.add(new DisplayRelativeTimesToPreviousRow());
    mainPopup.add(new DisplayNormalTimes());
    searchPopup.add(new DisplayNormalTimes());
    mainPopup.add(new JSeparator());
    searchPopup.add(new JSeparator());

    mainPopup.add(new BuildColorRule());
    searchPopup.add(new BuildColorRule());
    mainPopup.add(new Copy());
    searchPopup.add(new Copy());
    mainPopup.add(new JSeparator());
    searchPopup.add(new JSeparator());

    mainPopup.add(menuItemToggleDetails);
    mainPopup.add(menuItemLoggerTree);
    mainToggleToolTips = new ToggleToolTips();
    searchToggleToolTips = new ToggleToolTips();
    mainPopup.add(mainToggleToolTips);
    searchPopup.add(searchToggleToolTips);

    mainPopup.add(new JSeparator());
    searchPopup.add(new JSeparator());

    mainPopup.add(menuItemScrollToTop);
    mainPopup.add(menuItemScrollBottom);
    mainPopup.add(new JSeparator());

    mainPopup.add(menuItemToggleDock);

    mainPopup.add(new JSeparator());
    searchPopup.add(new JSeparator());

    mainPopup.add(new ColorPanel());
    searchPopup.add(new ColorPanel());
    mainPopup.add(new LogPanelPreferences());
    searchPopup.add(new LogPanelPreferences());

    final PopupListener mainTablePopupListener = new PopupListener(mainPopup);
    eventsPane.addMouseListener(mainTablePopupListener);
    table.addMouseListener(mainTablePopupListener);

    final PopupListener searchTablePopupListener = new PopupListener(searchPopup);
    detailPane.addMouseListener(searchTablePopupListener);
  }

  /**
   * Accessor
   *
   * @return scrollToBottom
   *
   */
  public boolean isScrollToBottom() {
  	return preferenceModel.isScrollToBottom();
  }

  public void setRefineFocusText(String refineFocusText) {
      final JTextField filterText =(JTextField) filterCombo.getEditor().getEditorComponent();
      filterText.setText(refineFocusText);
  }

  public String getRefineFocusText() {
      final JTextField filterText =(JTextField) filterCombo.getEditor().getEditorComponent();
      return filterText.getText();
  }
  /**
   * Mutator
   *
   */
  public void toggleScrollToBottom() {
  	preferenceModel.setScrollToBottom(!preferenceModel.isScrollToBottom());
  }
  
  private void scrollToBottom() {
    EventQueue.invokeLater(new Runnable()
    {
        public void run()
        {
            int scrollRow = tableModel.getRowCount() - 1;
            table.scrollToRow(scrollRow);
        }
    });
  }

  public void scrollToTop()
  {
      EventQueue.invokeLater(new Runnable() {
          public void run() {
              if (tableModel.getRowCount() > 1) {
                  table.scrollToRow(0);
              }
          }
      });
  }

  /**
   * Accessor
   *
   * @return namespace
   *
   * @see Profileable
   */
  public String getNamespace() {
    return getIdentifier();
  }

  /**
   * Accessor
   *
   * @return identifier
   *
   * @see EventBatchListener
   */
  public String getInterestedIdentifier() {
    return getIdentifier();
  }

  /**
   * Process events associated with the identifier.  Currently assumes it only
   * receives events which share this LogPanel's identifier
   *
   * @param ident identifier shared by events
   * @param events list of LoggingEvent objects
   */
  public void receiveEventBatch(String ident, final List events) {

    SwingHelper.invokeOnEDT(new Runnable() {
      public void run() {
        /*
        * if this panel is paused, we totally ignore events
        */
        if (isPaused()) {
          return;
        }
        final int selectedRow = table.getSelectedRow();
        final int startingRow = table.getRowCount();
        final LoggingEventWrapper selectedEvent;
        if (selectedRow >= 0) {
          selectedEvent = tableModel.getRow(selectedRow);
        } else {
          selectedEvent = null;
        }

        final int startingSearchRow = searchTable.getRowCount();

        boolean rowAdded = false;
        boolean searchRowAdded = false;

        int addedRowCount = 0;
        int searchAddedRowCount = 0;

        for (Iterator iter = events.iterator(); iter.hasNext();) {
          //these are actual LoggingEvent instances
          LoggingEvent event = (LoggingEvent)iter.next();
          //create two separate loggingEventWrappers (main table and search table), as they have different info on display state
          LoggingEventWrapper loggingEventWrapper1 = new LoggingEventWrapper(event, tableModel);
            //if the clearTableExpressionRule is not null, evaluate & clear the table if it matches
            if (clearTableExpressionRule != null && clearTableExpressionRule.evaluate(event, null)) {
                logger.info("clear table expression matched - clearing table - matching event msg - " + event.getMessage());
                clearEvents();
            }

          updateOtherModels(event);
          boolean isCurrentRowAdded = tableModel.isAddRow(loggingEventWrapper1);
          if (isCurrentRowAdded) {
              addedRowCount++;
          }
          rowAdded = rowAdded || isCurrentRowAdded;

          //create a new loggingEventWrapper via copy constructor to ensure same IDs
          LoggingEventWrapper loggingEventWrapper2 = new LoggingEventWrapper(loggingEventWrapper1, searchModel);
          boolean isSearchCurrentRowAdded = searchModel.isAddRow(loggingEventWrapper2);
          if (isSearchCurrentRowAdded) {
              searchAddedRowCount++;
          }
          searchRowAdded = searchRowAdded || isSearchCurrentRowAdded;
        }
        //fire after adding all events
        if (rowAdded) {
          tableModel.fireTableEvent(startingRow, startingRow + addedRowCount, addedRowCount);
        }
        if (searchRowAdded) {
          searchModel.fireTableEvent(startingSearchRow, startingSearchRow + searchAddedRowCount, searchAddedRowCount);
        }

        //tell the model to notify the count listeners
        tableModel.notifyCountListeners();

        if (rowAdded) {
          if (tableModel.isSortEnabled()) {
            tableModel.sort();
          }

          //always update detail pane (since we may be using a cyclic buffer which is full)
          detailPaneUpdater.setSelectedRow(table.getSelectedRow());
        }

        if (searchRowAdded) {
          if (searchModel.isSortEnabled()) {
            searchModel.sort();
          }
        }

        if (!isScrollToBottom() && selectedEvent != null) {
          final int newIndex = tableModel.getRowIndex(selectedEvent);
          if (newIndex >= 0) {
            // Don't scroll, just maintain selection...
            table.setRowSelectionInterval(newIndex, newIndex);
          }
        }
      }
    });
  }

  /**
   * Load settings from the panel preference model
   *
   * @param event
   *
   * @see LogPanelPreferenceModel
   */
  public void loadSettings(LoadSettingsEvent event) {

    File xmlFile = new File(SettingsManager.getInstance()
                .getSettingsDirectory(), URLEncoder.encode(identifier) + ".xml");

    if (xmlFile.exists()) {
        XStream stream = buildXStreamForLogPanelPreference();
        ObjectInputStream in = null;
        try {
            FileReader r = new FileReader(xmlFile);
            in = stream.createObjectInputStream(r);
            LogPanelPreferenceModel storedPrefs = (LogPanelPreferenceModel)in.readObject();
            lowerPanelDividerLocation = in.readInt();
            int treeDividerLocation = in.readInt();
            String conversionPattern = in.readObject().toString();
            Point p = (Point)in.readObject();
            Dimension d = (Dimension)in.readObject();
            //this version number is checked to identify whether there is a Vector comming next
            int versionNumber = 0;
            try {
                versionNumber = in.readInt();
            } catch (EOFException eof){
            }

            Vector savedVector;
            //read the vector only if the version number is greater than 0. higher version numbers can be
            //used in the future to save more data structures
            if (versionNumber > 0) {
                savedVector = (Vector) in.readObject();
                for(int i = 0 ; i < savedVector.size() ; i++){
                    Object item = savedVector.get(i);
                    //insert each row at index zero (so last row in vector will be row zero)
                    filterCombo.insertItemAt(item, 0);
                }
                if (versionNumber > 1) {
                    //update prefModel columns to include defaults
                    int index = 0;
                    String columnOrder = event.getSetting(TABLE_COLUMN_ORDER);
                    StringTokenizer tok = new StringTokenizer(columnOrder, ",");
                    while (tok.hasMoreElements()) {
                      String element = tok.nextElement().toString().trim().toUpperCase();
                      TableColumn column = new TableColumn(index++);
                      column.setHeaderValue(element);
                      preferenceModel.addColumn(column);
                    }

                    TableColumnModel columnModel = table.getColumnModel();
                    //remove previous columns
                    while (columnModel.getColumnCount() > 0) {
                        columnModel.removeColumn(columnModel.getColumn(0));
                    }
                    //add visible column order columns
                    for (Iterator iter = preferenceModel.getVisibleColumnOrder().iterator();iter.hasNext();) {
                        TableColumn col = (TableColumn)iter.next();
                        columnModel.addColumn(col);
                    }

                  TableColumnModel searchColumnModel = searchTable.getColumnModel();
                  //remove previous columns
                  while (searchColumnModel.getColumnCount() > 0) {
                      searchColumnModel.removeColumn(searchColumnModel.getColumn(0));
                  }
                  //add visible column order columns
                  for (Iterator iter = preferenceModel.getVisibleColumnOrder().iterator();iter.hasNext();) {
                      TableColumn col = (TableColumn)iter.next();
                      searchColumnModel.addColumn(col);
                  }

                    preferenceModel.apply(storedPrefs);
                } else {
                    loadDefaultColumnSettings(event);
                }
                //ensure tablemodel cyclic flag is updated
                tableModel.setCyclic(preferenceModel.isCyclic());
                searchModel.setCyclic(preferenceModel.isCyclic());
                //may be panel configs that don't have these values
                lowerPanel.setDividerLocation(lowerPanelDividerLocation);
                nameTreeAndMainPanelSplit.setDividerLocation(treeDividerLocation);
                detailLayout.setConversionPattern(conversionPattern);
                if (p.x != 0 && p.y != 0) {
                    undockedFrame.setLocation(p.x, p.y);
                    undockedFrame.setSize(d);
                } else {
                    undockedFrame.setLocation(0, 0);
                    undockedFrame.setSize(new Dimension(1024, 768));
                }
            } else {
                loadDefaultColumnSettings(event);
            }
        } catch (Exception e) {
            e.printStackTrace();
            loadDefaultColumnSettings(event);
            // TODO need to log this..
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException ioe) {}
            }
        }
    } else {
        loadDefaultColumnSettings(event);
    }

    logTreePanel.ignore(preferenceModel.getHiddenLoggers());
    logTreePanel.setHiddenExpression(preferenceModel.getHiddenExpression());
    if (preferenceModel.getClearTableExpression() != null) {
        try {
            clearTableExpressionRule = ExpressionRule.getRule(preferenceModel.getClearTableExpression());
        } catch (Exception e) {
            clearTableExpressionRule = null;
        }
    }

    //attempt to load color settings - no need to URL encode the identifier
    colorizer.loadColorSettings(identifier);
  }

  /**
   * Save preferences to the panel preference model
   *
   * @param event
   *
   * @see LogPanelPreferenceModel
   */
  public void saveSettings(SaveSettingsEvent event) {
      File xmlFile = new File(SettingsManager.getInstance()
              .getSettingsDirectory(), URLEncoder.encode(identifier) + ".xml");

    preferenceModel.setHiddenLoggers(new HashSet(logTreePanel.getHiddenSet()));
    preferenceModel.setHiddenExpression(logTreePanel.getHiddenExpression());
    List visibleOrder = new ArrayList();
    Enumeration cols = table.getColumnModel().getColumns();
    while (cols.hasMoreElements()) {
    	TableColumn c = (TableColumn)cols.nextElement();
    	visibleOrder.add(c);
    }
    preferenceModel.setVisibleColumnOrder(visibleOrder);
    //search table will use same columns as main table
    
    XStream stream = buildXStreamForLogPanelPreference();
    ObjectOutputStream s = null;
    try {
    	FileWriter w = new FileWriter(xmlFile);
    	s = stream.createObjectOutputStream(w);
    	s.writeObject(preferenceModel);
        if (lowerPanelDividerLocation == 0) {
            //pick a reasonable default
            s.writeInt((int) (lowerPanel.getSize().height * DEFAULT_DETAIL_SPLIT_LOCATION));
        } else {
            s.writeInt(lowerPanelDividerLocation);
        }
    	s.writeInt(nameTreeAndMainPanelSplit.getDividerLocation());
    	s.writeObject(detailLayout.getConversionPattern());
    	s.writeObject(undockedFrame.getLocation());
    	s.writeObject(undockedFrame.getSize());
        //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());
    } catch (Exception ex) {
        ex.printStackTrace();
        // TODO need to log this..
    } finally {
    	if (s != null) {
    		try {
    			s.close();
    		} catch (IOException ioe) {}
    	}
    }

    //no need to URL encode the identifier
    colorizer.saveColorSettings(identifier);
  }

    private XStream buildXStreamForLogPanelPreference() {
        XStream stream = new XStream(new DomDriver());
        stream.registerConverter(new TableColumnConverter());
        return stream;
    }

  /**
     * Display the panel preferences frame
     */
  void showPreferences() {
      //don't pack this frame
      centerAndSetVisible(logPanelPreferencesFrame);
  }

  public static void centerAndSetVisible(Window window) {
    Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
    window.setLocation(new Point((screenDimension.width / 2) - (window.getSize().width / 2),
      (screenDimension.height / 2) - (window.getSize().height / 2)));
    window.setVisible(true);
  }

  /**
   * Display the color rule frame
   */
  void showColorPreferences() {
    colorPanel.loadLogPanelColorizers();
    colorFrame.pack();
    centerAndSetVisible(colorFrame);
  }

  /**
   * Toggle panel preference for detail visibility on or off
   */
  void toggleDetailVisible() {
    preferenceModel.setDetailPaneVisible(
      !preferenceModel.isDetailPaneVisible());
  }

  /**
   * Accessor
   *
   * @return detail visibility flag
   */
  boolean isDetailVisible() {
    return preferenceModel.isDetailPaneVisible();
  }

  boolean isSearchResultsVisible() {
    return preferenceModel.isSearchResultsVisible();
  }

  /**
   * Toggle panel preference for logger tree visibility on or off
   */
  void toggleLogTreeVisible() {
    preferenceModel.setLogTreePanelVisible(
      !preferenceModel.isLogTreePanelVisible());
  }

  /**
   * Accessor
   *
   * @return logger tree visibility flag
   */
  boolean isLogTreeVisible() {
    return preferenceModel.isLogTreePanelVisible();
  }

  /**
   * Return all events
   *
   * @return list of LoggingEvents
   */
  List getEvents() {
    return tableModel.getAllEvents();
  }

  /**
   * Return the events that are visible with the current filter applied
   *
   * @return list of LoggingEvents
   */
  List getFilteredEvents() {
  	return tableModel.getFilteredEvents();
  }
  
  List getMatchingEvents(Rule rule) {
    return tableModel.getMatchingEvents(rule);
  }

  /**
   * Remove all events
   */
  void clearEvents() {
    clearModel();
  }

  /**
   * Accessor
   *
   * @return identifier
   */
  String getIdentifier() {
    return identifier;
  }

  /**
   * Undocks this DockablePanel by removing the panel from the LogUI window
   * and placing it inside it's own JFrame.
   */
  void undock() {
  	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);
    externalPanel.setDocked(false);
    undockedFrame.pack();

    undockedFrame.setVisible(true);
    dockingAction.putValue(Action.NAME, "Dock");
    dockingAction.putValue(Action.SMALL_ICON, ChainsawIcons.ICON_DOCK);
    if (row > -1) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                table.scrollToRow(row);
            }
        });
    }
  }

  /**
   * Add an eventCountListener
   *
   * @param l
   */
  void addEventCountListener(EventCountListener l) {
    tableModel.addEventCountListener(l);
  }

  /**
   * Accessor
   *
   * @return paused flag
   */
  boolean isPaused() {
    return paused;
  }

  /**
   * Modifies the Paused property and notifies the listeners
   *
   * @param paused
   */
  void setPaused(boolean paused) {
    boolean oldValue = this.paused;
    this.paused = paused;
    firePropertyChange("paused", oldValue, paused);
  }

  /**
   * Change the selected event on the log panel.  Will cause scrollToBottom to be turned off.
   *
   * @param eventNumber
   * @return row number or -1 if row with log4jid property with that number was not found
   */
  int setSelectedEvent(int eventNumber) {
      int row = tableModel.locate(ExpressionRule.getRule("prop.log4jid == " + eventNumber), 0, true);
      if (row > -1) {
        preferenceModel.setScrollToBottom(false);

        table.scrollToRow(row);
      }
      return row;
  }

  /**
   * Add a preference propertyChangeListener
   *
   * @param listener
   */
  void addPreferencePropertyChangeListener(PropertyChangeListener listener) {
    preferenceModel.addPropertyChangeListener(listener);
  }

  /**
   * Toggle the LoggingEvent container from either managing a cyclic buffer of
   * events or an ArrayList of events
   */
  void toggleCyclic() {
    boolean toggledCyclic = !preferenceModel.isCyclic();

    preferenceModel.setCyclic(toggledCyclic);
    tableModel.setCyclic(toggledCyclic);
    searchModel.setCyclic(toggledCyclic);
  }

  /**
   * Accessor
   *
   * @return flag answering if LoggingEvent container is a cyclic buffer
   */
  boolean isCyclic() {
    return preferenceModel.isCyclic();
  }

  public void updateFindRule(String ruleText) {
    if ((ruleText == null) || (ruleText.trim().equals(""))) {
      findRule = null;
      tableModel.updateEventsWithFindRule(null);
      colorizer.setFindRule(null);
      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(
        "Enter expression - right click or ctrl-space for menu");
      currentSearchMatchCount = 0;
      currentFindRuleText = null;
      statusBar.setSearchMatchCount(currentSearchMatchCount, getIdentifier());
      //if the preference to show search results is enabled, the find rule is now null - hide search results
      if (isSearchResultsVisible()) {
        hideSearchResults();
      }
    } else {
      //only turn off scrolltobottom when finding something (find not empty)
      preferenceModel.setScrollToBottom(false);
      if(ruleText.equals(currentFindRuleText)) {
          //don't update events if rule hasn't changed (we're finding next/previous)
          return;
      }
      currentFindRuleText = ruleText;
      try {
        findField.setToolTipText(
          "Enter expression - right click or ctrl-space for menu");
        findRule = ExpressionRule.getRule(ruleText);
        currentSearchMatchCount = tableModel.updateEventsWithFindRule(findRule);
        searchModel.updateEventsWithFindRule(findRule);
        colorizer.setFindRule(findRule);
        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"));
        statusBar.setSearchMatchCount(currentSearchMatchCount, getIdentifier());
        if (isSearchResultsVisible()) {
          showSearchResults();
        }
      } catch (IllegalArgumentException re) {
        findRule = null;
        findField.setToolTipText(re.getMessage());
        findField.setBackground(ChainsawConstants.INVALID_EXPRESSION_BACKGROUND);
        colorizer.setFindRule(null);
        tableRuleMediator.setFindRule(null);
        searchRuleMediator.setFindRule(null);
        tableModel.updateEventsWithFindRule(null);
        searchModel.updateEventsWithFindRule(null);
        currentSearchMatchCount = 0;
        statusBar.setSearchMatchCount(currentSearchMatchCount, getIdentifier());
        //if the preference to show search results is enabled, the find rule is now null - hide search results
        if (isSearchResultsVisible()) {
          hideSearchResults();
        }
      }
    }
  }

  private void hideSearchResults() {
    if (searchResultsDisplayed) {
      detailPanel.removeAll();
      detailPanel.add(detailToolbar, BorderLayout.NORTH);
      detailPanel.add(detailPane, BorderLayout.CENTER);
      detailPanel.invalidate();
      detailPanel.revalidate();
      detailPanel.repaint();
      //if the detail visible pref is not enabled, hide the detail pane
      searchResultsDisplayed = false;
      //hide if pref is not enabled
      if (!isDetailVisible()) {
        hideDetailPane();
      }
    }
  }

  private void showSearchResults() {
    if (isSearchResultsVisible() && !searchResultsDisplayed && findRule != null) {
      //if pref is set, always update detail panel to contain search results
      detailPanel.removeAll();
      detailPanel.add(searchPane, BorderLayout.CENTER);
      detailPanel.invalidate();
      detailPanel.revalidate();
      detailPanel.repaint();
      //if the detail visible pref is not enabled, show the detail pane
      searchResultsDisplayed = true;
      //show if pref is not enabled
      if (!isDetailVisible()) {
        showDetailPane();
      }
    }
  }

  /**
   * Display the detail pane, using the last known divider location
   */
  private void showDetailPane() {
    lowerPanel.setDividerSize(dividerSize);
      if (lowerPanelDividerLocation != 0) {
          lowerPanel.setDividerLocation(lowerPanelDividerLocation);
      } else {
          lowerPanel.setDividerLocation(lastDetailPanelSplitLocation);
      }
      detailPanel.setVisible(true);
      detailPanel.repaint();
      lowerPanel.repaint();
  }

  /**
   * Hide the detail pane, holding the current divider location for later use
   */
  private void hideDetailPane() {
    int currentSize = lowerPanel.getHeight() - lowerPanel.getDividerSize();

    if (currentSize > 0) {
      lastDetailPanelSplitLocation =
        (double) lowerPanel.getDividerLocation() / currentSize;
     }
     if (lowerPanel.getDividerLocation() > 0) {
        lowerPanelDividerLocation = lowerPanel.getDividerLocation();
     }

    lowerPanel.setDividerSize(0);
    detailPanel.setVisible(false);
    lowerPanel.repaint();
  }

  /**
   * Display the log tree pane, using the last known divider location
   */
  private void showLogTreePanel() {
    nameTreeAndMainPanelSplit.setDividerSize(dividerSize);
    nameTreeAndMainPanelSplit.setDividerLocation(
      lastLogTreePanelSplitLocation);
    logTreePanel.setVisible(true);
    nameTreeAndMainPanelSplit.repaint();
  }

  /**
   * Hide the log tree pane, holding the current divider location for later use
   */
  private void hideLogTreePanel() {
    //subtract one to make sizes match
    int currentSize = nameTreeAndMainPanelSplit.getWidth() - nameTreeAndMainPanelSplit.getDividerSize() - 1;

    if (currentSize > 0) {
      lastLogTreePanelSplitLocation =
        (double) nameTreeAndMainPanelSplit.getDividerLocation() / currentSize;
    }
    nameTreeAndMainPanelSplit.setDividerSize(0);
    logTreePanel.setVisible(false);
    nameTreeAndMainPanelSplit.repaint();
  }

  /**
   * Return a toolbar used by the undocked LogPanel's frame
   *
   * @return toolbar
   */
  private JToolBar createDockwindowToolbar() {
    final JToolBar toolbar = new JToolBar();
    toolbar.setFloatable(false);

    final Action dockPauseAction =
      new AbstractAction("Pause") {
        public void actionPerformed(ActionEvent evt) {
          setPaused(!isPaused());
        }
      };

    dockPauseAction.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_P));
    dockPauseAction.putValue(
      Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("F12"));
    dockPauseAction.putValue(
      Action.SHORT_DESCRIPTION,
      "Halts the display, while still allowing events to stream in the background");
    dockPauseAction.putValue(
      Action.SMALL_ICON, new ImageIcon(ChainsawIcons.PAUSE));

    final SmallToggleButton dockPauseButton =
      new SmallToggleButton(dockPauseAction);
    dockPauseButton.setText("");

    dockPauseButton.getModel().setSelected(isPaused());

    addPropertyChangeListener(
      "paused",
      new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
          dockPauseButton.getModel().setSelected(isPaused());
        }
      });
    toolbar.add(dockPauseButton);

    Action dockShowPrefsAction =
      new AbstractAction("") {
        public void actionPerformed(ActionEvent arg0) {
          showPreferences();
        }
      };

    dockShowPrefsAction.putValue(
      Action.SHORT_DESCRIPTION, "Define preferences...");
    dockShowPrefsAction.putValue(
      Action.SMALL_ICON, ChainsawIcons.ICON_PREFERENCES);

    toolbar.add(new SmallButton(dockShowPrefsAction));

    Action dockToggleLogTreeAction =
      new AbstractAction() {
        public void actionPerformed(ActionEvent e) {
          toggleLogTreeVisible();
        }
      };

      dockToggleLogTreeAction.putValue(Action.SHORT_DESCRIPTION, "Toggles the Logger Tree Pane");
      dockToggleLogTreeAction.putValue("enabled", Boolean.TRUE);
      dockToggleLogTreeAction.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_T));
      dockToggleLogTreeAction.putValue(
        Action.ACCELERATOR_KEY,
        KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.ALT_MASK));
      dockToggleLogTreeAction.putValue(
        Action.SMALL_ICON, new ImageIcon(ChainsawIcons.WINDOW_ICON));

    final SmallToggleButton toggleLogTreeButton =
      new SmallToggleButton(dockToggleLogTreeAction);
    preferenceModel.addPropertyChangeListener("logTreePanelVisible", new PropertyChangeListener() {
    	public void propertyChange(PropertyChangeEvent evt) {
    	    toggleLogTreeButton.setSelected(preferenceModel.isLogTreePanelVisible());    		
    	}
    });
    		
    toggleLogTreeButton.setSelected(isLogTreeVisible());
    toolbar.add(toggleLogTreeButton);
    toolbar.addSeparator();

    final Action undockedClearAction =
      new AbstractAction("Clear") {
        public void actionPerformed(ActionEvent arg0) {
          clearModel();
        }
      };

    undockedClearAction.putValue(
      Action.SMALL_ICON, new ImageIcon(ChainsawIcons.DELETE));
    undockedClearAction.putValue(
      Action.SHORT_DESCRIPTION, "Removes all the events from the current view");

    final SmallButton dockClearButton = new SmallButton(undockedClearAction);
    dockClearButton.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
      KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, InputEvent.CTRL_MASK),
      undockedClearAction.getValue(Action.NAME));
    dockClearButton.getActionMap().put(
      undockedClearAction.getValue(Action.NAME), undockedClearAction);

    dockClearButton.setText("");
    toolbar.add(dockClearButton);
    toolbar.addSeparator();

    Action dockToggleScrollToBottomAction =
        new AbstractAction("Toggles Scroll to Bottom") {
          public void actionPerformed(ActionEvent e) {
            toggleScrollToBottom();
          }
        };

        dockToggleScrollToBottomAction.putValue(Action.SHORT_DESCRIPTION, "Toggles Scroll to Bottom");
        dockToggleScrollToBottomAction.putValue("enabled", Boolean.TRUE);
        dockToggleScrollToBottomAction.putValue(
          Action.SMALL_ICON, new ImageIcon(ChainsawIcons.SCROLL_TO_BOTTOM));

      final SmallToggleButton toggleScrollToBottomButton =
        new SmallToggleButton(dockToggleScrollToBottomAction);
      preferenceModel.addPropertyChangeListener("scrollToBottom", new PropertyChangeListener() {
      	public void propertyChange(PropertyChangeEvent evt) {
      	    toggleScrollToBottomButton.setSelected(isScrollToBottom());    		
      	}
      });

      toggleScrollToBottomButton.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
  	      KeyStroke.getKeyStroke(KeyEvent.VK_B, InputEvent.CTRL_MASK),
  	      dockToggleScrollToBottomAction.getValue(Action.NAME));
  	    toggleScrollToBottomButton.getActionMap().put(
  	      dockToggleScrollToBottomAction.getValue(Action.NAME), dockToggleScrollToBottomAction);
      
      toggleScrollToBottomButton.setSelected(isScrollToBottom());
      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() {
        public void actionPerformed(ActionEvent e) {
          findPrevious();
        }
      };

    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) {
          dock();
        }
      };

    redockAction.putValue(
      Action.SHORT_DESCRIPTION,
      "Docks this window back with the main Chainsaw window");

    SmallButton redockButton = new SmallButton(redockAction);
    toolbar.add(redockButton);

    return toolbar;
  }

  /**
   * Update the status bar with current selected row and row count
   */
  protected void updateStatusBar() {
    SwingHelper.invokeOnEDT(
      new Runnable() {
        public void run() {
          statusBar.setSelectedLine(
            table.getSelectedRow() + 1, tableModel.getRowCount(),
            tableModel.size(), getIdentifier());
          statusBar.setSearchMatchCount(currentSearchMatchCount, getIdentifier());
        }
      });
  }

  /**
   * Update the detail pane layout text
   *
   * @param conversionPattern layout text
   */
  private void setDetailPaneConversionPattern(String conversionPattern) {
    String oldPattern = getDetailPaneConversionPattern();
    (detailLayout).setConversionPattern(conversionPattern);
    firePropertyChange(
      "detailPaneConversionPattern", oldPattern,
      getDetailPaneConversionPattern());
  }

  /**
   * Accessor
   *
   * @return conversionPattern layout text
   */
  private String getDetailPaneConversionPattern() {
    return (detailLayout).getConversionPattern();
  }

  /**
   * Reset the LoggingEvent container, detail panel and status bar
   */
  private void clearModel() {
    previousLastIndex = -1;
    tableModel.clearModel();
    searchModel.clearModel();

    synchronized (detail) {
      detailPaneUpdater.setSelectedRow(-1);
      detail.notify();
    }

    statusBar.setNothingSelected();
  }

  public void findNextColorizedEvent() {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            final int nextRow = tableModel.findColoredRow(table.getSelectedRow() + 1, true);
            if (nextRow > -1) {
                table.scrollToRow(nextRow);
            }
        }
    });
  }

  public void findPreviousColorizedEvent() {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            final int previousRow = tableModel.findColoredRow(table.getSelectedRow() - 1, false);
            if (previousRow > -1) {
                table.scrollToRow(previousRow);
            }
        }
    });
  }

  /**
   * Finds the next row matching the current find rule, and ensures it is made
   * visible
   *
   */
  public void findNext() {
    updateFindRule(findField.getText());

    if (findRule != null) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                  int filteredEventsSize = getFilteredEvents().size();
                  int startRow = table.getSelectedRow() + 1;
                    if (startRow > filteredEventsSize - 1) {
                        startRow = 0;
                    }
                  //no selected row would return -1, so we'd start at row zero
                  final int nextRow = tableModel.locate(findRule, startRow, true);

                  if (nextRow > -1) {
                    table.scrollToRow(nextRow);
                    findField.setToolTipText("Enter an expression");
                  }
                } catch (IllegalArgumentException iae) {
                  findField.setToolTipText(iae.getMessage());
                  colorizer.setFindRule(null);
                  tableRuleMediator.setFindRule(null);
                  searchRuleMediator.setFindRule(null);
                }
            }
        });
    }
  }

  /**
   * Finds the previous row matching the current find rule, and ensures it is made
   * visible
   *
   */
  public void findPrevious() {
    updateFindRule(findField.getText());

    if (findRule != null) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    int startRow = table.getSelectedRow() - 1;
                    int filteredEventsSize = getFilteredEvents().size();
                    if (startRow < 0) {
                        startRow = filteredEventsSize - 1;
                    }
                    final int previousRow = tableModel.locate(findRule, startRow, false);

                    if (previousRow > -1) {
                        table.scrollToRow(previousRow);
                        findField.setToolTipText("Enter an expression");
                    }
                } catch (IllegalArgumentException iae) {
                  findField.setToolTipText(iae.getMessage());
                }
            }
        });
    }
  }

  /**
   * Docks this DockablePanel by hiding the JFrame and placing the Panel back
   * inside the LogUI window.
   */
  private void dock() {
  	
  	final int row = table.getSelectedRow();
    setDocked(true);
    undockedFrame.setVisible(false);
    removeAll();

    add(nameTreeAndMainPanelSplit, BorderLayout.CENTER);
    externalPanel.setDocked(true);
    dockingAction.putValue(Action.NAME, "Undock");
    dockingAction.putValue(Action.SMALL_ICON, ChainsawIcons.ICON_UNDOCK);
    if (row > -1) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                table.scrollToRow(row);
            }
        });
    }
  }

  /**
   * Load default column settings if no settings exist for this identifier
   *
   * @param event
   */
  private void loadDefaultColumnSettings(LoadSettingsEvent event) {
    String columnOrder = event.getSetting(TABLE_COLUMN_ORDER);

    TableColumnModel columnModel = table.getColumnModel();
    TableColumnModel searchColumnModel = searchTable.getColumnModel();

    Map columnNameMap = new HashMap();
    Map searchColumnNameMap = new HashMap();

    for (int i = 0; i < columnModel.getColumnCount(); i++) {
      columnNameMap.put(table.getColumnName(i).toUpperCase(), columnModel.getColumn(i));
    }

    for (int i = 0; i < searchColumnModel.getColumnCount(); i++) {
      searchColumnNameMap.put(searchTable.getColumnName(i).toUpperCase(), searchColumnModel.getColumn(i));
    }

    int index = 0;
    StringTokenizer tok = new StringTokenizer(columnOrder, ",");
    List sortedColumnList = new ArrayList();

    /*
       remove all columns from the table that exist in the model
       and add in the correct order to a new arraylist
       (may be a subset of possible columns)
     **/
    while (tok.hasMoreElements()) {
      String element = tok.nextElement().toString().trim().toUpperCase();
      TableColumn column = (TableColumn) columnNameMap.get(element);

      if (column != null) {
        sortedColumnList.add(column);
        table.removeColumn(column);
        searchTable.removeColumn(column);
      }
    }
    preferenceModel.setDetailPaneVisible(event.asBoolean("detailPaneVisible"));
    preferenceModel.setLogTreePanelVisible(event.asBoolean("logTreePanelVisible"));
    preferenceModel.setHighlightSearchMatchText(event.asBoolean("highlightSearchMatchText"));
    preferenceModel.setWrapMessage(event.asBoolean("wrapMessage"));
    preferenceModel.setSearchResultsVisible(event.asBoolean("searchResultsVisible"));
    //re-add columns to the table in the order provided from the list
    for (Iterator iter = sortedColumnList.iterator(); iter.hasNext();) {
      TableColumn element = (TableColumn) iter.next();
      if (preferenceModel.addColumn(element)) {
          table.addColumn(element);
          searchTable.addColumn(element);
    	  preferenceModel.setColumnVisible(element.getHeaderValue().toString(), true);
      }
    }

    String columnWidths = event.getSetting(TABLE_COLUMN_WIDTHS);

    tok = new StringTokenizer(columnWidths, ",");
    index = 0;

    while (tok.hasMoreElements()) {
      String element = (String) tok.nextElement();

      try {
        int width = Integer.parseInt(element);

        if (index > (columnModel.getColumnCount() - 1)) {
          logger.warn(
            "loadsettings - failed attempt to set width for index " + index
            + ", width " + element);
        } else {
          columnModel.getColumn(index).setPreferredWidth(width);
          searchColumnModel.getColumn(index).setPreferredWidth(width);
        }

        index++;
      } catch (NumberFormatException e) {
        logger.error("Error decoding a Table width", e);
      }
    }
    undockedFrame.setSize(getSize());
    undockedFrame.setLocation(getBounds().x, getBounds().y);

      repaint();
    }

  public JTextField getFindTextField() {
    return findField;
  }

  /**
   * Iterate over all values in the column and return the longest width
   *
   * @param index column index
   *
   * @return longest width - relies on FontMetrics.stringWidth for calculation
   */
  private int getMaxColumnWidth(int index) {
    FontMetrics metrics = getGraphics().getFontMetrics();
    int longestWidth =
      metrics.stringWidth("  " + table.getColumnName(index) + "  ")
      + (2 * table.getColumnModel().getColumnMargin());

    for (int i = 0, j = tableModel.getRowCount(); i < j; i++) {
      Component c =
        renderer.getTableCellRendererComponent(
          table, table.getValueAt(i, index), false, false, i, index);

      if (c instanceof JLabel) {
        longestWidth =
          Math.max(longestWidth, metrics.stringWidth(((JLabel) c).getText()));
      }
    }

    return longestWidth + 5;
  }

  private String getToolTipTextForEvent(LoggingEventWrapper loggingEventWrapper) {
    StringBuffer buf = new StringBuffer();
    buf.append(detailLayout.getHeader()).append(detailLayout.format(loggingEventWrapper.getLoggingEvent())).append(detailLayout.getFooter());
    return buf.toString();
  }

  /**
   * ensures the Entry map of all the unque logger names etc, that is used for
   * the Filter panel is updated with any new information from the event
   *
   * @param event
   */
  private void updateOtherModels(LoggingEvent event) {

    /*
     * EventContainer is a LoggerNameModel imp, use that for notifing
     */
    tableModel.addLoggerName(event.getLoggerName());

    filterModel.processNewLoggingEvent(event);
  }

    public void findNextMarker() {
      EventQueue.invokeLater(new Runnable() {
          public void run() {
              int startRow = table.getSelectedRow() + 1;
              int filteredEventsSize = getFilteredEvents().size();
              if (startRow > filteredEventsSize - 1) {
                  startRow = 0;
              }
              final int nextRow = tableModel.locate(findMarkerRule, startRow, true);

              if (nextRow > -1) {
                  table.scrollToRow(nextRow);
              }
          }
      });
    }

    public void findPreviousMarker() {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                int startRow = table.getSelectedRow() - 1;
                int filteredEventsSize = getFilteredEvents().size();
                if (startRow < 0) {
                    startRow = filteredEventsSize - 1;
                }
                final int previousRow = tableModel.locate(findMarkerRule, startRow, false);

                if (previousRow > -1) {
                    table.scrollToRow(previousRow);
                }
            }
        });
    }

    public void clearAllMarkers() {
      //this will get the properties to be removed from both tables..but
      tableModel.removePropertyFromEvents(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE);
    }

    public void toggleMarker() {
        int row = table.getSelectedRow();
        if (row != -1) {
          LoggingEventWrapper loggingEventWrapper = tableModel.getRow(row);
          if (loggingEventWrapper != null) {
              Object marker = loggingEventWrapper.getLoggingEvent().getProperty(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE);
              if (marker == null) {
                  loggingEventWrapper.setProperty(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE, "set");
              } else {
                  loggingEventWrapper.removeProperty(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE);
              }
              //if marker -was- null, it no longer is (may need to add the column)
              tableModel.fireRowUpdated(row, (marker == null));
          }
        }
    }

    public void layoutComponents()
    {
        if (preferenceModel.isDetailPaneVisible()) {
          showDetailPane();
         } else {
          hideDetailPane();
        }
    }

  /**
   * This class receives notification when the Refine focus text field is
   * updated, where a backgrounh 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
    implements DocumentListener {
    private static final long CHECK_PERIOD = 1000;
    private final JTextField filterText;
    private long lastTimeStamp = System.currentTimeMillis();
    private final Thread delayThread;
    private final String defaultToolTip;
    private String lastFilterText = "";

    private DelayedFilterTextDocumentListener(final JTextField filterText) {
      super();
      this.filterText = filterText;
      this.defaultToolTip = filterText.getToolTipText();

      this.delayThread =
        new Thread(
          new Runnable() {
            public void run() {
              while (true) {
                try {
                  Thread.sleep(CHECK_PERIOD);
                } catch (InterruptedException e) {
                }

                if (
                  (System.currentTimeMillis() - lastTimeStamp) < CHECK_PERIOD) {
                  // They typed something since the last check. we ignor
                  // this for a sample period
                  //                logger.debug("Typed something since the last check");
                } else if (
                  (System.currentTimeMillis() - lastTimeStamp) < (2 * CHECK_PERIOD)) {
                  // 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();
                    EventQueue.invokeLater(new Runnable()
                    {
                        public void run()
                        {
                            setFilter();
                        }
                    });
                  }
                } else {
                  // they stopped typing a while ago, let's forget about it
                  //                logger.debug(
                  //                  "They stoppped typing a while ago, assuming filter has been applied");
                }
              }
            }
          });

      delayThread.setPriority(Thread.MIN_PRIORITY);
      delayThread.start();
    }

    /**
     * Update timestamp
     *
     * @param e
     */
    public void insertUpdate(DocumentEvent e) {
      notifyChange();
    }

    /**
     * Update timestamp
     *
     * @param e
     */
    public void removeUpdate(DocumentEvent e) {
      notifyChange();
    }

    /**
     * Update timestamp
     *
     * @param e
     */
    public void changedUpdate(DocumentEvent e) {
      notifyChange();
    }

    /**
     * Update timestamp
     */
    private void notifyChange() {
      this.lastTimeStamp = System.currentTimeMillis();
    }

    /**
     * Update refinement rule based on the entered expression.
     */
    private void setFilter() {
      if (filterText.getText().trim().equals("")) {
        //reset background color in case we were previously an invalid expression
        filterText.setBackground(UIManager.getColor("TextField.background"));
        tableRuleMediator.setFilterRule(null);
        searchRuleMediator.setFilterRule(null);
        filterText.setToolTipText(defaultToolTip);
      } else {
        try {
          tableRuleMediator.setFilterRule(ExpressionRule.getRule(filterText.getText()));
          searchRuleMediator.setFilterRule(ExpressionRule.getRule(filterText.getText()));
          filterText.setToolTipText(defaultToolTip);
          //valid expression, reset background color in case we were previously an invalid expression
          filterText.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);
        }
      }
    }
  }

  private final class TableMarkerListener extends MouseAdapter {
    private JTable markerTable;
    private EventContainer markerEventContainer;
    private EventContainer otherMarkerEventContainer;

    private TableMarkerListener(JTable markerTable, EventContainer markerEventContainer, EventContainer otherMarkerEventContainer) {
      this.markerTable = markerTable;
      this.markerEventContainer = markerEventContainer;
      this.otherMarkerEventContainer = otherMarkerEventContainer;
    }
    
      public void mouseClicked(MouseEvent evt) {
          if (evt.getClickCount() == 2) {
              int row = markerTable.rowAtPoint(evt.getPoint());
              if (row != -1) {
                LoggingEventWrapper loggingEventWrapper = markerEventContainer.getRow(row);
                if (loggingEventWrapper != null) {
                    Object marker = loggingEventWrapper.getLoggingEvent().getProperty(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE);
                    if (marker == null) {
                        loggingEventWrapper.setProperty(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE, "set");
                    } else {
                        loggingEventWrapper.removeProperty(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE);
                    }
                    //if marker -was- null, it no longer is (may need to add the column)
                    markerEventContainer.fireRowUpdated(row, (marker == null));
                    otherMarkerEventContainer.fireRowUpdated(otherMarkerEventContainer.getRowIndex(loggingEventWrapper), (marker == null));
                }
              }
          }
      }
  }

  /**
   * Update active tooltip
   */
  private final class TableColumnDetailMouseListener extends MouseMotionAdapter {
    private int currentRow = -1;
    private JTable detailTable;
    private EventContainer detailEventContainer;

    private TableColumnDetailMouseListener(JTable detailTable, EventContainer detailEventContainer) {
      this.detailTable = detailTable;
      this.detailEventContainer = detailEventContainer;
    }

    /**
     * Update tooltip based on mouse position
     *
     * @param evt
     */
    public void mouseMoved(MouseEvent evt) {
      currentPoint = evt.getPoint();
      currentTable = detailTable;

      if (preferenceModel.isToolTips()) {
        int row = detailTable.rowAtPoint(evt.getPoint());

        if ((row == currentRow) || (row == -1)) {
          return;
        }

        currentRow = row;

        LoggingEventWrapper event = detailEventContainer.getRow(currentRow);

        if (event != null) {
          String toolTipText = getToolTipTextForEvent(event);
          detailTable.setToolTipText(toolTipText);
        }
      } else {
        detailTable.setToolTipText(null);
      }
    }
  }

  //if columnmoved or columnremoved callback received, re-apply table's sort index based
  //sort column name
  private class ChainsawTableColumnModelListener implements TableColumnModelListener {
    private JSortTable modelListenerTable;

    private ChainsawTableColumnModelListener(JSortTable modelListenerTable) {
      this.modelListenerTable = modelListenerTable;
    }

    public void columnAdded(TableColumnModelEvent e) {
      //no-op
    }

    /**
     * Update sorted column
     *
     * @param e
     */
    public void columnRemoved(TableColumnModelEvent e) {
      modelListenerTable.updateSortedColumn();
    }

    /**
     * Update sorted column
     *
     * @param e
     */
    public void columnMoved(TableColumnModelEvent e) {
      modelListenerTable.updateSortedColumn();
    }

    /**
     * Ignore margin changed
     *
     * @param e
     */
    public void columnMarginChanged(ChangeEvent e) {
    }

    /**
     * Ignore selection changed
     *
     * @param e
     */
    public void columnSelectionChanged(ListSelectionEvent e) {
    }
  }

  /**
   * Thread that periodically checks if the selected row has changed, and if
   * it was, updates the Detail Panel with the detailed Logging information
   */
  private class DetailPaneUpdater implements PropertyChangeListener {
    private int selectedRow = -1;
    int lastRow = -1;
    private DetailPaneUpdater() {
    }

    /**
     * Update detail pane to display information about the LoggingEvent at index row
     *
     * @param row
     */
    private void setSelectedRow(int row) {
      selectedRow = row;
      updateDetailPane();
    }

    private void setAndUpdateSelectedRow(int row) {
        selectedRow = row;
        updateDetailPane(true);
    }

    private void updateDetailPane() {
        updateDetailPane(false);
    }
    /**
     * Update detail pane
     */
    private void updateDetailPane(boolean force) {
            /*
             * Don't bother doing anything if it's not visible. Note: the isVisible() method on
             * Component is not really accurate here because when the button to toggle display of
             * the detail pane is triggered it still appears as 'visible' for some reason.
             */
      if (!preferenceModel.isDetailPaneVisible()) {
        return;
      }

	      LoggingEventWrapper loggingEventWrapper = null;
	      if (force || (selectedRow != -1 && (lastRow != selectedRow))) {
	        loggingEventWrapper = tableModel.getRow(selectedRow);
	
	        if (loggingEventWrapper != null) {
	          final StringBuffer buf = new StringBuffer();
	          buf.append(detailLayout.getHeader())
	             .append(detailLayout.format(loggingEventWrapper.getLoggingEvent())).append(
	            detailLayout.getFooter());
	          if (buf.length() > 0) {
		          	try {
		          		final Document doc = detail.getEditorKit().createDefaultDocument();
		          		detail.getEditorKit().read(new StringReader(buf.toString()), doc, 0);

				      	SwingHelper.invokeOnEDT(new Runnable() {
				      		public void run() {
				      			detail.setDocument(doc);
                                JTextComponentFormatter.applySystemFontAndSize(detail);
				      			detail.setCaretPosition(0);
                                lastRow = selectedRow;
				      		}
				      	});
		          	} catch (Exception e) {}
	      		}
	        }
	      }
	
	      if (loggingEventWrapper == null && (lastRow != selectedRow)) {
          	try {
          		final Document doc = detail.getEditorKit().createDefaultDocument();
          		detail.getEditorKit().read(new StringReader("<html>Nothing selected</html>"), doc, 0);
		      	SwingHelper.invokeOnEDT(new Runnable() {
		      		public void run() {
		      			detail.setDocument(doc);
                        JTextComponentFormatter.applySystemFontAndSize(detail);
		      			detail.setCaretPosition(0);
                        lastRow = selectedRow;
		      		}
		      	});
          	} catch (Exception e) {}
  		}
    }

    /**
     * Update detail pane layout if it's changed
     *
     * @param arg0
     */
    public void propertyChange(PropertyChangeEvent arg0) {
      SwingUtilities.invokeLater(
        new Runnable() {
          public void run() {
            updateDetailPane(true);
          }
        });
    }
  }
    private class ThrowableDisplayMouseAdapter extends MouseAdapter {
      private JTable throwableTable;
      private EventContainer throwableEventContainer;
      final JDialog detailDialog;
      final JEditorPane detailArea;
      public ThrowableDisplayMouseAdapter(JTable throwableTable, EventContainer throwableEventContainer) {
        this.throwableTable = throwableTable;
        this.throwableEventContainer = throwableEventContainer;

        detailDialog = new JDialog((JFrame) null, true);
        Container container = detailDialog.getContentPane();
        detailArea = new JEditorPane();
        JTextComponentFormatter.applySystemFontAndSize(detailArea);
        detailArea.setEditable(false);
        Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
        detailArea.setPreferredSize(new Dimension(screenDimension.width / 2, screenDimension.height / 2));
        container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
        container.add(new JScrollPane(detailArea));

        detailDialog.pack();
      }
        public void mouseClicked(MouseEvent e)
        {
            TableColumn column = throwableTable.getColumnModel().getColumn(throwableTable.columnAtPoint(e.getPoint()));
            if (!column.getHeaderValue().toString().toUpperCase().equals(ChainsawColumns.getColumnName(ChainsawColumns.INDEX_THROWABLE_COL_NAME))) {
                return;
            }

            LoggingEventWrapper loggingEventWrapper = throwableEventContainer.getRow(throwableTable.getSelectedRow());

            //throwable string representation may be a length-one empty array
            String[] ti = loggingEventWrapper.getLoggingEvent().getThrowableStrRep();
            if (ti != null && ti.length > 0 && (!(ti.length == 1 && ti[0].equals("")))) {
                 detailDialog.setTitle(throwableTable.getColumnName(throwableTable.getSelectedColumn()) + " detail...");
                  StringBuffer buf = new StringBuffer();
                  buf.append(loggingEventWrapper.getLoggingEvent().getMessage());
                  buf.append("\n");
                  for (int i = 0; i < ti.length; i++) {
                    buf.append(ti[i]).append("\n    ");
                  }

                  detailArea.setText(buf.toString());
                  SwingHelper.invokeOnEDT(new Runnable() {
                    public void run() {
                      centerAndSetVisible(detailDialog);
                    }
                  });
                }
        }
    }

    private class MarkerCellEditor implements TableCellEditor {
      JTable currentTable;
      JTextField textField = new JTextField();
      Set cellEditorListeners = new HashSet();
      private LoggingEventWrapper currentLoggingEventWrapper;
      private final Object mutex = new Object();

        public Object getCellEditorValue()
        {
            return textField.getText();
        }

        public boolean isCellEditable(EventObject anEvent)
        {
            return true;
        }

        public boolean shouldSelectCell(EventObject anEvent)
        {
            textField.selectAll();
            return true;
        }

        public boolean stopCellEditing()
        {
            if (textField.getText().trim().equals("")) {
                currentLoggingEventWrapper.removeProperty(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE);
            } else {
                currentLoggingEventWrapper.setProperty(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE, textField.getText());
            }
            //row should always exist in the main table if it is being edited
            tableModel.fireRowUpdated(tableModel.getRowIndex(currentLoggingEventWrapper), true);
            int index = searchModel.getRowIndex(currentLoggingEventWrapper);
            if (index > -1) {
              searchModel.fireRowUpdated(index, true);
            }

            ChangeEvent event = new ChangeEvent(currentTable);
            Set cellEditorListenersCopy;
            synchronized(mutex) {
                cellEditorListenersCopy = new HashSet(cellEditorListeners);
            }

            for (Iterator iter = cellEditorListenersCopy.iterator();iter.hasNext();) {
                ((CellEditorListener)iter.next()).editingStopped(event);
            }
            currentLoggingEventWrapper = null;
            currentTable = null;

            return true;
        }

        public void cancelCellEditing()
        {
            Set cellEditorListenersCopy;
            synchronized(mutex) {
                cellEditorListenersCopy = new HashSet(cellEditorListeners);
            }

           ChangeEvent event = new ChangeEvent(currentTable);
           for (Iterator iter = cellEditorListenersCopy.iterator();iter.hasNext();) {
               ((CellEditorListener)iter.next()).editingCanceled(event);
           }
          currentLoggingEventWrapper = null;
          currentTable = null;
        }

        public void addCellEditorListener(CellEditorListener l)
        {
            synchronized(mutex) {
                cellEditorListeners.add(l);
            }
        }

        public void removeCellEditorListener(CellEditorListener l)
        {
            synchronized(mutex) {
                cellEditorListeners.remove(l);
            }
        }

        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
        {
          currentTable = table;
          currentLoggingEventWrapper =((EventContainer) table.getModel()).getRow(row);
            if (currentLoggingEventWrapper != null) {
                textField.setText(currentLoggingEventWrapper.getLoggingEvent().getProperty(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE));
                textField.selectAll();
            }
            else {
              textField.setText("");
            }
            return textField;
        }
    }

    private class EventTimeDeltaMatchThumbnail extends AbstractEventMatchThumbnail {
        public EventTimeDeltaMatchThumbnail() {
            super();
            initializeLists();
        }

        boolean primaryMatches(ThumbnailLoggingEventWrapper wrapper) {
            String millisDelta = wrapper.loggingEventWrapper.getLoggingEvent().getProperty(ChainsawConstants.MILLIS_DELTA_COL_NAME_LOWERCASE);
            if (millisDelta != null && !millisDelta.trim().equals("")) {
                long millisDeltaLong = Long.parseLong(millisDelta);
                //arbitrary
                return millisDeltaLong >= 1000;
            }
            return false;
        }

        boolean secondaryMatches(ThumbnailLoggingEventWrapper wrapper) {
            //secondary is not used
            return false;
        }

        private void initializeLists() {
            secondaryList.clear();
            primaryList.clear();

            int i=0;
            for (Iterator iter = tableModel.getFilteredEvents().iterator();iter.hasNext();) {
                LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper) iter.next();
                ThumbnailLoggingEventWrapper wrapper = new ThumbnailLoggingEventWrapper(i, loggingEventWrapper);
                i++;
                //only add if there is a color defined
                if (primaryMatches(wrapper)) {
                    primaryList.add(wrapper);
                }
            }
            invalidate();
            repaint();
        }

        public void paintComponent(Graphics g) {
            super.paintComponent(g);

            Point topAndBottomOffset = getScrollBarOffsets();
            int topOffset = topAndBottomOffset.x;
            int bottomOffset = topAndBottomOffset.y;

            int rowCount = table.getRowCount();
            if (rowCount == 0) {
                return;
            }
            //use event pane height as reference height - max component height will be extended by event height if
            // last row is rendered, so subtract here
            int height = eventsPane.getHeight() - topOffset - bottomOffset;
            int maxHeight = Math.min(maxEventHeight, (height / rowCount));
            int minHeight = Math.max(1, maxHeight);
            int componentHeight = height - minHeight;
            int eventHeight = minHeight;

            //draw all events
            for (Iterator iter = primaryList.iterator();iter.hasNext();) {
                ThumbnailLoggingEventWrapper wrapper = (ThumbnailLoggingEventWrapper)iter.next();
                    if (primaryMatches(wrapper)) {
                        float ratio = (wrapper.rowNum / (float)rowCount);
        //                System.out.println("error - ratio: " + ratio + ", component height: " + componentHeight);
                        int verticalLocation = (int) (componentHeight * ratio) + topOffset;

                        int startX = 1;
                        int width = getWidth() - (startX * 2);
                        //max out at 50, min 2...
                        String millisDelta = wrapper.loggingEventWrapper.getLoggingEvent().getProperty(ChainsawConstants.MILLIS_DELTA_COL_NAME_LOWERCASE);
                        long millisDeltaLong = Long.parseLong(millisDelta);
                        long delta = Math.min(ChainsawConstants.MILLIS_DELTA_RENDERING_HEIGHT_MAX, Math.max(0, (long) (millisDeltaLong * ChainsawConstants.MILLIS_DELTA_RENDERING_FACTOR)));
                        float widthMaxMillisDeltaRenderRatio = ((float)width / ChainsawConstants.MILLIS_DELTA_RENDERING_HEIGHT_MAX);
                        int widthToUse = Math.max(2, (int)(delta * widthMaxMillisDeltaRenderRatio));
                        eventHeight = Math.min(maxEventHeight, eventHeight + 3);
//                            eventHeight = maxEventHeight;
                        drawEvent(applicationPreferenceModel.getDeltaColor(), (verticalLocation - eventHeight + 1), eventHeight, g, startX, widthToUse);
    //                System.out.println("painting error - rownum: " + wrapper.rowNum + ", location: " + verticalLocation + ", height: " + eventHeight + ", component height: " + componentHeight + ", row count: " + rowCount);
                }
            }
        }
    }

    private class ColorizedEventAndSearchMatchThumbnail extends AbstractEventMatchThumbnail {
        public ColorizedEventAndSearchMatchThumbnail() {
            super();
            configureColors();
            colorizer.addPropertyChangeListener(new PropertyChangeListener() {
                public void propertyChange(PropertyChangeEvent evt) {
                    configureColors();
                }
            });
        }

        boolean primaryMatches(ThumbnailLoggingEventWrapper wrapper) {
            return !wrapper.loggingEventWrapper.getColorRuleBackground().equals(ChainsawConstants.COLOR_DEFAULT_BACKGROUND);
        }

        boolean secondaryMatches(ThumbnailLoggingEventWrapper wrapper) {
            return wrapper.loggingEventWrapper.isSearchMatch();
        }

        private void configureColors() {
            secondaryList.clear();
            primaryList.clear();

            int i=0;
            for (Iterator iter = tableModel.getFilteredEvents().iterator();iter.hasNext();) {
                LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper) iter.next();
                loggingEventWrapper.updateColorRuleColors(colorizer.getBackgroundColor(loggingEventWrapper.getLoggingEvent()), colorizer.getForegroundColor(loggingEventWrapper.getLoggingEvent()));
                ThumbnailLoggingEventWrapper wrapper = new ThumbnailLoggingEventWrapper(i, loggingEventWrapper);
                if (secondaryMatches(wrapper)) {
                    secondaryList.add(wrapper);
                }
                i++;
                //only add if there is a color defined
                if (primaryMatches(wrapper)) {
                    primaryList.add(wrapper);
                }
            }
            invalidate();
            repaint();
        }

        public void paintComponent(Graphics g) {
            super.paintComponent(g);

            Point topAndBottomOffset = getScrollBarOffsets();
            int topOffset = topAndBottomOffset.x;
            int bottomOffset = topAndBottomOffset.y;

            int rowCount = table.getRowCount();
            if (rowCount == 0) {
                return;
            }
            //use event pane height as reference height - max component height will be extended by event height if
            // last row is rendered, so subtract here
            int height = eventsPane.getHeight() - topOffset - bottomOffset;
            int maxHeight = Math.min(maxEventHeight, (height / rowCount));
            int minHeight = Math.max(1, maxHeight);
            int componentHeight = height - minHeight;
            int eventHeight = minHeight;

            //draw all non error/warning/marker events
            for (Iterator iter = primaryList.iterator();iter.hasNext();) {
                ThumbnailLoggingEventWrapper wrapper = (ThumbnailLoggingEventWrapper)iter.next();
                if (!wrapper.loggingEventWrapper.getColorRuleBackground().equals(ChainsawConstants.COLOR_DEFAULT_BACKGROUND)) {
                    if (wrapper.loggingEventWrapper.getLoggingEvent().getLevel().toInt() < Level.WARN.toInt() && wrapper.loggingEventWrapper.getLoggingEvent().getProperty(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE) == null) {
                        float ratio = (wrapper.rowNum / (float)rowCount);
        //                System.out.println("error - ratio: " + ratio + ", component height: " + componentHeight);
                        int verticalLocation = (int) (componentHeight * ratio) + topOffset;

                        int startX = 1;
                        int width = getWidth() - (startX * 2);

                        drawEvent(wrapper.loggingEventWrapper.getColorRuleBackground(), verticalLocation, eventHeight, g, startX, width);
        //                System.out.println("painting error - rownum: " + wrapper.rowNum + ", location: " + verticalLocation + ", height: " + eventHeight + ", component height: " + componentHeight + ", row count: " + rowCount);
                    }
                }
            }

            //draw warnings, error, fatal & markers last (full width)
            for (Iterator iter = primaryList.iterator();iter.hasNext();) {
                ThumbnailLoggingEventWrapper wrapper = (ThumbnailLoggingEventWrapper)iter.next();
                if (!wrapper.loggingEventWrapper.getColorRuleBackground().equals(ChainsawConstants.COLOR_DEFAULT_BACKGROUND)) {
                    if (wrapper.loggingEventWrapper.getLoggingEvent().getLevel().toInt() >= Level.WARN.toInt() || wrapper.loggingEventWrapper.getLoggingEvent().getProperty(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE) != null) {
                        float ratio = (wrapper.rowNum / (float)rowCount);
        //                System.out.println("error - ratio: " + ratio + ", component height: " + componentHeight);
                        int verticalLocation = (int) (componentHeight * ratio) + topOffset;

                        int startX = 1;
                        int width = getWidth() - (startX * 2);
                        //narrow the color a bit if level is less than warn
                            //make warnings, errors a little taller

                        eventHeight = Math.min(maxEventHeight, eventHeight + 3);
//                            eventHeight = maxEventHeight;

                        drawEvent(wrapper.loggingEventWrapper.getColorRuleBackground(), (verticalLocation - eventHeight + 1), eventHeight, g, startX, width);
    //                System.out.println("painting error - rownum: " + wrapper.rowNum + ", location: " + verticalLocation + ", height: " + eventHeight + ", component height: " + componentHeight + ", row count: " + rowCount);
                    }
                }
            }

            for (Iterator iter = secondaryList.iterator();iter.hasNext();) {
                ThumbnailLoggingEventWrapper wrapper = (ThumbnailLoggingEventWrapper)iter.next();
                float ratio = (wrapper.rowNum / (float)rowCount);
//                System.out.println("warning - ratio: " + ratio + ", component height: " + componentHeight);
                int verticalLocation = (int) (componentHeight * ratio) + topOffset;

                int startX = 1;
                int width = getWidth() - (startX * 2);
                width = (width / 2);

                //use black for search indicator in the 'gutter'
                drawEvent(Color.BLACK, verticalLocation, eventHeight, g, startX, width);
//                System.out.println("painting warning - rownum: " + wrapper.rowNum + ", location: " + verticalLocation + ", height: " + eventHeight + ", component height: " + componentHeight + ", row count: " + rowCount);
            }
        }
    }

    abstract class AbstractEventMatchThumbnail extends JPanel {
        protected List primaryList = new ArrayList();
        protected List secondaryList = new ArrayList();
        protected final int maxEventHeight = 6;

        AbstractEventMatchThumbnail() {
            super();
            addMouseMotionListener(new MouseMotionAdapter() {
              public void mouseMoved(MouseEvent e) {
                if (preferenceModel.isThumbnailBarToolTips()) {
                    int yPosition = e.getPoint().y;
                    ThumbnailLoggingEventWrapper event = getEventWrapperAtPosition(yPosition);
                    if (event != null) {
                        setToolTipText(getToolTipTextForEvent(event.loggingEventWrapper));
                    }
                } else {
                    setToolTipText(null);
                }
              }
            });

            addMouseListener(new MouseAdapter(){
                public void mouseClicked(MouseEvent e)
                {
                    int yPosition = e.getPoint().y;
                    ThumbnailLoggingEventWrapper event = getEventWrapperAtPosition(yPosition);
//                    System.out.println("rowToSelect: " + rowToSelect + ", closestRow: " + event.loggingEvent.getProperty("log4jid"));
                    if (event != null) {
                        int id = Integer.parseInt(event.loggingEventWrapper.getLoggingEvent().getProperty("log4jid"));
                        setSelectedEvent(id);
                    }
                }
            });

            tableModel.addTableModelListener(new TableModelListener(){
                public void tableChanged(TableModelEvent e) {
                    int firstRow = e.getFirstRow();
                    //lastRow may be Integer.MAX_VALUE..if so, set lastRow to rowcount - 1 (so rowcount may be negative here, which will bypass for loops below)
                    int lastRow = Math.min(e.getLastRow(), table.getRowCount() - 1);
                    //clear everything if we got an event w/-1 for first or last row
                    if (firstRow < 0 || lastRow < 0) {
                        primaryList.clear();
                        secondaryList.clear();
                    }

//                    System.out.println("lastRow: " + lastRow + ", first row: " + firstRow + ", original last row: " + e.getLastRow() + ", type: " + e.getType());

                    List displayedEvents = tableModel.getFilteredEvents();
                    if (e.getType() == TableModelEvent.INSERT) {
//                        System.out.println("insert - current warnings: " + warnings.size() + ", errors: " + errors.size() + ", first row: " + firstRow + ", last row: " + lastRow);
                        for (int i=firstRow;i<lastRow;i++) {
                            LoggingEventWrapper event = (LoggingEventWrapper)displayedEvents.get(i);
                            ThumbnailLoggingEventWrapper wrapper = new ThumbnailLoggingEventWrapper(i, event);
                            if (secondaryMatches(wrapper)) {
                                secondaryList.add(wrapper);
//                                System.out.println("added warning: " + i + " - " + event.getLevel());
                            }
                            if (primaryMatches(wrapper)) {
                                //add to this one
                                primaryList.add(wrapper);
                            }
//                                System.out.println("added error: " + i + " - " + event.getLevel());
                        }
//                        System.out.println("insert- new warnings: " + warnings + ", errors: " + errors);

                        //run evaluation on rows & add to list
                    } else if (e.getType() == TableModelEvent.DELETE) {
                        //find each eventwrapper with an id in the deleted range and remove it...
//                        System.out.println("delete- current warnings: " + warnings.size() + ", errors: " + errors.size() + ", first row: " + firstRow + ", last row: " + lastRow + ", displayed event count: " + displayedEvents.size() );
                        for (Iterator iter = secondaryList.iterator();iter.hasNext();) {
                            ThumbnailLoggingEventWrapper wrapper = (ThumbnailLoggingEventWrapper)iter.next();
                            if ((wrapper.rowNum >= firstRow) && (wrapper.rowNum <= lastRow)) {
//                                System.out.println("deleting find: " + wrapper);
                                iter.remove();
                            }
                        }
                        for (Iterator iter = primaryList.iterator();iter.hasNext();) {
                            ThumbnailLoggingEventWrapper wrapper = (ThumbnailLoggingEventWrapper)iter.next();
                            if ((wrapper.rowNum >= firstRow) && (wrapper.rowNum <= lastRow)) {
//                                System.out.println("deleting error: " + wrapper);
                                iter.remove();
                            }
                        }
//                        System.out.println("delete- new warnings: " + warnings.size() + ", errors: " + errors.size());

                        //remove any matching rows
                    } else if (e.getType() == TableModelEvent.UPDATE) {
//                        System.out.println("update - about to delete old warnings in range: " + firstRow + " to " + lastRow + ", current warnings: " + warnings.size() + ", errors: " + errors.size());
                        //find each eventwrapper with an id in the deleted range and remove it...
                        for (Iterator iter = secondaryList.iterator();iter.hasNext();) {
                            ThumbnailLoggingEventWrapper wrapper = (ThumbnailLoggingEventWrapper)iter.next();
                            if ((wrapper.rowNum >= firstRow) && (wrapper.rowNum <= lastRow)) {
//                                System.out.println("update - deleting warning: " + wrapper);
                                iter.remove();
                            }
                        }
                        for (Iterator iter = primaryList.iterator();iter.hasNext();) {
                            ThumbnailLoggingEventWrapper wrapper = (ThumbnailLoggingEventWrapper)iter.next();
                            if ((wrapper.rowNum >= firstRow) && (wrapper.rowNum <= lastRow)) {
//                                System.out.println("update - deleting error: " + wrapper);
                                iter.remove();
                            }
                        }
//                        System.out.println("update - after deleting old warnings in range: " + firstRow + " to " + lastRow + ", new warnings: " + warnings.size() + ", errors: " + errors.size());
                        //NOTE: for update, we need to do i<= lastRow
                        for (int i=firstRow;i<=lastRow;i++) {
                            LoggingEventWrapper event = (LoggingEventWrapper)displayedEvents.get(i);
                            ThumbnailLoggingEventWrapper wrapper = new ThumbnailLoggingEventWrapper(i, event);
//                                System.out.println("update - adding error: " + i + ", event: " + event.getMessage());
                            //only add event to thumbnail if there is a color
                            if (primaryMatches(wrapper)) {
                                //!wrapper.loggingEvent.getColorRuleBackground().equals(ChainsawConstants.COLOR_DEFAULT_BACKGROUND)
                                primaryList.add(wrapper);
                            } else {
                                primaryList.remove(wrapper);
                            }

                            if (secondaryMatches(wrapper)) {
                                //event.isSearchMatch())
//                                System.out.println("update - adding marker: " + i + ", event: " + event.getMessage());
                                secondaryList.add(wrapper);
                            } else {
                                secondaryList.remove(wrapper);
                            }
                        }
//                        System.out.println("update - new warnings: " + warnings.size() + ", errors: " + errors.size());
                    }
                    invalidate();
                    repaint();
                    if (isScrollToBottom()) {
                        scrollToBottom();
                    }
                }
            });
        }

        abstract boolean primaryMatches(ThumbnailLoggingEventWrapper wrapper);

        abstract boolean secondaryMatches(ThumbnailLoggingEventWrapper wrapper);
        /**
         * Get event wrapper - may be null
         * @param yPosition
         * @return event wrapper or null
         */
        protected ThumbnailLoggingEventWrapper getEventWrapperAtPosition(int yPosition) {
            int rowCount = table.getRowCount();

            Point offsets = getScrollBarOffsets();
            int topOffset = offsets.x;
            int bottomOffset = offsets.y;

            //'effective' height of this component is scrollpane height - top/bottom offsets
            int height = eventsPane.getHeight() - topOffset - bottomOffset;

            //remove top offset from click location but avoid going negative
            yPosition = Math.max(yPosition - topOffset, 0);

            //don't let clicklocation exceed height
            if (yPosition >= height) {
                yPosition = height;
            }

    //                    System.out.println("clicked y pos: " + e.getPoint().y + ", relative: " + clickLocation);
            float ratio = (float) yPosition / height;
            int rowToSelect = Math.round(rowCount * ratio);
    //                    System.out.println("rowCount: " + rowCount + ", height: " + height + ", clickLocation: " + clickLocation + ", ratio: " + ratio + ", rowToSelect: " + rowToSelect);
            ThumbnailLoggingEventWrapper event = getClosestRow(rowToSelect);
            return event;
        }

        private ThumbnailLoggingEventWrapper getClosestRow(int rowToSelect) {
            ThumbnailLoggingEventWrapper closestRow = null;
            int rowDelta = Integer.MAX_VALUE;
            for (Iterator iter = secondaryList.iterator();iter.hasNext();) {
                ThumbnailLoggingEventWrapper event = (ThumbnailLoggingEventWrapper) iter.next();
                int newRowDelta = Math.abs(rowToSelect - event.rowNum);
                if (newRowDelta < rowDelta) {
                    closestRow = event;
                    rowDelta = newRowDelta;
                }
            }
            for (Iterator iter = primaryList.iterator();iter.hasNext();) {
                ThumbnailLoggingEventWrapper event = (ThumbnailLoggingEventWrapper) iter.next();
                int newRowDelta = Math.abs(rowToSelect - event.rowNum);
                if (newRowDelta < rowDelta) {
                    closestRow = event;
                    rowDelta = newRowDelta;
                }
            }
            return closestRow;
        }

        /**
         * Return a point representing top and bottom offsets
         * Top offset is held by Point.x, bottom offset is held by Point.y
         *
         * @return point representing top and bottom offsets (x and y values of Point)
         */
        public Point getScrollBarOffsets() {
            Integer scrollBarWidth = (Integer) UIManager.get("ScrollBar.width");
            int scrollBarOffset = scrollBarWidth == null ? 0 : scrollBarWidth.intValue();
            //calculate topOffset and bottomOffset (topOffset is tableheader size + optional vertical scrollbar thumb height
            //bottom offset is optional vertical scrollbar thumb height + optional horizontal scrollbar thumb height
            int topOffset = table.getTableHeader().getMinimumSize().height;
            int bottomOffset = 0;
            if (eventsPane.getVerticalScrollBar().isVisible()) {
                topOffset += scrollBarOffset;
                bottomOffset += scrollBarOffset;
            }
            if (eventsPane.getHorizontalScrollBar().isVisible()) {
                bottomOffset += scrollBarOffset;
            }
            return new Point(topOffset, bottomOffset);
        }

        public Point getToolTipLocation(MouseEvent event) {
            //shift tooltip down so the the pointer doesn't cover up events below the current mouse location
            return new Point(event.getX(), event.getY() + 30);
        }

        protected void drawEvent(Color newColor, int verticalLocation, int eventHeight, Graphics g, int x, int width) {
    //            System.out.println("painting: - color: " + newColor + ", verticalLocation: " + verticalLocation + ", eventHeight: " + eventHeight);
            //center drawing at vertical location
            int y = verticalLocation + (eventHeight / 2);
            Color oldColor = g.getColor();
            g.setColor(newColor);
            g.fillRect(x, y, width, eventHeight);
            if (eventHeight >= 3) {
                g.setColor(newColor.darker());
                g.drawRect(x, y, width, eventHeight);
            }
            g.setColor(oldColor);
        }
    }

    class ThumbnailLoggingEventWrapper {
        int rowNum;
        LoggingEventWrapper loggingEventWrapper;
        public ThumbnailLoggingEventWrapper(int rowNum, LoggingEventWrapper loggingEventWrapper) {
            this.rowNum = rowNum;
            this.loggingEventWrapper = loggingEventWrapper;
        }

        public String toString() {
            return "event - rownum: " + rowNum + ", level: " + loggingEventWrapper.getLoggingEvent().getLevel();
        }

        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }

            ThumbnailLoggingEventWrapper that = (ThumbnailLoggingEventWrapper) o;

            if (loggingEventWrapper != null ? !loggingEventWrapper.equals(that.loggingEventWrapper) : that.loggingEventWrapper != null) {
                return false;
            }

            return true;
        }

        public int hashCode() {
            return loggingEventWrapper != null ? loggingEventWrapper.hashCode() : 0;
        }
    }

    static class AutoFilterComboBox extends JComboBox {
        private boolean bypassFiltering;
        private List allEntries = new ArrayList();
        private List displayedEntries = new ArrayList();
        private AutoFilterComboBoxModel model = new AutoFilterComboBoxModel();
        //editor component
        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);
                }
            }
            setModel(model);
            setEditor(new AutoFilterEditor());
            ((JTextField)getEditor().getEditorComponent()).getDocument().addDocumentListener(new AutoFilterDocumentListener());
            setEditable(true);
            addPopupMenuListener(new PopupMenuListenerImpl());
        }

        public Vector getModelData() {
            //reverse the model order, because it will be un-reversed when we reload it from saved settings
            Vector vector = new Vector();
            for (Iterator iter = allEntries.iterator();iter.hasNext();) {
                vector.insertElementAt(iter.next(), 0);
            }
            return vector;
        }

        private void refilter() {
            //only refilter if we're not bypassing filtering AND the text has changed since the last call to refilter
            String textToMatch = getEditor().getItem().toString();
            if (bypassFiltering || (lastTextToMatch != null && lastTextToMatch.equals(textToMatch))) {
                return;
            }
            lastTextToMatch = textToMatch;
            displayedEntries.clear();
            bypassFiltering = true;
                model.removeAllElements();
                List entriesCopy = new ArrayList(allEntries);
                for (Iterator iter = entriesCopy.iterator();iter.hasNext();) {
                    String thisEntry = iter.next().toString();
                    if (thisEntry.toLowerCase().contains(textToMatch.toLowerCase())) {
                        displayedEntries.add(thisEntry);
                        model.addElement(thisEntry);
                    }
                }
                bypassFiltering = false;
                //TODO: on no-match, don't filter at all (show the popup?)
                if (displayedEntries.size() > 0 && !textToMatch.equals("")) {
                    showPopup();
                } else {
                    hidePopup();
                }
        }

        class AutoFilterEditor implements ComboBoxEditor {
            public Component getEditorComponent() {
                return textField;
            }

            public void setItem(Object item) {
                if (bypassFiltering) {
                    return;
                }
                bypassFiltering = true;
                if (item == null) {
                    textField.setText("");
                } else {
                    textField.setText(item.toString());
                }
                bypassFiltering = false;
            }

            public Object getItem() {
                return textField.getText();
            }

            public void selectAll() {
                textField.selectAll();
            }

            public void addActionListener(ActionListener listener) {
                textField.addActionListener(listener);
            }

            public void removeActionListener(ActionListener listener) {
                textField.removeActionListener(listener);
            }
        }

        class AutoFilterDocumentListener implements DocumentListener {
            public void insertUpdate(DocumentEvent e) {
                refilter();
            }

            public void removeUpdate(DocumentEvent e) {
                refilter();
            }

            public void changedUpdate(DocumentEvent e) {
                refilter();
            }
        }

        class AutoFilterComboBoxModel extends AbstractListModel implements MutableComboBoxModel {
            private Object selectedItem;

            public void addElement(Object obj) {
                //assuming add is to displayed list...add to full list (only if not a dup)
                if (allEntries.contains(obj)) {
                    return;
                }
                bypassFiltering = true;
                allEntries.add(obj);
                displayedEntries.add(obj);
                fireIntervalAdded(this, displayedEntries.size() - 1, displayedEntries.size() -1);
                bypassFiltering = false;
            }

            public void removeElement(Object obj) {
                int index = displayedEntries.indexOf(obj);
                if (index != -1) {
                    removeElementAt(index);
                }
            }

            public void insertElementAt(Object obj, int index) {
                //assuming add is to displayed list...add to full list (only if not a dup)
                if (allEntries.contains(obj)) {
                    return;
                }
                bypassFiltering = true;
                displayedEntries.add(index, obj);
                allEntries.add(index, obj);
                fireIntervalAdded(this, index, index);
                bypassFiltering = false;
                refilter();
            }

            public void removeElementAt(int index) {
                bypassFiltering = true;
                //assuming removal is from displayed list..remove from full list
                Object obj = displayedEntries.get(index);
                allEntries.remove(obj);
                fireContentsChanged(this, 0, displayedEntries.size());
                bypassFiltering = false;
                refilter();
            }

            public void setSelectedItem(Object item) {
                if ((selectedItem != null && !selectedItem.equals(item)) || selectedItem == null && item != null) {
                    selectedItem = item;
                    fireContentsChanged(this, -1, -1);
                }
            }

            public Object getSelectedItem() {
                return selectedItem;
            }

            public int getSize() {
                return displayedEntries.size();
            }

            public Object getElementAt(int index) {
                if (index >= 0 && index < displayedEntries.size()) {
                    return displayedEntries.get(index);
                }
                return null;
            }


            public void removeAllElements() {
                bypassFiltering = true;
                displayedEntries.clear();
                fireContentsChanged(this, 0, displayedEntries.size());
                bypassFiltering = false;
            }

            public void showAllElements() {
                bypassFiltering = true;
                displayedEntries.clear();
                displayedEntries.addAll(allEntries);
                fireContentsChanged(this, 0, displayedEntries.size());
                bypassFiltering = false;
            }
        }

        private class PopupMenuListenerImpl implements PopupMenuListener {
            private boolean willBecomeVisible = false;

            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
                bypassFiltering = true;
                ((JComboBox)e.getSource()).setSelectedIndex(-1);
                bypassFiltering = false;
                if (!willBecomeVisible) {
                    //we already have a match but we're showing the popup - unfilter
                    if (displayedEntries.contains(textField.getText())) {
                        model.showAllElements();
                    }

                    //workaround for bug http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4743225
                    //the height of the popup after updating entries in this listener was not updated..
                    JComboBox list = (JComboBox) e.getSource();
                    willBecomeVisible = true; // the flag is needed to prevent a loop
                    try {
                        list.getUI().setPopupVisible(list, true);
                    } finally {
                        willBecomeVisible = false;
                    }
                }
            }

            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
                //no-op
            }

            public void popupMenuCanceled(PopupMenuEvent e) {
                //no-op
            }
        }
    }

  class ToggleToolTips extends JCheckBoxMenuItem {
    public ToggleToolTips() {
      super("Show ToolTips", new ImageIcon(ChainsawIcons.TOOL_TIP));
  addActionListener(
    new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        preferenceModel.setToolTips(isSelected());
      }
    });
    }
  }
}
