/*
 * 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 com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
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.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 javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.text.Document;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.*;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.List;
import org.apache.log4j.chainsaw.logevents.ChainsawLoggingEvent;
import org.apache.log4j.chainsaw.logevents.Level;
import org.apache.log4j.plugins.Receiver;
import org.apache.log4j.spi.LoggingEventFieldResolver;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;


/**
 * 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>
 *
 * @author Scott Deboy (sdeboy at apache.org)
 * @author Paul Smith (psmith at apache.org)
 * @author Stephen Pain
 * @author Isuru Suriarachchi
 * @see org.apache.log4j.chainsaw.color.ColorPanel
 * @see org.apache.log4j.rule.ExpressionRule
 * @see org.apache.log4j.spi.LoggingEventFieldResolver
 */
public class LogPanel extends DockablePanel implements Profileable, ChainsawEventBatchListener {
    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();
    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;
    private ChainsawReceiver m_receiver;
    private ChainsawStatusBar m_statusBar;

    /**
     * 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<String, RuleColorizer> allColorizers, final ApplicationPreferenceModel applicationPreferenceModel,
                    ChainsawStatusBar sb) {
        m_statusBar = sb;
        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<Object, String> 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) {
                            m_statusBar.setMessage(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 = Integer.parseInt(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);
        addPropertyChangeListener("detailPaneDatetimeFormat", 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());
                setDetailPaneDatetimeFormat(layoutEditorPane.getDatetimeFormatter());
                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());
                    layoutEditorPane.setDatetimeFormatter(getDetailPaneDatetimeFormat());

                    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().m_timestamp.atZone(ZoneId.systemDefault()));
                                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 org.apache.log4j.chainsaw.logevents.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().m_message);
                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();
    }

    /**
     * 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 {
                logger.info("configuration for panel exists: " + xmlFile + " - " + identifier + ", loading");
                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();
                //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);
                    undockedFrame.setLocation(0, 0);
                    undockedFrame.setSize(new Dimension(1024, 768));
                } else {
                    loadDefaultColumnSettings(event);
                }
            } catch (Exception e) {
                logger.info("unable to load configuration for panel: " + xmlFile + " - " + identifier + " - using default settings", e);
                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<TableColumn> cols = table.getColumnModel().getColumns();
        while (cols.hasMoreElements()) {
            TableColumn c = 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());
            //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<LoggingEventWrapper> 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();
    }

    private void setDetailPaneDatetimeFormat(DateTimeFormatter datetimeFormat){
        DateTimeFormatter oldFormat = getDetailPaneDatetimeFormat();
        detailLayout.setDateformat(datetimeFormat);
        firePropertyChange(
            "detailPaneDatetimeFormat", oldFormat,
            getDetailPaneDatetimeFormat());
    }

    private DateTimeFormatter getDetailPaneDatetimeFormat() {
        return detailLayout.getDateformat();
    }

    /**
     * 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<String, TableColumn> columnNameMap = new HashMap<>();
        Map<String, TableColumn> 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<TableColumn> 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 = 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.format(loggingEventWrapper.getLoggingEvent());
    }

    /**
     * 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(ChainsawLoggingEvent event) {

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

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

    public void setReceiver( ChainsawReceiver rx ){
        m_receiver = rx;
        m_receiver.addPropertyChangeListener(((pce) -> {
            if( pce.getPropertyName().equals( "name" ) ){
                //this.identifier = pce.getNewValue();
            }
        }));
        m_receiver.addChainsawEventBatchListener(this);
    }

    public void receiveChainsawEventBatch(List<ChainsawLoggingEvent> 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 (ChainsawLoggingEvent event1 : events) {
                //create two separate loggingEventWrappers (main table and search table), as they have different info on display state
                LoggingEventWrapper loggingEventWrapper1 = new LoggingEventWrapper(event1);
                //if the clearTableExpressionRule is not null, evaluate & clear the table if it matches
                if (clearTableExpressionRule != null && clearTableExpressionRule.evaluate(event1, null)) {
                    logger.info("clear table expression matched - clearing table - matching event msg - " + event1.m_message);
                    clearEvents();
                }

                updateOtherModels(event1);
                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);
                }
            }
        });
    }

    /**
     * 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.format(loggingEventWrapper.getLoggingEvent()));
                    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<CellEditorListener> 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<CellEditorListener> 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<CellEditorListener> 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().m_level.ordinal() < Level.WARN.ordinal() && 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().m_level.ordinal() >= Level.WARN.ordinal() || 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<ThumbnailLoggingEventWrapper> primaryList = new ArrayList<>();
        protected List<ThumbnailLoggingEventWrapper> 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<ThumbnailLoggingEventWrapper> iter = secondaryList.iterator(); iter.hasNext(); ) {
                        ThumbnailLoggingEventWrapper wrapper = iter.next();
                        if ((wrapper.rowNum >= firstRow) && (wrapper.rowNum <= lastRow)) {
//                                System.out.println("deleting find: " + wrapper);
                            iter.remove();
                        }
                    }
                    for (Iterator<ThumbnailLoggingEventWrapper> iter = primaryList.iterator(); iter.hasNext(); ) {
                        ThumbnailLoggingEventWrapper wrapper = 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<ThumbnailLoggingEventWrapper> iter = secondaryList.iterator(); iter.hasNext(); ) {
                        ThumbnailLoggingEventWrapper wrapper = iter.next();
                        if ((wrapper.rowNum >= firstRow) && (wrapper.rowNum <= lastRow)) {
//                                System.out.println("update - deleting warning: " + wrapper);
                            iter.remove();
                        }
                    }
                    for (Iterator<ThumbnailLoggingEventWrapper> iter = primaryList.iterator(); iter.hasNext(); ) {
                        ThumbnailLoggingEventWrapper wrapper = 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().m_level;
        }

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