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

import 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.util.*;
import java.util.List;


/**
 * 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 EventBatchListener, Profileable {
    private static final DateFormat TIMESTAMP_DATE_FORMAT = new SimpleDateFormat(Constants.TIMESTAMP_RULE_FORMAT);
    private static final double DEFAULT_DETAIL_SPLIT_LOCATION = 0.71d;
    private static final double DEFAULT_LOG_TREE_SPLIT_LOCATION = 0.2d;
    private final String identifier;
    private final ChainsawStatusBar statusBar;
    private final JFrame logPanelPreferencesFrame = new JFrame();
    private ColorPanel colorPanel;
    private final JFrame colorFrame = new JFrame();
    private final JFrame undockedFrame;
    private final DockablePanel externalPanel;
    private final Action dockingAction;
    private final JToolBar undockedToolbar;
    private final JSortTable table;
    private final TableColorizingRenderer renderer;
    private final EventContainer tableModel;
    private final JEditorPane detail;
    private final JSplitPane lowerPanel;
    private final DetailPaneUpdater detailPaneUpdater;
    private final JPanel detailPanel = new JPanel(new BorderLayout());
    private final JSplitPane nameTreeAndMainPanelSplit;
    private final LoggerNameTreePanel logTreePanel;
    private final LogPanelPreferenceModel preferenceModel = new LogPanelPreferenceModel();
    private ApplicationPreferenceModel applicationPreferenceModel;
    private final LogPanelPreferencePanel logPanelPreferencesPanel;
    private final FilterModel filterModel = new FilterModel();
    private final RuleColorizer colorizer = new RuleColorizer();
    private final RuleMediator tableRuleMediator = new RuleMediator(false);
    private final RuleMediator searchRuleMediator = new RuleMediator(true);
    private final EventDetailLayout detailLayout = new EventDetailLayout();
    private double lastLogTreePanelSplitLocation = DEFAULT_LOG_TREE_SPLIT_LOCATION;
    private Point currentPoint;
    private JTable currentTable;
    private boolean paused = false;
    private Rule findRule;
    private String currentFindRuleText;
    private Rule findMarkerRule;
    private final int dividerSize;
    static final String TABLE_COLUMN_ORDER = "table.columns.order";
    static final String TABLE_COLUMN_WIDTHS = "table.columns.widths";
    static final String COLORS_EXTENSION = ".colors";
    private static final int LOG_PANEL_SERIALIZATION_VERSION_NUMBER = 2; //increment when format changes
    private int previousLastIndex = -1;
    private final Logger logger = LogManager.getLogger(LogPanel.class);
    private AutoFilterComboBox filterCombo;
    private AutoFilterComboBox findCombo;
    private JScrollPane eventsPane;
    private int currentSearchMatchCount;
    private Rule clearTableExpressionRule;
    private int lowerPanelDividerLocation;
    private EventContainer searchModel;
    private final JSortTable searchTable;
    private TableColorizingRenderer searchRenderer;
    private ToggleToolTips mainToggleToolTips;
    private ToggleToolTips searchToggleToolTips;
    private JScrollPane detailPane;
    private JScrollPane searchPane;
    //only one tableCellEditor, shared by both tables
    private TableCellEditor markerCellEditor;
    private JToolBar detailToolbar;
    private boolean searchResultsDisplayed;
    private ColorizedEventAndSearchMatchThumbnail colorizedEventAndSearchMatchThumbnail;
    private EventTimeDeltaMatchThumbnail eventTimeDeltaMatchThumbnail;
    private boolean isDetailPanelVisible;

    /**
     * Creates a new LogPanel object.  If a LogPanel with this identifier has
     * been loaded previously, reload settings saved on last exit.
     *
     * @param statusBar  shared status bar, provided by main application
     * @param identifier used to load and save settings
     */
    public LogPanel(final ChainsawStatusBar statusBar, final String identifier, int cyclicBufferSize,
                    Map<String, RuleColorizer> allColorizers, final ApplicationPreferenceModel applicationPreferenceModel) {
        this.identifier = identifier;
        this.statusBar = statusBar;
        this.applicationPreferenceModel = applicationPreferenceModel;
        this.logPanelPreferencesPanel = new LogPanelPreferencePanel(preferenceModel, applicationPreferenceModel);
        logger.debug("creating logpanel for " + identifier);

        setLayout(new BorderLayout());

        String prototypeValue = "1231231231231231231231";

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

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

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

        final Map<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) {
                            MessageCenter.getInstance().getLogger().info(msg);
                        }
                    }
                }
            });

        /*
         * Logger tree panel
         *
         */
        LogPanelLoggerTreeModel logTreeModel = new LogPanelLoggerTreeModel();
        logTreePanel = new LoggerNameTreePanel(logTreeModel, preferenceModel, this, colorizer, filterModel);
        logTreePanel.getLoggerVisibilityRule().addPropertyChangeListener(evt -> {
            if (evt.getPropertyName().equals("searchExpression")) {
                findCombo.setSelectedItem(evt.getNewValue().toString());
                findNext();
            }
        });

        tableModel.addLoggerNameListener(logTreeModel);
        tableModel.addLoggerNameListener(logTreePanel);

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

        colorizer.setLoggerRule(logTreePanel.getLoggerColorRule());

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

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

        colorFrame.getContentPane().add(colorPanel);

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

        colorPanel.setCloseActionListener(
            e -> colorFrame.setVisible(false));

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

                    searchTable.revalidate();
                    searchTable.repaint();
                }
            });

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

        table.setDefaultRenderer(Object.class, renderer);

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

        searchTable.setDefaultRenderer(Object.class, searchRenderer);

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

        //select a row in the main table when a row in the search table is selected
        searchTable.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                LoggingEventWrapper loggingEventWrapper = searchModel.getRow(searchTable.getSelectedRow());
                if (loggingEventWrapper != null) {
                    int id = 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);

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

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

        detailPanel.add(detailPane, BorderLayout.CENTER);

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

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

        eventsAndStatusPanel.add(eventsPane, BorderLayout.CENTER);

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

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

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

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

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

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

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

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

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

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

        layoutEditorPane.addCancelActionListener(
            e -> layoutEditorDialog.setVisible(false));

        layoutEditorPane.addOkActionListener(
            e -> {
                setDetailPaneConversionPattern(
                    layoutEditorPane.getConversionPattern());
                layoutEditorDialog.setVisible(false);
            });

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

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

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

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

                    layoutEditorDialog.setVisible(true);
                }
            };

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

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

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

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

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

        detailPanel.add(detailToolbar, BorderLayout.NORTH);

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

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

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

        JPopupMenu editDetailPopupMenu = new JPopupMenu();

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

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

        final ButtonGroup layoutGroup = new ButtonGroup();

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

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

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

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

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

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

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

        add(nameTreeAndMainPanelSplit, BorderLayout.CENTER);

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

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

        class ColorPanel extends JMenuItem {
            public ColorPanel() {
                super("Color settings...");
                setIcon(ChainsawIcons.ICON_PREFERENCES);
                addActionListener(
                    evt -> showColorPreferences());
            }
        }

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

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

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

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

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

                        }
                    });
            }
        }

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

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

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

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

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

        class ClearFocus extends AbstractAction {
            public ClearFocus() {
                super("Clear 'refine focus' field");
            }

            public void actionPerformed(ActionEvent e) {
                filterText.setText(null);
                tableRuleMediator.setFilterRule(null);
                searchRuleMediator.setFilterRule(null);
            }
        }

        class CopySelection extends AbstractAction {
            public CopySelection() {
                super("Copy selection to clipboard");
            }

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

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

            public void actionPerformed(ActionEvent e) {
                if (currentPoint != null && currentTable != null) {
                    int column = currentTable.columnAtPoint(currentPoint);
                    int row = currentTable.rowAtPoint(currentPoint);
                    String value = getValueOf(row, column);
                    StringSelection selection = new StringSelection(value);
                    Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
                    clipboard.setContents(selection, null);
                }
            }
        }
        final JMenuItem menuItemToggleDock = new JMenuItem("Undock/dock");

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

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

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

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

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

        class ClearSearch extends AbstractAction {
            public ClearSearch() {
                super("Clear find field");
            }

            public void actionPerformed(ActionEvent e) {
                findCombo.setSelectedItem(null);
                updateFindRule(null);
            }
        }

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

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

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

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

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

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

        mainPopup.add(new BuildColorRule());
        searchPopup.add(new BuildColorRule());
        mainPopup.add(new JSeparator());
        searchPopup.add(new JSeparator());
        mainPopup.add(new CopyField());
        mainPopup.add(new CopySelection());
        searchPopup.add(new CopyField());
        searchPopup.add(new CopySelection());
        mainPopup.add(new JSeparator());
        searchPopup.add(new JSeparator());

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

        mainPopup.add(new JSeparator());

        mainPopup.add(menuItemToggleDock);

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

        mainPopup.add(new JSeparator());

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

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

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

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

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

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

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

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


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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

        return action;
    }

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

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

        return action;
    }

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

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

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

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

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

    public String getRefineFocusText() {
        final JTextField filterText = (JTextField) filterCombo.getEditor().getEditorComponent();
        return filterText.getText();
    }

    /**
     * Mutator
     */
    public void toggleScrollToBottom() {
        preferenceModel.setScrollToBottom(!preferenceModel.isScrollToBottom());
    }

    private void scrollToBottom() {
        //run this in an invokeLater block to ensure this action is enqueued to the end of the EDT
        EventQueue.invokeLater(() -> {
            int scrollRow = tableModel.getRowCount() - 1;
            table.scrollToRow(scrollRow);
        });
    }

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

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

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

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

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

            final int startingSearchRow = searchTable.getRowCount();

            boolean rowAdded = false;
            boolean searchRowAdded = false;

            int addedRowCount = 0;
            int searchAddedRowCount = 0;

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

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

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

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

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

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

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

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

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

        File xmlFile = null;
        try {
            xmlFile = new File(SettingsManager.getInstance().getSettingsDirectory(), URLEncoder.encode(identifier, "UTF-8") + ".xml");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        if (xmlFile.exists()) {
            XStream stream = buildXStreamForLogPanelPreference();
            ObjectInputStream in = null;
            try {
                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();
    }

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

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

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

        filterModel.processNewLoggingEvent(event);
    }

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

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

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

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

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

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

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

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

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

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

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

            this.delayThread =
                new Thread(
                    () -> {
                        while (true) {
                            try {
                                Thread.sleep(CHECK_PERIOD);
                            } catch (InterruptedException e) {
                            }

                            if (
                                (System.currentTimeMillis() - lastTimeStamp) < CHECK_PERIOD) {
                                // They typed something since the last check. we ignor
                                // this for a sample period
                                //                logger.debug("Typed something since the last check");
                            } else if (
                                (System.currentTimeMillis() - lastTimeStamp) < (2 * CHECK_PERIOD)) {
                                // they stopped typing recently, but have stopped for at least
                                // 1 sample period. lets apply the filter
                                //                logger.debug("Typed something recently applying filter");
                                if (!(textFeld.getText().trim().equals(lastText.trim()))) {
                                    lastText = textFeld.getText();
                                    EventQueue.invokeLater(DelayedTextDocumentListener.this::setFilter);
                                }
                            } else {
                                // they stopped typing a while ago, let's forget about it
                                //                logger.debug(
                                //                  "They stoppped typing a while ago, assuming filter has been applied");
                            }
                        }
                    });

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

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

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

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

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

        /**
         * Update refinement rule based on the entered expression.
         */
        private void setFilter() {
            if (textField.getText().trim().equals("")) {
                //reset background color in case we were previously an invalid expression
                textField.setBackground(UIManager.getColor("TextField.background"));
                tableRuleMediator.setFilterRule(null);
                searchRuleMediator.setFilterRule(null);
                textField.setToolTipText(defaultToolTip);
                if (findRule != null) {
                    currentSearchMatchCount = tableModel.getSearchMatchCount();
                    statusBar.setSearchMatchCount(currentSearchMatchCount, getIdentifier());
                }
            } else {
                try {
                    tableRuleMediator.setFilterRule(ExpressionRule.getRule(textField.getText()));
                    searchRuleMediator.setFilterRule(ExpressionRule.getRule(textField.getText()));
                    textField.setToolTipText(defaultToolTip);
                    if (findRule != null) {
                        currentSearchMatchCount = tableModel.getSearchMatchCount();
                        statusBar.setSearchMatchCount(currentSearchMatchCount, getIdentifier());
                    }
                    //valid expression, reset background color in case we were previously an invalid expression
                    textField.setBackground(UIManager.getColor("TextField.background"));
                } catch (IllegalArgumentException iae) {
                    //invalid expression, change background of the field
                    textField.setToolTipText(iae.getMessage());
                    textField.setBackground(ChainsawConstants.INVALID_EXPRESSION_BACKGROUND);
                    if (findRule != null) {
                        currentSearchMatchCount = tableModel.getSearchMatchCount();
                        statusBar.setSearchMatchCount(currentSearchMatchCount, getIdentifier());
                    }
                }
            }
        }
    }

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

        private TableMarkerListener(JTable markerTable, EventContainer markerEventContainer, EventContainer otherMarkerEventContainer) {
            this.markerTable = markerTable;
            this.markerEventContainer = markerEventContainer;
            this.otherMarkerEventContainer = otherMarkerEventContainer;
        }

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

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

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

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

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

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

                currentRow = row;

                LoggingEventWrapper event = detailEventContainer.getRow(currentRow);

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

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

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

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

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

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

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

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

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

        private DetailPaneUpdater() {
        }

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

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

        private void updateDetailPane() {
            updateDetailPane(false);
        }

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

            LoggingEventWrapper loggingEventWrapper = null;
            if (force || (selectedRow != -1 && (lastRow != selectedRow))) {
                loggingEventWrapper = tableModel.getRow(selectedRow);

                if (loggingEventWrapper != null) {
                    final StringBuilder buf = new StringBuilder();
                    buf.append(detailLayout.getHeader())
                        .append(detailLayout.format(loggingEventWrapper.getLoggingEvent())).append(
                        detailLayout.getFooter());
                    if (buf.length() > 0) {
                        try {
                            final Document doc = detail.getEditorKit().createDefaultDocument();
                            detail.getEditorKit().read(new StringReader(buf.toString()), doc, 0);

                            SwingHelper.invokeOnEDT(() -> {
                                detail.setDocument(doc);
                                JTextComponentFormatter.applySystemFontAndSize(detail);
                                detail.setCaretPosition(0);
                                lastRow = selectedRow;
                            });
                        } catch (Exception e) {
                        }
                    }
                }
            }

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

        /**
         * Update detail pane layout if it's changed
         *
         * @param arg0
         */
        public void propertyChange(PropertyChangeEvent arg0) {
            SwingUtilities.invokeLater(
                () -> updateDetailPane(true));
        }
    }

    private class ThrowableDisplayMouseAdapter extends MouseAdapter {
        private JTable throwableTable;
        private EventContainer throwableEventContainer;
        final JDialog detailDialog;
        final JEditorPane detailArea;

        public ThrowableDisplayMouseAdapter(JTable throwableTable, EventContainer throwableEventContainer) {
            this.throwableTable = throwableTable;
            this.throwableEventContainer = throwableEventContainer;

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

            detailDialog.pack();
        }

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

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

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

                detailArea.setText(buf.toString());
                SwingHelper.invokeOnEDT(() -> centerAndSetVisible(detailDialog));
            }
        }
    }

    private class MarkerCellEditor implements TableCellEditor {
        JTable currentTable;
        JTextField textField = new JTextField();
        Set<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().getLevel().toInt() < Level.WARN.toInt() && wrapper.loggingEventWrapper.getLoggingEvent().getProperty(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE) == null) {
                        float ratio = (wrapper.rowNum / (float) rowCount);
                        //                System.out.println("error - ratio: " + ratio + ", component height: " + componentHeight);
                        int verticalLocation = (int) (componentHeight * ratio);

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

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

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

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

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

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

            for (Object aSecondaryList : secondaryList) {
                ThumbnailLoggingEventWrapper wrapper = (ThumbnailLoggingEventWrapper) aSecondaryList;
                float ratio = (wrapper.rowNum / (float) rowCount);
//                System.out.println("warning - ratio: " + ratio + ", component height: " + componentHeight);
                int verticalLocation = (int) (componentHeight * ratio);

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

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

    abstract class AbstractEventMatchThumbnail extends JPanel {
        protected List<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().getLevel();
        }

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

            ThumbnailLoggingEventWrapper that = (ThumbnailLoggingEventWrapper) o;

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

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

    class AutoFilterComboBox extends JComboBox {
        private boolean bypassFiltering;
        private List allEntries = new ArrayList();
        private List displayedEntries = new ArrayList();
        private AutoFilterComboBoxModel model = new AutoFilterComboBoxModel();
        //editor component
        private final JTextField textField = new JTextField();
        private String lastTextToMatch;

        public AutoFilterComboBox() {
            textField.setPreferredSize(getPreferredSize());
            setModel(model);
            setEditor(new AutoFilterEditor());
            ((JTextField) getEditor().getEditorComponent()).getDocument().addDocumentListener(new AutoFilterDocumentListener());
            setEditable(true);
            addPopupMenuListener(new PopupMenuListenerImpl());
        }

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

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

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

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

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

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

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

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

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

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

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

        class AutoFilterComboBoxModel extends AbstractListModel implements MutableComboBoxModel {
            private Object selectedItem;

            public void addElement(Object obj) {
                //assuming add is to displayed list...add to full list (only if not a dup)
                bypassFiltering = true;

                boolean entryExists = !allEntries.contains(obj);
                if (entryExists) {
                    allEntries.add(obj);
                }
                displayedEntries.add(obj);
                if (!entryExists) {
                    fireIntervalAdded(this, displayedEntries.size() - 1, displayedEntries.size());
                }
                bypassFiltering = false;
            }

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

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

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

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

            public Object getSelectedItem() {
                return selectedItem;
            }

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

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

            public void removeAllElements() {
                bypassFiltering = true;
                int displayedEntrySize = displayedEntries.size();
                if (displayedEntrySize > 0) {
                    displayedEntries.clear();
                    //if firecontentschaned is used, the combobox resizes..use fireintervalremoved instead, which doesn't do that..
                    fireIntervalRemoved(this, 0, displayedEntrySize - 1);
                }
                bypassFiltering = false;
            }

            public void showAllElements() {
                //first remove whatever is there and fire necessary events then add events
                removeAllElements();
                bypassFiltering = true;
                displayedEntries.addAll(allEntries);
                if (displayedEntries.size() > 0) {
                    fireIntervalAdded(this, 0, displayedEntries.size() - 1);
                }
                bypassFiltering = false;
            }
        }

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

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

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

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

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

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