/*
 * 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.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.MouseListener;
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.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
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.Locale;
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.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 DateFormat TIMESTAMP_DATE_FORMAT = new SimpleDateFormat(Constants.TIMESTAMP_RULE_FORMAT);
  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 ApplicationPreferenceModel applicationPreferenceModel;
  private final LogPanelPreferencePanel logPanelPreferencesPanel;
  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 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 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 Logger logger = LogManager.getLogger(LogPanel.class);
  private AutoFilterComboBox filterCombo;
  private AutoFilterComboBox findCombo;
  private JScrollPane eventsPane;
  private int currentSearchMatchCount;
  private Rule clearTableExpressionRule;
  private int lowerPanelDividerLocation;
  private EventContainer searchModel;
  private final 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;
  private ColorizedEventAndSearchMatchThumbnail colorizedEventAndSearchMatchThumbnail;
  private EventTimeDeltaMatchThumbnail eventTimeDeltaMatchThumbnail;
  private boolean isDetailPanelVisible;

  /**
   * 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, final ApplicationPreferenceModel applicationPreferenceModel) {
    this.identifier = identifier;
    this.statusBar = statusBar;
    this.applicationPreferenceModel = applicationPreferenceModel;
    this.logPanelPreferencesPanel = new LogPanelPreferencePanel(preferenceModel, applicationPreferenceModel);
    logger.debug("creating logpanel for " + identifier);

    setLayout(new BorderLayout());

    String prototypeValue = "1231231231231231231231";

    filterCombo = new AutoFilterComboBox();
    findCombo = new AutoFilterComboBox();

    filterCombo.setPrototypeDisplayValue(prototypeValue);
    buildCombo(filterCombo, true, findCombo.model);

    findCombo.setPrototypeDisplayValue(prototypeValue);
    buildCombo(findCombo, false, filterCombo.model);

    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.ID_COL_NAME.toUpperCase(), LoggingEventFieldResolver.PROP_FIELD + Constants.LOG4J_ID_KEY);
    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(
            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();

    preferenceModel.addPropertyChangeListener(
      "scrollToBottom",
            evt -> {
              boolean value = (Boolean) evt.getNewValue();
              if (value) {
                scrollToBottom();
              }
            });
    /*
     * 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(
            e -> preferenceModel.setLogTreePanelVisible(
              menuItemLoggerTree.isSelected()));
    menuItemLoggerTree.setIcon(new ImageIcon(ChainsawIcons.WINDOW_ICON));

    final JCheckBoxMenuItem menuItemToggleDetails =
      new JCheckBoxMenuItem("Show Detail Pane");
    menuItemToggleDetails.addActionListener(
            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();
          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();
          renderer.setWrapMessage(wrap);
          table.tableChanged(new TableModelEvent(tableModel));
          searchRenderer.setWrapMessage(wrap);
          searchTable.tableChanged(new TableModelEvent(searchModel));
        }
      });

    preferenceModel.addPropertyChangeListener("searchResultsVisible",
            evt -> {
              boolean displaySearchResultsInDetailsIfAvailable = (Boolean) evt.getNewValue();
              if (displaySearchResultsInDetailsIfAvailable) {
                showSearchResults();
              } else {
                hideSearchResults();
              }
            });

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

    preferenceModel.addPropertyChangeListener(
      "detailPaneVisible",
            evt -> {
              boolean detailPaneVisible = (Boolean) evt.getNewValue();

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

    preferenceModel.addPropertyChangeListener(
      "logTreePanelVisible",
            evt -> {
              boolean newValue = (Boolean) evt.getNewValue();

              if (newValue) {
                showLogTreePanel();
              } else {
                hideLogTreePanel();
              }
            });
    
    preferenceModel.addPropertyChangeListener("toolTips",
      new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
          boolean toolTips = (Boolean) evt.getNewValue();
          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 (Object o1 : preferenceModel.getVisibleColumnOrder()) {
            TableColumn c = (TableColumn) o1;
            if (c.getHeaderValue().toString().equalsIgnoreCase(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 (Object o : preferenceModel.getVisibleColumnOrder()) {
            TableColumn c = (TableColumn) o;
            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", 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",
            evt -> {
              boolean value = (Boolean) evt.getNewValue();
              searchToggleToolTips.setSelected(value);
              mainToggleToolTips.setSelected(value);
            });

    preferenceModel.addPropertyChangeListener(
      "logTreePanelVisible",
            evt -> {
              boolean value = (Boolean) evt.getNewValue();
              menuItemLoggerTree.setSelected(value);
            });

    preferenceModel.addPropertyChangeListener(
      "detailPaneVisible",
            evt -> {
              boolean value = (Boolean) evt.getNewValue();
              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, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "none");
    table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | 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, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "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, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "none");
    searchTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | 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, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "none");

    //add a listener to update the 'refine focus'
    tableModel.addNewKeyListener(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(
            (currentCount, 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) / tableModel.getMaxSize();
            String msg;
            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(evt -> {
        if (evt.getPropertyName().equals("searchExpression")) {
            findCombo.setSelectedItem(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(
            e -> colorFrame.setVisible(false));

    colorizer.addPropertyChangeListener(
      "colorrule",
      new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent evt) {
          for (Object o : tableModel.getAllEvents()) {
            LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper) o;
            loggingEventWrapper.updateColorRuleColors(colorizer.getBackgroundColor(loggingEventWrapper.getLoggingEvent()), colorizer.getForegroundColor(loggingEventWrapper.getLoggingEvent()));
          }
//          no need to update searchmodel events since tablemodel and searchmodel share all events, and color rules aren't different between the two
//          if that changes, un-do the color syncing in loggingeventwrapper & re-enable this code
//
//          for (Iterator iter = searchModel.getAllEvents().iterator();iter.hasNext();) {
//             LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper)iter.next();
//             loggingEventWrapper.updateColorRuleColors(colorizer.getBackgroundColor(loggingEventWrapper.getLoggingEvent()), colorizer.getForegroundColor(loggingEventWrapper.getLoggingEvent()));
//           }
          colorizedEventAndSearchMatchThumbnail.configureColors();
          lowerPanel.revalidate();
          lowerPanel.repaint();

          searchTable.revalidate();
          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(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"));
          //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(
            e -> SwingHelper.invokeOnEDT(() -> {
// 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)) {
                if (preferenceModel.isColumnVisible(col) || !applicationPreferenceModel.isDefaultColumnsSet() || applicationPreferenceModel.isDefaultColumnsSet() &&
                        applicationPreferenceModel.getDefaultColumnNames().contains(col.getHeaderValue())) {
                  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();
    upperPanel.setLayout(new BoxLayout(upperPanel, BoxLayout.X_AXIS));
    upperPanel.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 0));

    final JLabel filterLabel = new JLabel("Refine focus on: ");
    filterLabel.setFont(filterLabel.getFont().deriveFont(Font.BOLD));

    upperPanel.add(filterLabel);
    upperPanel.add(Box.createHorizontalStrut(3));
    upperPanel.add(filterCombo);
    upperPanel.add(Box.createHorizontalStrut(3));

    final JTextField filterText =(JTextField) filterCombo.getEditor().getEditorComponent();
    final JTextField findText =(JTextField) findCombo.getEditor().getEditorComponent();


    //Adding a button to clear filter expressions which are currently remembered by Chainsaw...
    final JButton removeFilterButton = new JButton(" Remove ");

    removeFilterButton.setToolTipText("Click here to remove the selected expression from the list");
    removeFilterButton.addActionListener(
            new AbstractAction() {
                public void actionPerformed(ActionEvent e){
                	Object selectedItem = filterCombo.getSelectedItem();
                    if (e.getSource() == removeFilterButton && selectedItem != null && !selectedItem.toString().trim().equals("")){
                      //don't just remove the entry from the store, clear the field
                      int index = filterCombo.getSelectedIndex();
                      filterText.setText(null);
                      filterCombo.setSelectedIndex(-1);
                      filterCombo.removeItemAt(index);
                      if (!(findCombo.getSelectedItem() != null && findCombo.getSelectedItem().equals(selectedItem))) {
                        //now remove the entry from the other model
                        ((AutoFilterComboBox.AutoFilterComboBoxModel)findCombo.getModel()).removeElement(selectedItem);
                      }
                    }
                }
            }
    );
    upperPanel.add(removeFilterButton);
    //add some space between refine focus and search sections of the panel
    upperPanel.add(Box.createHorizontalStrut(25));

    final JLabel findLabel = new JLabel("Find: ");
    findLabel.setFont(filterLabel.getFont().deriveFont(Font.BOLD));

    upperPanel.add(findLabel);
    upperPanel.add(Box.createHorizontalStrut(3));

    upperPanel.add(findCombo);
    upperPanel.add(Box.createHorizontalStrut(3));

    Action findNextAction = getFindNextAction();
    Action findPreviousAction = getFindPreviousAction();
    //add up & down search
    JButton findNextButton = new SmallButton(findNextAction);
    findNextButton.setText("");
    findNextButton.getActionMap().put(
      findNextAction.getValue(Action.NAME), findNextAction);
    findNextButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
      (KeyStroke) findNextAction.getValue(Action.ACCELERATOR_KEY),
      findNextAction.getValue(Action.NAME));

    JButton findPreviousButton = new SmallButton(findPreviousAction);
    findPreviousButton.setText("");
    findPreviousButton.getActionMap().put(
      findPreviousAction.getValue(Action.NAME), findPreviousAction);
    findPreviousButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
      (KeyStroke) findPreviousAction.getValue(Action.ACCELERATOR_KEY),
      findPreviousAction.getValue(Action.NAME));

    upperPanel.add(findNextButton);

    upperPanel.add(findPreviousButton);
    upperPanel.add(Box.createHorizontalStrut(3));
    
    //Adding a button to clear filter expressions which are currently remembered by Chainsaw...
    final JButton removeFindButton = new JButton(" Remove ");
    removeFindButton.setToolTipText("Click here to remove the selected expression from the list");
    removeFindButton.addActionListener(
            new AbstractAction() {
                public void actionPerformed(ActionEvent e){
                	Object selectedItem = findCombo.getSelectedItem();
                    if (e.getSource() == removeFindButton && selectedItem != null && !selectedItem.toString().trim().equals("")){
                      //don't just remove the entry from the store, clear the field
                      int index = findCombo.getSelectedIndex();
                      findText.setText(null);
                      findCombo.setSelectedIndex(-1);
                      findCombo.removeItemAt(index);
                      if (!(filterCombo.getSelectedItem() != null && filterCombo.getSelectedItem().equals(selectedItem))) {
                        //now remove the entry from the other model if it wasn't selected
                        ((AutoFilterComboBox.AutoFilterComboBoxModel)filterCombo.getModel()).removeElement(selectedItem);
                      }
                    }
                }
            }
    );
    upperPanel.add(removeFindButton);

    //define search and refine focus selection and clear actions
    Action findFocusAction = new AbstractAction() {
      public void actionPerformed(ActionEvent actionEvent) {
        findCombo.requestFocus();
      }
    };

    Action filterFocusAction = new AbstractAction() {
      public void actionPerformed(ActionEvent actionEvent) {
        filterCombo.requestFocus();
      }
    };

    Action findClearAction = new AbstractAction() {
      public void actionPerformed(ActionEvent actionEvent) {
        findCombo.setSelectedIndex(-1);
        findNext();
      }
    };

    Action filterClearAction = new AbstractAction() {
      public void actionPerformed(ActionEvent actionEvent) {
        setRefineFocusText("");
        filterCombo.refilter();
      }
    };

    //now add them to the action and input maps for the logpanel
        KeyStroke ksFindFocus =
      KeyStroke.getKeyStroke(KeyEvent.VK_F, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
    KeyStroke ksFilterFocus =
      KeyStroke.getKeyStroke(KeyEvent.VK_R, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
        KeyStroke ksFindClear =
      KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.SHIFT_MASK |Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
    KeyStroke ksFilterClear =
      KeyStroke.getKeyStroke(KeyEvent.VK_R,  InputEvent.SHIFT_MASK | Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());

    getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ksFindFocus, "FindFocus");
    getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ksFilterFocus, "FilterFocus");
    getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ksFindClear, "FindClear");
    getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ksFilterClear, "FilterClear");

    getActionMap().put("FindFocus", findFocusAction);
    getActionMap().put("FilterFocus", filterFocusAction);
    getActionMap().put("FindClear", findClearAction);
    getActionMap().put("FilterClear", filterClearAction);

    /*
     * 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(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 JPanel();
    rightThumbNailPanel.setLayout(new BoxLayout(rightThumbNailPanel, BoxLayout.Y_AXIS));
    rightThumbNailPanel.add(Box.createVerticalStrut(scrollBarWidth));
    colorizedEventAndSearchMatchThumbnail = new ColorizedEventAndSearchMatchThumbnail();
    rightThumbNailPanel.add(colorizedEventAndSearchMatchThumbnail);
    rightThumbNailPanel.add(Box.createVerticalStrut(scrollBarWidth));
    rightPanel.add(rightThumbNailPanel);
    //set thumbnail width to be a bit narrower than scrollbar width
    if (scrollBarWidth != null) {
        rightThumbNailPanel.setPreferredSize(new Dimension(scrollBarWidth -4, -1));
    }
    eventsAndStatusPanel.add(rightPanel, BorderLayout.EAST);

    JPanel leftPanel = new JPanel();
    leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS));

    JPanel leftThumbNailPanel = new JPanel();
    leftThumbNailPanel.setLayout(new BoxLayout(leftThumbNailPanel, BoxLayout.Y_AXIS));
    leftThumbNailPanel.add(Box.createVerticalStrut(scrollBarWidth));
    eventTimeDeltaMatchThumbnail = new EventTimeDeltaMatchThumbnail();
    leftThumbNailPanel.add(eventTimeDeltaMatchThumbnail);
    leftThumbNailPanel.add(Box.createVerticalStrut(scrollBarWidth));
    leftPanel.add(leftThumbNailPanel);

    //set thumbnail width to be a bit narrower than scrollbar width
    if (scrollBarWidth != null) {
        leftThumbNailPanel.setPreferredSize(new Dimension(scrollBarWidth -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(
            e -> layoutEditorDialog.setVisible(false));

    layoutEditorPane.addOkActionListener(
            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;
            }
            findCombo.setSelectedItem("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(
            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(
          evt -> showColorPreferences());
      }
    }

    class LogPanelPreferences extends JMenuItem {
      public LogPanelPreferences() {
        super("Tab Preferences...");
        setIcon(ChainsawIcons.ICON_PREFERENCES);
    addActionListener(
            evt -> showPreferences());
    }
  }

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

                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(
          evt -> {
            if (currentPoint != null) {
              String operator = "==";
              int column = currentTable.columnAtPoint(currentPoint);
              int row = currentTable.rowAtPoint(currentPoint);
              String value = getValueOf(row, column);
              String colName = currentTable.getColumnName(column).toUpperCase();

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

            }
          });
      }
    }

        class DefineAddCustomFind extends JMenuItem {
      public DefineAddCustomFind() {
        super("Add value under pointer to 'find' field");
  addActionListener(
          evt -> {
            if (currentPoint != null) {
              String operator = "==";
              int column = currentTable.columnAtPoint(currentPoint);
              int row = currentTable.rowAtPoint(currentPoint);
              String value = getValueOf(row, column);
              String colName = currentTable.getColumnName(column).toUpperCase();

              if (columnNameKeywordMap.containsKey(colName)) {
                findCombo.setSelectedItem(
                  findText.getText() + " && "
                  + columnNameKeywordMap.get(colName).toString() + " "
                  + operator + " '" + value + "'");
                findNext();
              }
            }
          });
      }
    }

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

                  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 CopySelection extends AbstractAction {
      public CopySelection() {
        super("Copy selection to clipboard");
      }

        public void actionPerformed(ActionEvent e) {
          if (currentTable == null) {
            return;
          }
          int start = currentTable.getSelectionModel().getMinSelectionIndex();
          int end = currentTable.getSelectionModel().getMaxSelectionIndex();
          StringBuilder result = new StringBuilder();
          for (int row=start;row<end+1;row++) {
            for (int column=0;column<currentTable.getColumnCount();column++) {
              result.append(getValueOf(row, column));
              if (column != (currentTable.getColumnCount() - 1)) {
                result.append(" - ");
              }
            }
            result.append(System.getProperty("line.separator"));
          }
          StringSelection selection = new StringSelection(result.toString());
          Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
          clipboard.setContents(selection, null);
      }
    }

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

        public void actionPerformed(ActionEvent e) {
          if (currentPoint != null && currentTable != null) {
            int column = currentTable.columnAtPoint(currentPoint);
            int row = currentTable.rowAtPoint(currentPoint);
            String value = getValueOf(row, column);
            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("Find value under pointer");

    addActionListener(
            evt -> {
              if (currentPoint != null) {
                String operator = "==";
                int column = currentTable.columnAtPoint(currentPoint);
                int row = currentTable.rowAtPoint(currentPoint);
                String colName = currentTable.getColumnName(column).toUpperCase();
                String value = getValueOf(row, column);
                if (columnNameKeywordMap.containsKey(colName)) {
                  findCombo.setSelectedItem(
                    columnNameKeywordMap.get(colName).toString() + " " + operator
                    + " '" + value + "'");
                  findNext();
                }
              }
            });
      }
    }

     class ClearSearch extends AbstractAction {
       public ClearSearch() {
         super("Clear find field");
       }
          public void actionPerformed(ActionEvent e) {
            findCombo.setSelectedItem(null);
            updateFindRule(null);
          }
        }

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

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

    class DisplayNormalTimes extends JMenuItem {
      public DisplayNormalTimes() {
        super("Hide relative times");
  addActionListener(
          e -> {
            if (currentPoint != null) {
              ((TableColorizingRenderer)currentTable.getDefaultRenderer(Object.class)).setUseNormalTimes();
              ((ChainsawCyclicBufferTableModel)currentTable.getModel()).reFilter();
              setEnabled(true);
            }
          });
      }
    }

    class DisplayRelativeTimesToRowUnderCursor extends JMenuItem {
    public DisplayRelativeTimesToRowUnderCursor() {
      super("Show times relative to this event");
      addActionListener(
              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(
              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 JSeparator());
    searchPopup.add(new JSeparator());
    mainPopup.add(new CopyField());
    mainPopup.add(new CopySelection());
    searchPopup.add(new CopyField());
    searchPopup.add(new CopySelection());
    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());

    mainPopup.add(menuItemToggleDock);

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

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

    table.addMouseListener(new MouseListener(){
      public void mouseClicked(MouseEvent mouseEvent) {
        checkMultiSelect(mouseEvent);
      }

      public void mousePressed(MouseEvent mouseEvent) {
        checkMultiSelect(mouseEvent);
      }

      public void mouseReleased(MouseEvent mouseEvent) {
        checkMultiSelect(mouseEvent);
      }

      public void mouseEntered(MouseEvent mouseEvent) {
        checkMultiSelect(mouseEvent);
      }

      public void mouseExited(MouseEvent mouseEvent) {
        checkMultiSelect(mouseEvent);
      }

      private void checkMultiSelect(MouseEvent mouseEvent) {
        if (mouseEvent.isAltDown()) {
          table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
        } else {
          table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        }
      }
    });


    searchTable.addMouseListener(new MouseListener(){
      public void mouseClicked(MouseEvent mouseEvent) {
        checkMultiSelect(mouseEvent);
      }

      public void mousePressed(MouseEvent mouseEvent) {
        checkMultiSelect(mouseEvent);
      }

      public void mouseReleased(MouseEvent mouseEvent) {
        checkMultiSelect(mouseEvent);
      }

      public void mouseEntered(MouseEvent mouseEvent) {
        checkMultiSelect(mouseEvent);
      }

      public void mouseExited(MouseEvent mouseEvent) {
        checkMultiSelect(mouseEvent);
      }

      private void checkMultiSelect(MouseEvent mouseEvent) {
        if (mouseEvent.isAltDown()) {
          searchTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
        } else {
          searchTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        }
      }
    });


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

       private String getValueOf(int row, int column) {
         if (currentTable == null) {
           return "";
         }

         Object o = currentTable.getValueAt(row, column);

         if (o instanceof Date) {
           return TIMESTAMP_DATE_FORMAT.format((Date)o);
         }

         if (o instanceof String) {
           return (String)o;
         }

         if (o instanceof Level) {
           return o.toString();
         }

         if (o instanceof String[]) {
           StringBuilder value = new StringBuilder();
          //exception - build message + throwable
          String[] ti = (String[])o;
            if (ti.length > 0 && (!(ti.length == 1 && ti[0].equals("")))) {
              LoggingEventWrapper loggingEventWrapper = ((ChainsawCyclicBufferTableModel)(currentTable.getModel())).getRow(row);
              value = new StringBuilder(loggingEventWrapper.getLoggingEvent().getMessage().toString());
              for (int i=0;i<((String[])o).length;i++) {
                  value.append('\n').append(((String[]) o)[i]);
              }
            }
           return value.toString();
         }
         return "";
      }

    private Action getFindNextAction() {
    final Action action =
      new AbstractAction("Find next") {
        public void actionPerformed(ActionEvent e) {
          findNext();
        }
      };

    //    action.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_F));
    action.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("F3"));
    action.putValue(
      Action.SHORT_DESCRIPTION,
      "Find the next occurrence of the rule from the current row");
    action.putValue(Action.SMALL_ICON, new ImageIcon(ChainsawIcons.DOWN));

    return action;
  }

  private Action getFindPreviousAction() {
    final Action action =
      new AbstractAction("Find previous") {
        public void actionPerformed(ActionEvent e) {
            findPrevious();
        }
      };

    //    action.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_F));
    action.putValue(
      Action.ACCELERATOR_KEY,
      KeyStroke.getKeyStroke(KeyEvent.VK_F3, InputEvent.SHIFT_MASK));
    action.putValue(
      Action.SHORT_DESCRIPTION,
      "Find the previous occurrence of the rule from the current row");
    action.putValue(Action.SMALL_ICON, new ImageIcon(ChainsawIcons.UP));

    return action;
  }

  private  void buildCombo(final AutoFilterComboBox combo, boolean isFiltering, final AutoFilterComboBox.AutoFilterComboBoxModel otherModel) {
    //add (hopefully useful) default filters
    combo.addItem("LEVEL == TRACE");
    combo.addItem("LEVEL >= DEBUG");
    combo.addItem("LEVEL >= INFO");
    combo.addItem("LEVEL >= WARN");
    combo.addItem("LEVEL >= ERROR");
    combo.addItem("LEVEL == FATAL");

    final JTextField filterText =(JTextField) combo.getEditor().getEditorComponent();
    if (isFiltering) {
      filterText.getDocument().addDocumentListener(new DelayedTextDocumentListener(filterText));
    }
    filterText.setToolTipText("Enter an expression - right click or ctrl-space for menu - press enter to add to list");
    filterText.addKeyListener(new ExpressionRuleContext(filterModel, filterText));

    if (combo.getEditor().getEditorComponent() instanceof JTextField) {
      combo.addActionListener(
        new AbstractAction() {
          public void actionPerformed(ActionEvent e) {
            if (e.getActionCommand().equals("comboBoxEdited")) {
              try {
                //verify the expression is valid
                  Object item = combo.getSelectedItem();
                  if (item != null && !item.toString().trim().equals("")) {
                    ExpressionRule.getRule(item.toString());
                    //add entry as first row of the combo box
                    combo.insertItemAt(item, 0);
                    otherModel.insertElementAt(item, 0);
                  }
                //valid expression, reset background color in case we were previously an invalid expression
                filterText.setBackground(UIManager.getColor("TextField.background"));
              } catch (IllegalArgumentException iae) {
                  //don't add expressions that aren't valid
                  //invalid expression, change background of the field
                  filterText.setToolTipText(iae.getMessage());
                  filterText.setBackground(ChainsawConstants.INVALID_EXPRESSION_BACKGROUND);
              }
            }
          }
        });
    }
  }

  /**
   * Accessor
   *
   * @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() {
    //run this in an invokeLater block to ensure this action is enqueued to the end of the EDT
    EventQueue.invokeLater(() -> {
      int scrollRow = tableModel.getRowCount() - 1;
        table.scrollToRow(scrollRow);
    });
  }

  public void scrollToTop() {
      EventQueue.invokeLater(() -> {
          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(() -> {
      /*
      * 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 (Object event1 : events) {
        //these are actual LoggingEvent instances
        LoggingEvent event = (LoggingEvent) event1;
        //create two separate loggingEventWrappers (main table and search table), as they have different info on display state
        LoggingEventWrapper loggingEventWrapper1 = new LoggingEventWrapper(event);
        //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);
        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 = null;
    try {
      xmlFile = new File(SettingsManager.getInstance().getSettingsDirectory(), URLEncoder.encode(identifier, "UTF-8") + ".xml");
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }

    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 (Object item : savedVector) {
                //insert each row at index zero (so last row in vector will be row zero)
                filterCombo.insertItemAt(item, 0);
                findCombo.insertItemAt(item, 0);
              }
                if (versionNumber > 1) {
                    //update prefModel columns to include defaults
                    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 (Object o1 : preferenceModel.getVisibleColumnOrder()) {
                    TableColumn col = (TableColumn) o1;
                    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 (Object o : preferenceModel.getVisibleColumnOrder()) {
                    TableColumn col = (TableColumn) o;
                    searchColumnModel.addColumn(col);
                  }

                    preferenceModel.apply(storedPrefs);
                } else {
                    loadDefaultColumnSettings(event);
                }
                //ensure tablemodel cyclic flag is updated
                //may be panel configs that don't have these values
                tableModel.setCyclic(preferenceModel.isCyclic());
                searchModel.setCyclic(preferenceModel.isCyclic());
                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 {
        //not setting lower panel divider location here - will do that after the UI is visible
        loadDefaultColumnSettings(event);
    }
    //ensure tablemodel cyclic flag is updated
    tableModel.setCyclic(preferenceModel.isCyclic());
    searchModel.setCyclic(preferenceModel.isCyclic());
    logTreePanel.ignore(preferenceModel.getHiddenLoggers());
    logTreePanel.setHiddenExpression(preferenceModel.getHiddenExpression());
    logTreePanel.setAlwaysDisplayExpression(preferenceModel.getAlwaysDisplayExpression());
    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;
    try {
      xmlFile = new File(SettingsManager.getInstance().getSettingsDirectory(), URLEncoder.encode(identifier, "UTF-8") + ".xml");
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
      //unable to save..just return
      return;
    }

    preferenceModel.setHiddenLoggers(new HashSet(logTreePanel.getHiddenSet()));
    preferenceModel.setHiddenExpression(logTreePanel.getHiddenExpression());
    preferenceModel.setAlwaysDisplayExpression(logTreePanel.getAlwaysDisplayExpression());
    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 (isDetailPanelVisible) {
        //use current size
        s.writeInt(lowerPanel.getDividerLocation());
      } else {
        //use size when last hidden
        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
        Vector combinedVector = new Vector();
        combinedVector.addAll(filterCombo.getModelData());
        combinedVector.addAll(findCombo.getModelData());
        //duplicates will be removed when loaded..
        s.writeObject(combinedVector);
    } catch (Exception ex) {
        ex.printStackTrace();
        // TODO need to log this..
    } 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();

    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(() -> 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
      findCombo.setBackground(UIManager.getColor("TextField.background"));
      findCombo.setToolTipText(
        "Enter an expression - right click or ctrl-space for menu - press enter to add to list");
      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 {
        final JTextField findText =(JTextField) findCombo.getEditor().getEditorComponent();
        findText.setToolTipText(
          "Enter an expression - right click or ctrl-space for menu - press enter to add to list");
        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
        findText.setBackground(UIManager.getColor("TextField.background"));
        statusBar.setSearchMatchCount(currentSearchMatchCount, getIdentifier());
        if (isSearchResultsVisible()) {
          showSearchResults();
        }
      } catch (IllegalArgumentException re) {
        findRule = null;
        final JTextField findText =(JTextField) findCombo.getEditor().getEditorComponent();
        findText.setToolTipText(re.getMessage());
        findText.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();
      JPanel leftSpacePanel = new JPanel();
      Integer scrollBarWidth = (Integer) UIManager.get("ScrollBar.width");
      leftSpacePanel.setPreferredSize(new Dimension(scrollBarWidth -4, -1));

      JPanel rightSpacePanel = new JPanel();
      rightSpacePanel.setPreferredSize(new Dimension(scrollBarWidth -4, -1));

      detailPanel.add(detailToolbar, BorderLayout.NORTH);
      detailPanel.add(detailPane, BorderLayout.CENTER);

      detailPanel.add(leftSpacePanel, BorderLayout.WEST);
      detailPanel.add(rightSpacePanel, BorderLayout.EAST);
 
      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);
      Integer scrollBarWidth = (Integer) UIManager.get("ScrollBar.width");
      JPanel leftSpacePanel = new JPanel();
      leftSpacePanel.setPreferredSize(new Dimension(scrollBarWidth -4, -1));
      JPanel rightSpacePanel = new JPanel();
      rightSpacePanel.setPreferredSize(new Dimension(scrollBarWidth -4, -1));
      detailPanel.add(leftSpacePanel, BorderLayout.WEST);
      detailPanel.add(rightSpacePanel, BorderLayout.EAST);
      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() {
    if (!isDetailPanelVisible) {
      lowerPanel.setDividerSize(dividerSize);
      if (lowerPanelDividerLocation == 0) {
        lowerPanel.setDividerLocation(DEFAULT_DETAIL_SPLIT_LOCATION);
        lowerPanelDividerLocation = lowerPanel.getDividerLocation();
      } else {
        lowerPanel.setDividerLocation(lowerPanelDividerLocation);
      }
      detailPanel.setVisible(true);
      detailPanel.repaint();
      lowerPanel.repaint();
      isDetailPanelVisible = true;
    }
  }

  /**
   * Hide the detail pane, holding the current divider location for later use
   */
  private void hideDetailPane() {
    //may be called not currently visible on initial setup to ensure panel is not visible..only update divider location if hiding when currently visible
    if (isDetailPanelVisible) {
      lowerPanelDividerLocation = lowerPanel.getDividerLocation();
    }
    lowerPanel.setDividerSize(0);
    detailPanel.setVisible(false);
    lowerPanel.repaint();
    isDetailPanelVisible = false;
  }

  /**
   * 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, 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",
            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, KeyEvent.VK_T);
      dockToggleLogTreeAction.putValue(
        Action.ACCELERATOR_KEY,
        KeyStroke.getKeyStroke(KeyEvent.VK_T, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
      dockToggleLogTreeAction.putValue(
        Action.SMALL_ICON, new ImageIcon(ChainsawIcons.WINDOW_ICON));

    final SmallToggleButton toggleLogTreeButton =
      new SmallToggleButton(dockToggleLogTreeAction);
    preferenceModel.addPropertyChangeListener("logTreePanelVisible", 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, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
      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", evt -> toggleScrollToBottomButton.setSelected(isScrollToBottom()));

      toggleScrollToBottomButton.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
  	      KeyStroke.getKeyStroke(KeyEvent.VK_B, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
  	      dockToggleScrollToBottomAction.getValue(Action.NAME));
  	    toggleScrollToBottomButton.getActionMap().put(
  	      dockToggleScrollToBottomAction.getValue(Action.NAME), dockToggleScrollToBottomAction);
      
      toggleScrollToBottomButton.setSelected(isScrollToBottom());
      toggleScrollToBottomButton.setText("");
      toolbar.add(toggleScrollToBottomButton);
      toolbar.addSeparator();

    findCombo.addActionListener(e -> {
      //comboboxchanged event received when text is modified in the field..when enter is pressed, it's comboboxedited
      if (e.getActionCommand().equalsIgnoreCase("comboBoxEdited")) {
          findNext();
      }
    });
    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(
            () -> {
              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(() -> {
        final int nextRow = tableModel.findColoredRow(table.getSelectedRow() + 1, true);
        if (nextRow > -1) {
            table.scrollToRow(nextRow);
        }
    });
  }

  public void findPreviousColorizedEvent() {
    EventQueue.invokeLater(() -> {
        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() {
    Object item = findCombo.getSelectedItem();
    updateFindRule(item == null ? null: item.toString());

    if (findRule != null) {
        EventQueue.invokeLater(() -> {
          final JTextField findText =(JTextField) findCombo.getEditor().getEditorComponent();
            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);
                findText.setToolTipText("Enter an expression - right click or ctrl-space for menu - press enter to add to list");
              }
              findText.setBackground(UIManager.getColor("TextField.background"));
            } catch (IllegalArgumentException iae) {
              findText.setToolTipText(iae.getMessage());
              findText.setBackground(ChainsawConstants.INVALID_EXPRESSION_BACKGROUND);
              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() {
    Object item = findCombo.getSelectedItem();
    updateFindRule(item == null ? null: item.toString());

    if (findRule != null) {
        EventQueue.invokeLater(() -> {
          final JTextField findText =(JTextField) findCombo.getEditor().getEditorComponent();
            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);
                    findCombo.setToolTipText("Enter an expression - right click or ctrl-space for menu - press enter to add to list");
                }
              findText.setBackground(UIManager.getColor("TextField.background"));
            } catch (IllegalArgumentException iae) {
              findText.setToolTipText(iae.getMessage());
              findText.setBackground(ChainsawConstants.INVALID_EXPRESSION_BACKGROUND);
            }
        });
    }
  }

  /**
   * 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(() -> 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;
    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 (Object aSortedColumnList : sortedColumnList) {
      TableColumn element = (TableColumn) aSortedColumnList;
      if (preferenceModel.addColumn(element)) {
        if (!applicationPreferenceModel.isDefaultColumnsSet() || applicationPreferenceModel.isDefaultColumnsSet() &&
                applicationPreferenceModel.getDefaultColumnNames().contains(element.getHeaderValue())) {
          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();
    }

  /**
   * 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) {
      return detailLayout.getHeader() + detailLayout.format(loggingEventWrapper.getLoggingEvent()) + detailLayout.getFooter();
  }

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

  public void setFindText(String findText) {
    findCombo.setSelectedItem(findText);
    findNext();
  }

  public String getFindText() {
    Object selectedItem = findCombo.getSelectedItem();
    if (selectedItem == null) {
      return "";
    }
    return selectedItem.toString();
  }

  /**
   * This class receives notification when the Refine focus or find field is
   * updated, where a background thread periodically wakes up and checks if
   * they have stopped typing yet. This ensures that the filtering of the
   * model is not done for every single character typed.
   *
   * @author Paul Smith psmith
   */
  private final class DelayedTextDocumentListener
    implements DocumentListener {
    private static final long CHECK_PERIOD = 1000;
    private final JTextField textField;
    private long lastTimeStamp = System.currentTimeMillis();
    private final Thread delayThread;
    private final String defaultToolTip;
    private String lastText = "";

    private DelayedTextDocumentListener(final JTextField textFeld) {
      super();
      this.textField = textFeld;
      this.defaultToolTip = textFeld.getToolTipText();

      this.delayThread =
        new Thread(
                () -> {
                  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 (!(textFeld.getText().trim().equals(lastText.trim()))) {
                        lastText = textFeld.getText();
                        EventQueue.invokeLater(DelayedTextDocumentListener.this::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 (textField.getText().trim().equals("")) {
        //reset background color in case we were previously an invalid expression
        textField.setBackground(UIManager.getColor("TextField.background"));
        tableRuleMediator.setFilterRule(null);
        searchRuleMediator.setFilterRule(null);
        textField.setToolTipText(defaultToolTip);
        if (findRule != null) {
          currentSearchMatchCount=tableModel.getSearchMatchCount();
          statusBar.setSearchMatchCount(currentSearchMatchCount, getIdentifier());
        }
      } else {
        try {
          tableRuleMediator.setFilterRule(ExpressionRule.getRule(textField.getText()));
          searchRuleMediator.setFilterRule(ExpressionRule.getRule(textField.getText()));
          textField.setToolTipText(defaultToolTip);
          if (findRule != null) {
            currentSearchMatchCount=tableModel.getSearchMatchCount();
            statusBar.setSearchMatchCount(currentSearchMatchCount, getIdentifier());
          }
          //valid expression, reset background color in case we were previously an invalid expression
          textField.setBackground(UIManager.getColor("TextField.background"));
        } catch (IllegalArgumentException iae) {
          //invalid expression, change background of the field
          textField.setToolTipText(iae.getMessage());
          textField.setBackground(ChainsawConstants.INVALID_EXPRESSION_BACKGROUND);
          if (findRule != null) {
            currentSearchMatchCount=tableModel.getSearchMatchCount();
            statusBar.setSearchMatchCount(currentSearchMatchCount, getIdentifier());
          }
        }
      }
    }
  }

  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 StringBuilder buf = new StringBuilder();
	          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(() -> {
                              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(() -> {
                      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(
              () -> 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...");
                  StringBuilder buf = new StringBuilder();
                  buf.append(loggingEventWrapper.getLoggingEvent().getMessage());
                  buf.append("\n");
              for (String aTi : ti) {
                buf.append(aTi).append("\n    ");
              }

                  detailArea.setText(buf.toString());
                  SwingHelper.invokeOnEDT(() -> 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 (Object aCellEditorListenersCopy : cellEditorListenersCopy) {
            ((CellEditorListener) aCellEditorListenersCopy).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 (Object aCellEditorListenersCopy : cellEditorListenersCopy) {
            ((CellEditorListener) aCellEditorListenersCopy).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 (Object o : tableModel.getFilteredEvents()) {
            LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper) o;
            ThumbnailLoggingEventWrapper wrapper = new ThumbnailLoggingEventWrapper(i, loggingEventWrapper);
            i++;
            //only add if there is a color defined
            if (primaryMatches(wrapper)) {
              primaryList.add(wrapper);
            }
          }
            revalidate();
            repaint();
        }

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

            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();
            int maxHeight = Math.min(maxEventHeight, (height / rowCount));
            int minHeight = Math.max(1, maxHeight);
            int componentHeight = height - minHeight;
            int eventHeight = minHeight;

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

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

  //a listener receiving color updates needs to call configureColors on this class
    private class ColorizedEventAndSearchMatchThumbnail extends AbstractEventMatchThumbnail {
        public ColorizedEventAndSearchMatchThumbnail() {
            super();
            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 (Object o : tableModel.getFilteredEvents()) {
            LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper) o;
            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);
            }
          }
            revalidate();
            repaint();
        }

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

            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();
            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 (Object aPrimaryList1 : primaryList) {
            ThumbnailLoggingEventWrapper wrapper = (ThumbnailLoggingEventWrapper) aPrimaryList1;
            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);

                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 (Object aPrimaryList : primaryList) {
            ThumbnailLoggingEventWrapper wrapper = (ThumbnailLoggingEventWrapper) aPrimaryList;
            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);

                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 (Object aSecondaryList : secondaryList) {
            ThumbnailLoggingEventWrapper wrapper = (ThumbnailLoggingEventWrapper) aSecondaryList;
            float ratio = (wrapper.rowNum / (float) rowCount);
//                System.out.println("warning - ratio: " + ratio + ", component height: " + componentHeight);
            int verticalLocation = (int) (componentHeight * ratio);

            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(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());
                }
                revalidate();
                repaint();
                //run this in an invokeLater block to ensure this action is enqueued to the end of the EDT
                EventQueue.invokeLater(() -> {
                  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();

            //'effective' height of this component is scrollpane height
            int height = eventsPane.getHeight();

            yPosition = Math.max(yPosition, 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 (Object aSecondaryList : secondaryList) {
            ThumbnailLoggingEventWrapper event = (ThumbnailLoggingEventWrapper) aSecondaryList;
            int newRowDelta = Math.abs(rowToSelect - event.rowNum);
            if (newRowDelta < rowDelta) {
              closestRow = event;
              rowDelta = newRowDelta;
            }
          }
          for (Object aPrimaryList : primaryList) {
            ThumbnailLoggingEventWrapper event = (ThumbnailLoggingEventWrapper) aPrimaryList;
            int newRowDelta = Math.abs(rowToSelect - event.rowNum);
            if (newRowDelta < rowDelta) {
              closestRow = event;
              rowDelta = newRowDelta;
            }
          }
            return closestRow;
        }

        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;

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

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

    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() {
            textField.setPreferredSize(getPreferredSize());
            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 (Object allEntry : allEntries) {
            vector.insertElementAt(allEntry, 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;
            bypassFiltering = true;
                model.removeAllElements();
                List entriesCopy = new ArrayList(allEntries);
          for (Object anEntriesCopy : entriesCopy) {
            String thisEntry = anEntriesCopy.toString();
            if (thisEntry.toLowerCase(Locale.ENGLISH).contains(textToMatch.toLowerCase())) {
              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)
                bypassFiltering = true;

              boolean entryExists = !allEntries.contains(obj);
              if (entryExists) {
                  allEntries.add(obj);
                }
                displayedEntries.add(obj);
                if (!entryExists) {
                  fireIntervalAdded(this, displayedEntries.size() - 1, displayedEntries.size());
                }
                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);
                displayedEntries.remove(obj);
                fireIntervalRemoved(this, index, index);
                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;
                int displayedEntrySize = displayedEntries.size();
                if (displayedEntrySize > 0) {
                  displayedEntries.clear();
                  //if firecontentschaned is used, the combobox resizes..use fireintervalremoved instead, which doesn't do that..
                  fireIntervalRemoved(this, 0, displayedEntrySize - 1);
                }
                bypassFiltering = false;
            }

            public void showAllElements() {
              //first remove whatever is there and fire necessary events then add events
                removeAllElements();
                bypassFiltering = true;
                displayedEntries.addAll(allEntries);
                if (displayedEntries.size() > 0) {
                  fireIntervalAdded(this, 0, displayedEntries.size() - 1);
                }
                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(
          evt -> preferenceModel.setToolTips(isSelected()));
    }
  }
}
