You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by sd...@apache.org on 2023/12/18 08:00:01 UTC

(logging-chainsaw) branch master updated: Reorganized property logic to go through the PreferenceModel in order to consolidate configuration key definitions. Per-tab settings are now persisted (detail/log tree panel display and positions), and reduced the set of visible columns.

This is an automated email from the ASF dual-hosted git repository.

sdeboy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-chainsaw.git


The following commit(s) were added to refs/heads/master by this push:
     new 20821b8  Reorganized property logic to go through the PreferenceModel in order to consolidate configuration key definitions. Per-tab settings are now persisted (detail/log tree panel display and positions), and reduced the set of visible columns.
20821b8 is described below

commit 20821b818af9394100f81b0684a4f2733afcce3b
Author: sdeboy <sd...@apache.org>
AuthorDate: Sun Dec 17 23:59:53 2023 -0800

    Reorganized property logic to go through the PreferenceModel in order to consolidate configuration key definitions. Per-tab settings are now persisted (detail/log tree panel display and positions), and reduced the set of visible columns.
---
 .../log4j/chainsaw/ApplicationPreferenceModel.java | 390 ++++---------
 .../chainsaw/ApplicationPreferenceModelPanel.java  |  79 ++-
 .../org/apache/log4j/chainsaw/ChainsawStarter.java |   2 +-
 .../apache/log4j/chainsaw/ChainsawStatusBar.java   |   6 +-
 .../log4j/chainsaw/ChainsawToolBarAndMenus.java    |  34 +-
 .../org/apache/log4j/chainsaw/EventContainer.java  |   4 +-
 .../apache/log4j/chainsaw/LoggerNameTreePanel.java |   9 +-
 .../log4j/chainsaw/TableColorizingRenderer.java    |  12 +-
 .../apache/log4j/chainsaw/color/ColorPanel.java    |   4 +-
 .../apache/log4j/chainsaw/color/RuleColorizer.java | 103 +---
 .../chainsaw/components/logpanel/LogPanel.java     | 642 +++++++--------------
 .../logpanel/LogPanelPreferenceModel.java          | 424 ++++++--------
 .../logpanel/LogPanelPreferencePanel.java          |  94 ++-
 .../org/apache/log4j/chainsaw/logui/LogUI.java     |  28 +-
 .../log4j/chainsaw/logui/LogUIPanelBuilder.java    |  16 +-
 .../log4j/chainsaw/logui/LogUiReceiversPanel.java  |  13 +-
 .../log4j/chainsaw/prefs/SettingsManager.java      |   2 +-
 .../apache/log4j/chainsaw/prefs/default.properties |  45 +-
 .../log4j/chainsaw/prefs/logpanel.properties       |  35 +-
 19 files changed, 672 insertions(+), 1270 deletions(-)

diff --git a/src/main/java/org/apache/log4j/chainsaw/ApplicationPreferenceModel.java b/src/main/java/org/apache/log4j/chainsaw/ApplicationPreferenceModel.java
index 8a4eed0..803d3d0 100644
--- a/src/main/java/org/apache/log4j/chainsaw/ApplicationPreferenceModel.java
+++ b/src/main/java/org/apache/log4j/chainsaw/ApplicationPreferenceModel.java
@@ -16,13 +16,15 @@
  */
 package org.apache.log4j.chainsaw;
 
+import org.apache.commons.configuration2.AbstractConfiguration;
+import org.apache.commons.configuration2.event.ConfigurationEvent;
+import org.apache.commons.configuration2.event.EventListener;
+import org.apache.log4j.varia.LogFilePatternReceiver;
+
 import javax.swing.*;
 import java.awt.*;
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
-import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
-import java.util.Vector;
 
 /**
  * Encapsulates the Chainsaw Application wide properties
@@ -31,159 +33,95 @@ import java.util.Vector;
  */
 public class ApplicationPreferenceModel {
 
-    private boolean showNoReceiverWarning = true;
-    private boolean statusBar = true;
-    private boolean toolbar = true;
-    private boolean receivers = false; //setting this to true will cause the receivers panel to be displayed by default
-    private boolean confirmExit = true;
-    private boolean showSplash = true;
-    private String lookAndFeelClassName = "";
-    private int toolTipDisplayMillis = 4000;
-    private int cyclicBufferSize = 50000;
-    private String lastUsedVersion = "";
-    private int responsiveness = 3;
-    private Color searchBackgroundColor = ChainsawConstants.FIND_LOGGER_BACKGROUND;
-    private Color searchForegroundColor = ChainsawConstants.FIND_LOGGER_FOREGROUND;
-    private Color alternatingColorForegroundColor = ChainsawConstants.COLOR_ODD_ROW_FOREGROUND;
-    private Color alternatingColorBackgroundColor = ChainsawConstants.COLOR_ODD_ROW_BACKGROUND;
-
-    private String identifierExpression = "PROP.hostname - PROP.application";
-
-    private transient final PropertyChangeSupport propertySupport =
-        new PropertyChangeSupport(this);
-
-    private int tabPlacement = 3;
-
-    /**
-     * If not 'empty', this property will be used as the URL to load log4j configuration at startup
-     */
-    private Vector<String> configurationURLs = new Vector<>();
-
-    private String configurationURL = "";
-
-    /**
-     * Remember current config if provided via means other than configurationURL (command line arg, etc)
-     */
-    private transient String bypassConfigurationURL = null;
-    /**
-     * this means for Receivers that require optional jars that can't be delivered
-     * by the Web start classloader, we need to be able to remove the SecurityManager in place
-     */
-    private boolean okToRemoveSecurityManager = false;
-    private static final int CONFIGURATION_URL_ENTRY_COUNT = 10;
-    private List defaultColumnNames = new ArrayList();
-    private boolean defaultColumnsSet;
-    private boolean bypassSearchColors = false;
-
-    /**
-     * @param listener
-     */
-    public void addPropertyChangeListener(PropertyChangeListener listener) {
-        propertySupport.addPropertyChangeListener(listener);
-    }
-
-    /**
-     * @param propertyName
-     * @param listener
-     */
-    public void addPropertyChangeListener(String propertyName,
-                                          PropertyChangeListener listener) {
-        propertySupport.addPropertyChangeListener(propertyName, listener);
-    }
-
-    /**
-     * @param propertyName
-     * @param oldValue
-     * @param newValue
-     */
-    private void firePropertyChange(String propertyName, boolean oldValue,
-                                    boolean newValue) {
-        propertySupport.firePropertyChange(propertyName, oldValue, newValue);
-    }
-
-    /**
-     * @param propertyName
-     * @param oldValue
-     * @param newValue
-     */
-    private void firePropertyChange(String propertyName, int oldValue,
-                                    int newValue) {
-        propertySupport.firePropertyChange(propertyName, oldValue, newValue);
-    }
-
-    /**
-     * @param propertyName
-     * @param oldValue
-     * @param newValue
-     */
-    private void firePropertyChange(String propertyName, Object oldValue,
-                                    Object newValue) {
-        propertySupport.firePropertyChange(propertyName, oldValue, newValue);
-    }
-
-    /**
-     * @param propertyName
-     * @return listeners flag
-     */
-    public boolean hasListeners(String propertyName) {
-        return propertySupport.hasListeners(propertyName);
-    }
-
-    /**
-     * @param listener
-     */
-    public void removePropertyChangeListener(PropertyChangeListener listener) {
-        propertySupport.removePropertyChangeListener(listener);
+    public static final String SHOW_NO_RECEIVER_WARNING = "showNoReceiverWarning";
+    public static final String IDENTIFIER_EXPRESSION = "identifierExpression";
+    public static final String CYCLIC_BUFFER_SIZE = "cyclicBufferSize";
+    public static final String TOOL_TIP_DISPLAY_MILLIS = "toolTipDisplayMillis";
+    public static final String RESPONSIVENESS = "responsiveness";
+    public static final String TAB_PLACEMENT = "tabPlacement";
+    public static final String STATUS_BAR_VISIBLE = "statusBarVisible";
+    public static final String ALTERNATING_FOREGROUND_COLOR = "alternatingForegroundColor";
+    public static final String ALTERNATING_BACKGROUND_COLOR = "alternatingBackgroundColor";
+    public static final String SEARCH_FOREGROUND_COLOR = "searchForegroundColor";
+    public static final String SEARCH_BACKGROUND_COLOR = "searchBackgroundColor";
+    public static final String RECEIVERS_VISIBLE = "receiversVisible";
+    public static final String TOOLBAR_VISIBLE = "toolbarVisible";
+    public static final String LOOK_AND_FEEL_CLASS_NAME = "lookAndFeelClassName";
+    public static final String CONFIRM_EXIT = "confirmExit";
+    public static final String SHOW_SPLASH = "showSplash";
+    public static final String CONFIGURATION_URL = "configurationURL";
+    public static final String BYPASS_CONFIGURATION_URL = "bypassConfigurationURL";
+    public static final String DEFAULT_COLUMN_NAMES = "defaultColumnNames";
+    public static final String BYPASS_SEARCH_COLORS = "bypassSearchColors";
+    private final AbstractConfiguration globalConfiguration;
+    private final int toolTipDisplayMillisDefault = 4000;
+    private final int cyclicBufferSizeDefault = 50000;
+    private final int responsivenessDefault = 3;
+    private final Color searchBackgroundColorDefault = ChainsawConstants.FIND_LOGGER_BACKGROUND;
+    private final Color searchForegroundColorDefault = ChainsawConstants.FIND_LOGGER_FOREGROUND;
+    private final Color alternatingForegroundColorDefault = ChainsawConstants.COLOR_ODD_ROW_FOREGROUND;
+    private final Color alternatingBackgroundColorDefault = ChainsawConstants.COLOR_ODD_ROW_BACKGROUND;
+
+    private final String identifierExpressionDefault = "PROP.hostname - PROP.application";
+
+    private final int tabPlacementDefault = 3;
+
+    private final boolean bypassSearchColorsDefault = false;
+    private final boolean statusBarVisibleDefault = true;
+    private final boolean receiversDefault = false;
+    private final boolean showNoReceiverWarningDefault = true;
+    private final boolean isToolbarDefault = true;
+    private final boolean confirmExitDefault = true;
+    private final boolean showSplashDefault = true;
+    private List<String> defaultColumns = List.of("LOGGER","MARKER","TIMESTAMP","LEVEL","MESSAGE");
+
+
+    public ApplicationPreferenceModel(AbstractConfiguration globalConfiguration) {
+        this.globalConfiguration = globalConfiguration;
+    }
+
+    public void addEventListener(EventListener<ConfigurationEvent> listener) {
+        globalConfiguration.addEventListener(ConfigurationEvent.SET_PROPERTY, listener);
     }
 
     /**
      * @return Returns the showNoReceiverWarning.
      */
     public final boolean isShowNoReceiverWarning() {
-
-        return showNoReceiverWarning;
+        return globalConfiguration.getBoolean(SHOW_NO_RECEIVER_WARNING, showNoReceiverWarningDefault);
     }
 
     public final String getIdentifierExpression() {
-        return identifierExpression;
+        return globalConfiguration.getString(IDENTIFIER_EXPRESSION, identifierExpressionDefault);
     }
 
     public final void setCyclicBufferSize(int newCyclicBufferSize) {
-        int oldCyclicBufferSize = cyclicBufferSize;
-        cyclicBufferSize = newCyclicBufferSize;
-        firePropertyChange("cyclicBufferSize", oldCyclicBufferSize, newCyclicBufferSize);
+        globalConfiguration.setProperty(CYCLIC_BUFFER_SIZE, newCyclicBufferSize);
     }
 
     public final int getCyclicBufferSize() {
-        return cyclicBufferSize;
+        return globalConfiguration.getInt(CYCLIC_BUFFER_SIZE, cyclicBufferSizeDefault);
     }
 
     public final void setToolTipDisplayMillis(int newToolTipDisplayMillis) {
-        int oldToolTipDisplayMillis = toolTipDisplayMillis;
-        toolTipDisplayMillis = newToolTipDisplayMillis;
-        firePropertyChange("toolTipDisplayMillis", oldToolTipDisplayMillis, newToolTipDisplayMillis);
+        globalConfiguration.setProperty(TOOL_TIP_DISPLAY_MILLIS, newToolTipDisplayMillis);
     }
 
     public final int getToolTipDisplayMillis() {
-        return toolTipDisplayMillis;
+        return globalConfiguration.getInt(TOOL_TIP_DISPLAY_MILLIS, toolTipDisplayMillisDefault);
     }
 
     public final void setIdentifierExpression(String newIdentifierExpression) {
-        String oldIdentifierExpression = identifierExpression;
-        this.identifierExpression = newIdentifierExpression;
-        firePropertyChange("identifierExpression", oldIdentifierExpression, newIdentifierExpression);
+        globalConfiguration.setProperty(IDENTIFIER_EXPRESSION, newIdentifierExpression);
     }
 
     /**
      * @param newShowNoReceiverWarning The showNoReceiverWarning to set.
      */
     public final void setShowNoReceiverWarning(boolean newShowNoReceiverWarning) {
-        boolean oldShowNoReceiverWarning = showNoReceiverWarning;
-        this.showNoReceiverWarning = newShowNoReceiverWarning;
-        firePropertyChange("showNoReceiverWarning", oldShowNoReceiverWarning, newShowNoReceiverWarning);
+        globalConfiguration.setProperty(SHOW_NO_RECEIVER_WARNING, newShowNoReceiverWarning);
     }
 
-
     /**
      * Takes another model and copies all the values into this model
      *
@@ -194,9 +132,9 @@ public class ApplicationPreferenceModel {
         setShowNoReceiverWarning(model.isShowNoReceiverWarning() || (model.getConfigurationURL() == null || model.getConfigurationURL().trim().isEmpty()));
         setResponsiveness(model.getResponsiveness());
         setTabPlacement(model.getTabPlacement());
-        setStatusBar(model.isStatusBar());
-        setToolbar(model.isToolbar());
-        setReceivers(model.isReceivers());
+        setStatusBarVisible(model.isStatusBarVisible());
+        setToolbarVisible(model.isToolbarVisible());
+        setReceiversVisible(model.isReceiversVisible());
         if (model.getLookAndFeelClassName() != null && !model.getLookAndFeelClassName().trim().isEmpty()) {
             setLookAndFeelClassName(model.getLookAndFeelClassName());
         } else {
@@ -207,16 +145,10 @@ public class ApplicationPreferenceModel {
         setShowSplash(model.isShowSplash());
         setToolTipDisplayMillis(model.getToolTipDisplayMillis());
         setCyclicBufferSize(model.getCyclicBufferSize());
-        Vector<String> configurationURLs = model.getConfigurationURLs();
-        if (configurationURLs != null) {
-            setConfigurationURLs(configurationURLs);
-        }
         //only set current config URL if bypass is null
         if (model.getBypassConfigurationURL() == null) {
             setConfigurationURL(model.getConfigurationURL());
         }
-        setLastUsedVersion(model.getLastUsedVersion());
-        setOkToRemoveSecurityManager(model.isOkToRemoveSecurityManager());
         Color searchForeground = model.getSearchForegroundColor();
         Color searchBackground = model.getSearchBackgroundColor();
         if (searchForeground != null && searchBackground != null) {
@@ -224,13 +156,13 @@ public class ApplicationPreferenceModel {
             setSearchForegroundColor(searchForeground);
         }
 
-        Color alternatingForeground = model.getAlternatingColorForegroundColor();
-        Color alternatingBackground = model.getAlternatingColorBackgroundColor();
+        Color alternatingForeground = model.getAlternatingForegroundColor();
+        Color alternatingBackground = model.getAlternatingBackgroundColor();
         if (alternatingForeground != null && alternatingBackground != null) {
             setAlternatingBackgroundColor(alternatingBackground);
             setAlternatingForegroundColor(alternatingForeground);
         }
-        if (model.isDefaultColumnsSet()) {
+        if (!model.getDefaultColumnNames().isEmpty()) {
             setDefaultColumnNames(model.getDefaultColumnNames());
         }
         setBypassSearchColors(model.isBypassSearchColors());
@@ -255,277 +187,185 @@ public class ApplicationPreferenceModel {
      * @return Returns the responsiveness.
      */
     public final int getResponsiveness() {
-        return responsiveness;
+        return globalConfiguration.getInt(RESPONSIVENESS, responsivenessDefault);
     }
 
     /**
      * @param newValue The responsiveness to set.
      */
     public final void setResponsiveness(int newValue) {
-        int oldvalue = responsiveness;
-
-        if (newValue >= 1000) {
-            responsiveness = (newValue - 750) / 1000;
-        } else {
-            responsiveness = newValue;
-        }
-        firePropertyChange("responsiveness", oldvalue, responsiveness);
+        globalConfiguration.setProperty(RESPONSIVENESS, newValue);
     }
 
     /**
      * @param i
      */
     public void setTabPlacement(int i) {
-        int oldValue = this.tabPlacement;
-        this.tabPlacement = i;
-        firePropertyChange("tabPlacement", oldValue, this.tabPlacement);
+        globalConfiguration.setProperty(TAB_PLACEMENT, i);
     }
 
     /**
      * @return Returns the tabPlacement.
      */
     public final int getTabPlacement() {
-        return tabPlacement;
+        return globalConfiguration.getInt(TAB_PLACEMENT, tabPlacementDefault);
     }
 
     /**
      * @return Returns the statusBar.
      */
-    public final boolean isStatusBar() {
-        return statusBar;
-    }
-
-    public Vector<String> getConfigurationURLs() {
-        return configurationURLs;
-    }
-
-    public void setConfigurationURLs(Vector<String> urls) {
-        if (urls != null) {
-            configurationURLs = urls;
-        }
+    public final boolean isStatusBarVisible() {
+        return globalConfiguration.getBoolean(STATUS_BAR_VISIBLE, statusBarVisibleDefault);
     }
 
     /**
-     * @param statusBar The statusBar to set.
+     * @param statusBarVisible The statusBarVisible to set.
      */
-    public final void setStatusBar(boolean statusBar) {
-        boolean oldValue = this.statusBar;
-        this.statusBar = statusBar;
-        firePropertyChange("statusBar", oldValue, this.statusBar);
+    public final void setStatusBarVisible(boolean statusBarVisible) {
+        globalConfiguration.setProperty(STATUS_BAR_VISIBLE, statusBarVisible);
     }
 
     public void setAlternatingForegroundColor(Color alternatingColorForegroundColor) {
-        this.alternatingColorForegroundColor = alternatingColorForegroundColor;
-        firePropertyChange("alternatingColor", true, false);
+        globalConfiguration.setProperty(ALTERNATING_FOREGROUND_COLOR, alternatingColorForegroundColor);
     }
 
     public void setAlternatingBackgroundColor(Color alternatingColorBackgroundColor) {
-        this.alternatingColorBackgroundColor = alternatingColorBackgroundColor;
-        firePropertyChange("alternatingColor", true, false);
+        globalConfiguration.setProperty(ALTERNATING_BACKGROUND_COLOR, alternatingColorBackgroundColor);
     }
 
     public void setSearchForegroundColor(Color searchForegroundColor) {
-        this.searchForegroundColor = searchForegroundColor;
-        firePropertyChange("searchColor", true, false);
+        globalConfiguration.setProperty(SEARCH_FOREGROUND_COLOR, searchForegroundColor);
     }
 
     public void setSearchBackgroundColor(Color searchBackgroundColor) {
-        this.searchBackgroundColor = searchBackgroundColor;
-        firePropertyChange("searchColor", true, false);
+        globalConfiguration.setProperty(SEARCH_BACKGROUND_COLOR, searchBackgroundColor);
     }
 
-    public Color getAlternatingColorBackgroundColor() {
-        return alternatingColorBackgroundColor;
+    public Color getAlternatingBackgroundColor() {
+        return globalConfiguration.get(Color.class, ALTERNATING_BACKGROUND_COLOR, alternatingBackgroundColorDefault);
     }
 
-    public Color getAlternatingColorForegroundColor() {
-        return alternatingColorForegroundColor;
+    public Color getAlternatingForegroundColor() {
+        return globalConfiguration.get(Color.class, ALTERNATING_FOREGROUND_COLOR, alternatingForegroundColorDefault);
     }
 
+
     public Color getSearchBackgroundColor() {
-        return searchBackgroundColor;
+        return globalConfiguration.get(Color.class, SEARCH_BACKGROUND_COLOR, searchBackgroundColorDefault);
     }
 
     public Color getSearchForegroundColor() {
-        return searchForegroundColor;
+        return globalConfiguration.get(Color.class, SEARCH_FOREGROUND_COLOR, searchForegroundColorDefault);
     }
 
     /**
      * @return Returns the receivers.
      */
-    public final boolean isReceivers() {
-        return receivers;
+    public final boolean isReceiversVisible() {
+        return globalConfiguration.getBoolean(RECEIVERS_VISIBLE, receiversDefault);
     }
 
     /**
-     * @param receivers The receivers to set.
+     * @param receiversVisible The receiversVisible to set.
      */
-    public final void setReceivers(boolean receivers) {
-        boolean oldValue = this.receivers;
-        this.receivers = receivers;
-        firePropertyChange("receivers", oldValue, this.receivers);
+    public final void setReceiversVisible(boolean receiversVisible) {
+        globalConfiguration.setProperty(RECEIVERS_VISIBLE, receiversVisible);
     }
 
     /**
      * @return Returns the toolbar.
      */
-    public final boolean isToolbar() {
-        return toolbar;
+    public final boolean isToolbarVisible() {
+        return globalConfiguration.getBoolean(TOOLBAR_VISIBLE, isToolbarDefault);
     }
 
     /**
-     * @param toolbar The toolbar to set.
+     * @param toolbarVisible The toolbarVisible to set.
      */
-    public final void setToolbar(boolean toolbar) {
-        boolean oldValue = this.toolbar;
-        this.toolbar = toolbar;
-        firePropertyChange("toolbar", oldValue, this.toolbar);
+    public final void setToolbarVisible(boolean toolbarVisible) {
+        globalConfiguration.setProperty(TOOLBAR_VISIBLE, toolbarVisible);
     }
 
     /**
      * @return Returns the lookAndFeelClassName.
      */
     public final String getLookAndFeelClassName() {
-        return lookAndFeelClassName;
+        return globalConfiguration.getString(LOOK_AND_FEEL_CLASS_NAME, "");
     }
 
     /**
      * @param lookAndFeelClassName The lookAndFeelClassName to set.
      */
     public final void setLookAndFeelClassName(String lookAndFeelClassName) {
-        String oldValue = this.lookAndFeelClassName;
-        this.lookAndFeelClassName = lookAndFeelClassName;
-        firePropertyChange("lookAndFeelClassName", oldValue, this.lookAndFeelClassName);
+        globalConfiguration.setProperty(LOOK_AND_FEEL_CLASS_NAME, lookAndFeelClassName);
     }
 
     /**
      * @return Returns the confirmExit.
      */
     public final boolean isConfirmExit() {
-        return confirmExit;
+        return globalConfiguration.getBoolean(CONFIRM_EXIT, confirmExitDefault);
     }
 
     /**
      * @param confirmExit The confirmExit to set.
      */
     public final void setConfirmExit(boolean confirmExit) {
-        boolean oldValue = this.confirmExit;
-        this.confirmExit = confirmExit;
-        firePropertyChange("confirmExit", oldValue, this.confirmExit);
+        globalConfiguration.setProperty(CONFIRM_EXIT, confirmExit);
     }
 
     /**
      * @return Returns the showSplash.
      */
     public final boolean isShowSplash() {
-        return showSplash;
+        return globalConfiguration.getBoolean(SHOW_SPLASH, showSplashDefault);
     }
 
     /**
      * @param showSplash The showSplash to set.
      */
     public final void setShowSplash(boolean showSplash) {
-        boolean oldValue = this.showSplash;
-        this.showSplash = showSplash;
-        firePropertyChange("showSplash", oldValue, this.showSplash);
+        globalConfiguration.setProperty(SHOW_SPLASH, showSplash);
     }
 
     /**
      * @return Returns the configurationURL.
      */
     public final String getConfigurationURL() {
-        return this.configurationURL;
+        return globalConfiguration.getString(CONFIGURATION_URL, "");
     }
 
     public final String getBypassConfigurationURL() {
-        return bypassConfigurationURL;
+        return globalConfiguration.getString(BYPASS_CONFIGURATION_URL, "");
     }
 
     /*
       Set to null to un-bypass
      */
     public void setBypassConfigurationURL(String bypassConfigurationURL) {
-        //don't change configuration URL..configurationURL is persisted on app exit
-        if (bypassConfigurationURL != null && bypassConfigurationURL.trim().isEmpty()) {
-            this.bypassConfigurationURL = null;
-        }
-        this.bypassConfigurationURL = bypassConfigurationURL;
+        globalConfiguration.setProperty(BYPASS_CONFIGURATION_URL, bypassConfigurationURL);
     }
 
     /**
      * @param configurationURL The configurationURL to set.
      */
     public final void setConfigurationURL(String configurationURL) {
-        //don't add empty entries, but allow the current configuration URL to be set to an empty string
-        Object oldValue = this.bypassConfigurationURL != null ? this.bypassConfigurationURL : this.configurationURL;
-        bypassConfigurationURL = null;
-        if (configurationURL == null || configurationURL.trim().isEmpty()) {
-            this.configurationURL = "";
-            firePropertyChange("configurationURL", oldValue, this.configurationURL);
-            return;
-        }
-        //add entry to MRU list
-        if (!configurationURLs.contains(configurationURL)) {
-            if (configurationURLs.size() == CONFIGURATION_URL_ENTRY_COUNT) {
-                configurationURLs.remove(CONFIGURATION_URL_ENTRY_COUNT - 1);
-            }
-            configurationURLs.add(0, configurationURL);
-        }
-        this.configurationURL = configurationURL;
-        firePropertyChange("configurationURL", oldValue, this.configurationURL);
-    }
-
-    /**
-     * @return Returns the lastUsedVersion.
-     */
-    public final String getLastUsedVersion() {
-        return this.lastUsedVersion;
-    }
-
-    /**
-     * @param lastUsedVersion The lastUsedVersion to set.
-     */
-    public final void setLastUsedVersion(String lastUsedVersion) {
-        String oldValue = this.lastUsedVersion;
-        this.lastUsedVersion = lastUsedVersion;
-        firePropertyChange("lastUsedVersion", oldValue, this.lastUsedVersion);
-    }
-
-    /**
-     * @return ok to remove security manager flag
-     */
-    public final boolean isOkToRemoveSecurityManager() {
-        return this.okToRemoveSecurityManager;
-    }
-
-    /**
-     * @param okToRemoveSecurityManager The okToRemoveSecurityManager to set.
-     */
-    public final void setOkToRemoveSecurityManager(boolean okToRemoveSecurityManager) {
-        boolean oldValue = this.okToRemoveSecurityManager;
-        this.okToRemoveSecurityManager = okToRemoveSecurityManager;
-        firePropertyChange("okToRemoveSecurityManager", oldValue, this.okToRemoveSecurityManager);
-    }
-
-    public void setDefaultColumnNames(List defaultColumnNames) {
-        defaultColumnsSet = true;
-        this.defaultColumnNames.clear();
-        this.defaultColumnNames.addAll(defaultColumnNames);
+        globalConfiguration.setProperty(CONFIGURATION_URL, configurationURL);
     }
 
-    public boolean isDefaultColumnsSet() {
-        return defaultColumnsSet;
+    public void setDefaultColumnNames(List<String> defaultColumnNames) {
+        globalConfiguration.setProperty(DEFAULT_COLUMN_NAMES, defaultColumnNames);
     }
 
-    public List getDefaultColumnNames() {
-        return defaultColumnNames;
+    public List<String> getDefaultColumnNames() {
+        return globalConfiguration.getList(String.class, DEFAULT_COLUMN_NAMES, defaultColumns);
     }
 
     public void setBypassSearchColors(boolean bypassSearchColors) {
-        this.bypassSearchColors = bypassSearchColors;
+        globalConfiguration.setProperty(BYPASS_SEARCH_COLORS, bypassSearchColors);
     }
 
     public boolean isBypassSearchColors() {
-        return bypassSearchColors;
+        return globalConfiguration.getBoolean(BYPASS_SEARCH_COLORS, bypassSearchColorsDefault);
     }
 }
diff --git a/src/main/java/org/apache/log4j/chainsaw/ApplicationPreferenceModelPanel.java b/src/main/java/org/apache/log4j/chainsaw/ApplicationPreferenceModelPanel.java
index bdd1772..5d96c77 100644
--- a/src/main/java/org/apache/log4j/chainsaw/ApplicationPreferenceModelPanel.java
+++ b/src/main/java/org/apache/log4j/chainsaw/ApplicationPreferenceModelPanel.java
@@ -30,8 +30,6 @@ import java.util.Dictionary;
 import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.Locale;
-import org.apache.commons.configuration2.AbstractConfiguration;
-import org.apache.commons.configuration2.event.ConfigurationEvent;
 import org.apache.log4j.chainsaw.prefs.SettingsManager;
 
 
@@ -42,16 +40,13 @@ import org.apache.log4j.chainsaw.prefs.SettingsManager;
  */
 public class ApplicationPreferenceModelPanel extends AbstractPreferencePanel {
     private static final Logger logger = LogManager.getLogger(ApplicationPreferenceModelPanel.class);
-    
+    private final ApplicationPreferenceModel applicationPreferenceModel;
+
     private JTextField toolTipDisplayMillis;
     private JTextField cyclicBufferSize;
     private GeneralAllPrefPanel generalAllPrefPanel;
-    private AbstractConfiguration m_globalConfiguration;
-    private SettingsManager settingsManager;
-
-    public ApplicationPreferenceModelPanel(SettingsManager settingsManager) {
-        this.m_globalConfiguration = settingsManager.getGlobalConfiguration();
-        this.settingsManager = settingsManager;
+    public ApplicationPreferenceModelPanel(SettingsManager settingsManager, ApplicationPreferenceModel applicationPreferenceModel) {
+        this.applicationPreferenceModel = applicationPreferenceModel;
         initComponents();
         getOkButton().addActionListener(
             e -> {
@@ -122,21 +117,19 @@ public class ApplicationPreferenceModelPanel extends AbstractPreferencePanel {
          *
          */
         private void setupListeners() {
-            final AbstractConfiguration config = settingsManager.getGlobalConfiguration();
-
             topPlacement.addActionListener(
-                e -> config.setProperty("tabPlacement", SwingConstants.TOP));
+                e -> applicationPreferenceModel.setTabPlacement(SwingConstants.TOP));
             bottomPlacement.addActionListener(
-                e -> config.setProperty("tabPlacement", SwingConstants.BOTTOM));
+                e -> applicationPreferenceModel.setTabPlacement(SwingConstants.BOTTOM));
 
             statusBar.addActionListener(
-                e -> config.setProperty("statusBar",statusBar.isSelected()));
+                e -> applicationPreferenceModel.setStatusBarVisible(statusBar.isSelected()));
 
             toolBar.addActionListener(
-                e -> config.setProperty("toolbar",toolBar.isSelected()));
+                e -> applicationPreferenceModel.setToolbarVisible(toolBar.isSelected()));
 
             receivers.addActionListener(
-                e -> config.setProperty("showReceivers",receivers.isSelected()));
+                e -> applicationPreferenceModel.setReceiversVisible(receivers.isSelected()));
 
 //            uncommittedPreferenceModel.addPropertyChangeListener(
 //                "tabPlacement",
@@ -215,14 +208,12 @@ public class ApplicationPreferenceModelPanel extends AbstractPreferencePanel {
             JPanel lfPanel = new JPanel();
             lfPanel.setLayout(new BoxLayout(lfPanel, BoxLayout.Y_AXIS));
             lfPanel.setBorder(BorderFactory.createTitledBorder(" Look & Feel "));
-            final AbstractConfiguration configuration = settingsManager.getGlobalConfiguration();
 
             for (final UIManager.LookAndFeelInfo lfInfo : lookAndFeels) {
                 final JRadioButton lfItem = new JRadioButton(" " + lfInfo.getName() + " ");
                 lfItem.setName(lfInfo.getClassName());
                 lfItem.addActionListener(
-                    e -> configuration.setProperty("lookAndFeelClassName",
-                        lfInfo.getClassName()));
+                    e -> applicationPreferenceModel.setLookAndFeelClassName(lfInfo.getClassName()));
                 lookAndFeelGroup.add(lfItem);
                 lfPanel.add(lfItem);
             }
@@ -232,8 +223,7 @@ public class ApplicationPreferenceModelPanel extends AbstractPreferencePanel {
                     Class.forName("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
                 final JRadioButton lfIGTK = new JRadioButton(" GTK+ 2.0 ");
                 lfIGTK.addActionListener(
-                    e -> configuration.setProperty("lookAndFeelClassName",
-                        gtkLF.getName()));
+                    e -> applicationPreferenceModel.setLookAndFeelClassName(gtkLF.getName()));
                 lookAndFeelGroup.add(lfIGTK);
                 lfPanel.add(lfIGTK);
             } catch (Exception e) {
@@ -266,16 +256,14 @@ public class ApplicationPreferenceModelPanel extends AbstractPreferencePanel {
         }
 
         public void updateModel(){
-            AbstractConfiguration config = settingsManager.getGlobalConfiguration();
-
-            statusBar.setSelected(config.getBoolean("statusBar", false));
-            receivers.setSelected(config.getBoolean("showReceivers", false));
-            toolBar.setSelected(config.getBoolean("toolbar", false));
-            configureTabPlacement(config.getInt("tabPlacement", SwingConstants.TOP));
+            statusBar.setSelected(applicationPreferenceModel.isStatusBarVisible());
+            receivers.setSelected(applicationPreferenceModel.isReceiversVisible());
+            toolBar.setSelected(applicationPreferenceModel.isToolbarVisible());
+            configureTabPlacement(applicationPreferenceModel.getTabPlacement());
             Enumeration e = lookAndFeelGroup.getElements();
             while (e.hasMoreElements()) {
                 JRadioButton radioButton = (JRadioButton) e.nextElement();
-                if (radioButton.getText().equals(config.getString("lookAndFeelClassName"))) {
+                if (radioButton.getText().equals(applicationPreferenceModel.getLookAndFeelClassName())) {
                     radioButton.setSelected(true);
                     break;
                 }
@@ -359,17 +347,17 @@ public class ApplicationPreferenceModelPanel extends AbstractPreferencePanel {
         }
 
         private void setupListeners() {
-            m_globalConfiguration.addEventListener(ConfigurationEvent.SET_PROPERTY,
+            applicationPreferenceModel.addEventListener(
                 evt -> {
-                    if( evt.getPropertyName().equals( "showSplash" ) ){
+                    if( evt.getPropertyName().equals(ApplicationPreferenceModel.SHOW_SPLASH) ){
                         boolean value = (Boolean) evt.getPropertyValue();
                         showSplash.setSelected(value);
                     }
                 });
 
-            m_globalConfiguration.addEventListener(ConfigurationEvent.SET_PROPERTY,
+            applicationPreferenceModel.addEventListener(
                 evt -> {
-                    if( evt.getPropertyName().equals( "responsiveness" ) ){
+                    if( evt.getPropertyName().equals(ApplicationPreferenceModel.RESPONSIVENESS) ){
                         int value = (Integer) evt.getPropertyValue();
                         if (value >= 1000) {
                             int newValue = (value - 750) / 1000;
@@ -381,29 +369,29 @@ public class ApplicationPreferenceModelPanel extends AbstractPreferencePanel {
                     }
                 });
 
-            m_globalConfiguration.addEventListener(ConfigurationEvent.SET_PROPERTY,
+            applicationPreferenceModel.addEventListener(
                 evt -> {
-                    if( evt.getPropertyName().equals( "toolTipDisplayMillis" ) ){
+                    if( evt.getPropertyName().equals(ApplicationPreferenceModel.TOOL_TIP_DISPLAY_MILLIS) ){
                         toolTipDisplayMillis.setText(evt.getPropertyValue().toString());
                     }
                 });
 
-            m_globalConfiguration.addEventListener(ConfigurationEvent.SET_PROPERTY,
+            applicationPreferenceModel.addEventListener(
                 evt -> {
-                    if( evt.getPropertyName().equals( "cyclicBufferSize" ) ){
+                    if( evt.getPropertyName().equals(ApplicationPreferenceModel.CYCLIC_BUFFER_SIZE) ){
                         cyclicBufferSize.setText(evt.getPropertyValue().toString());
                     }
                 });
 
-            m_globalConfiguration.addEventListener(ConfigurationEvent.SET_PROPERTY,
+            applicationPreferenceModel.addEventListener(
                 evt -> {
-                    if( evt.getPropertyName().equals( "confirmExit" ) ){
+                    if( evt.getPropertyName().equals(ApplicationPreferenceModel.CONFIRM_EXIT) ){
                         boolean value = (Boolean) evt.getPropertyValue();
                         confirmExit.setSelected(value);
                     }
                 });
 
-            showSplash.addActionListener(e -> m_globalConfiguration.setProperty("showSplash", showSplash.isSelected()));
+            showSplash.addActionListener(e -> applicationPreferenceModel.setShowSplash(showSplash.isSelected()));
             responsiveSlider.getModel().addChangeListener(
                 e -> {
                     if (responsiveSlider.getValueIsAdjusting()) {
@@ -418,13 +406,12 @@ public class ApplicationPreferenceModelPanel extends AbstractPreferencePanel {
                         }
 
                         logger.debug("Adjust responsiveness to {}", value);
-                        m_globalConfiguration.setProperty("responsiveness", value);
+                        applicationPreferenceModel.setResponsiveness(value);
                     }
                 });
 
             confirmExit.addActionListener(
-                e -> m_globalConfiguration.setProperty( "confirmExit",
-                    confirmExit.isSelected()));
+                e -> applicationPreferenceModel.setConfirmExit(confirmExit.isSelected()));
         }
 
         private void setupInitialValues() {
@@ -434,10 +421,10 @@ public class ApplicationPreferenceModelPanel extends AbstractPreferencePanel {
             sliderLabelMap.put(4, new JLabel(" Slow "));
 
 
-            confirmExit.setSelected(m_globalConfiguration.getBoolean("confirmExit", Boolean.TRUE));
-            showSplash.setSelected(m_globalConfiguration.getBoolean("showSplash", Boolean.TRUE));
-            toolTipDisplayMillis.setText(m_globalConfiguration.getInt( "toolTipDisplayMillis", 1000 ) + "");
-            cyclicBufferSize.setText(m_globalConfiguration.getInt( "cyclicBufferSize", 20000 ) + "");
+            confirmExit.setSelected(applicationPreferenceModel.isConfirmExit());
+            showSplash.setSelected(applicationPreferenceModel.isShowSplash());
+            toolTipDisplayMillis.setText(String.valueOf(applicationPreferenceModel.getToolTipDisplayMillis()));
+            cyclicBufferSize.setText(String.valueOf(applicationPreferenceModel.getCyclicBufferSize()));
         }
     }
 }
diff --git a/src/main/java/org/apache/log4j/chainsaw/ChainsawStarter.java b/src/main/java/org/apache/log4j/chainsaw/ChainsawStarter.java
index a8c8c5b..61a6d7f 100644
--- a/src/main/java/org/apache/log4j/chainsaw/ChainsawStarter.java
+++ b/src/main/java/org/apache/log4j/chainsaw/ChainsawStarter.java
@@ -93,7 +93,7 @@ public class ChainsawStarter {
         final LoggerContext ctx = (LoggerContext) org.apache.logging.log4j.LogManager.getContext(false);
         logUI.chainsawAppender = ctx.getConfiguration().getAppender("chainsaw");
 
-        if (configuration.getBoolean("slowSplash", true)) {
+        if (configuration.getBoolean("showSplash", true)) {
             splashViewer.showSplash(logUI);
         }
 
diff --git a/src/main/java/org/apache/log4j/chainsaw/ChainsawStatusBar.java b/src/main/java/org/apache/log4j/chainsaw/ChainsawStatusBar.java
index a35c33f..d872600 100644
--- a/src/main/java/org/apache/log4j/chainsaw/ChainsawStatusBar.java
+++ b/src/main/java/org/apache/log4j/chainsaw/ChainsawStatusBar.java
@@ -53,13 +53,13 @@ public class ChainsawStatusBar extends JPanel {
         BorderFactory.createLineBorder(statusMsg.getBackground().darker());
     private final LogUI logUI;
 
-    public ChainsawStatusBar(LogUI logUI, AbstractConfiguration configuration) {
+    public ChainsawStatusBar(LogUI logUI, ApplicationPreferenceModel applicationPreferenceModel) {
         setLayout(new GridBagLayout());
         this.logUI = logUI;
 
-        configuration.addEventListener(ConfigurationEvent.SET_PROPERTY,
+        applicationPreferenceModel.addEventListener(
             evt -> {
-                if (evt.getPropertyName().equals("statusBar")) {
+                if (evt.getPropertyName().equals(ApplicationPreferenceModel.STATUS_BAR_VISIBLE)) {
                     boolean value = (Boolean) evt.getPropertyValue();
                     setVisible(value);
                 }
diff --git a/src/main/java/org/apache/log4j/chainsaw/ChainsawToolBarAndMenus.java b/src/main/java/org/apache/log4j/chainsaw/ChainsawToolBarAndMenus.java
index 877f285..9792426 100644
--- a/src/main/java/org/apache/log4j/chainsaw/ChainsawToolBarAndMenus.java
+++ b/src/main/java/org/apache/log4j/chainsaw/ChainsawToolBarAndMenus.java
@@ -76,7 +76,6 @@ public class ChainsawToolBarAndMenus implements ChangeListener {
     private final JCheckBoxMenuItem menuShowWelcome = new JCheckBoxMenuItem();
     private final JToolBar toolbar;
     private final LogUI logui;
-    private final AbstractConfiguration configuration;
     private final SmallButton clearButton = new SmallButton();
     private final SmallToggleButton detailPaneButton = new SmallToggleButton();
     private final SmallToggleButton logTreePaneButton = new SmallToggleButton();
@@ -85,10 +84,11 @@ public class ChainsawToolBarAndMenus implements ChangeListener {
     private final SmallToggleButton toggleCyclicButton = new SmallToggleButton();
     private final Action[] logPanelSpecificActions;
     private final JMenu activeTabMenu = new JMenu("Current tab");
+    private final ApplicationPreferenceModel applicationPreferenceModel;
 
-    public ChainsawToolBarAndMenus(final LogUI logui, AbstractConfiguration configuration) {
+    public ChainsawToolBarAndMenus(final LogUI logui, ApplicationPreferenceModel applicationPreferenceModel) {
         this.logui = logui;
-        this.configuration = configuration;
+        this.applicationPreferenceModel = applicationPreferenceModel;
         toolbar = new JToolBar(SwingConstants.HORIZONTAL);
         menuBar = new JMenuBar();
         fileMenu = new FileMenu(logui);
@@ -117,14 +117,14 @@ public class ChainsawToolBarAndMenus implements ChangeListener {
         createMenuBar();
         createToolbar();
 
-        configuration.addEventListener(ConfigurationEvent.SET_PROPERTY,
+        applicationPreferenceModel.addEventListener(
             evt -> {
-                if (evt.getPropertyName().equals("toolbar")) {
+                if (evt.getPropertyName().equals(ApplicationPreferenceModel.TOOLBAR_VISIBLE)) {
                     boolean value = (Boolean) evt.getPropertyValue();
                     toolbar.setVisible(value);
                 }
             });
-        boolean showToolbar = configuration.getBoolean("toolbar", true);
+        boolean showToolbar = applicationPreferenceModel.isToolbarVisible();
         toolbar.setVisible(showToolbar);
 
         logPanelSpecificActions =
@@ -137,17 +137,17 @@ public class ChainsawToolBarAndMenus implements ChangeListener {
                 toggleLogTreeAction, toggleScrollToBottomAction, changeModelAction,
             };
 
-            configuration.addEventListener(ConfigurationEvent.SET_PROPERTY,
+            applicationPreferenceModel.addEventListener(
             evt -> {
-                if( evt.getPropertyName().equals( "statusBar" ) ){
+                if( evt.getPropertyName().equals(ApplicationPreferenceModel.STATUS_BAR_VISIBLE) ){
                     boolean value = (Boolean) evt.getPropertyValue();
                     toggleStatusBarCheck.setSelected(value);
                 }
             });
 
-            configuration.addEventListener(ConfigurationEvent.SET_PROPERTY,
+        applicationPreferenceModel.addEventListener(
             evt -> {
-                if( evt.getPropertyName().equals( "showReceivers" ) ){
+                if( evt.getPropertyName().equals(ApplicationPreferenceModel.RECEIVERS_VISIBLE) ){
                     boolean value = (Boolean) evt.getPropertyValue();
                     showReceiversButton.setSelected(value);
                     toggleShowReceiversCheck.setSelected(value);
@@ -377,7 +377,7 @@ public class ChainsawToolBarAndMenus implements ChangeListener {
         viewMenu.setMnemonic('V');
 
         toggleShowToolbarCheck.setAction(toggleToolbarAction);
-        toggleShowToolbarCheck.setSelected(configuration.getBoolean("toolbar", true));
+        toggleShowToolbarCheck.setSelected(applicationPreferenceModel.isToolbarVisible());
 
         menuShowWelcome.setAction(toggleWelcomeVisibleAction);
 
@@ -415,13 +415,13 @@ public class ChainsawToolBarAndMenus implements ChangeListener {
             new AbstractAction("Show Status bar") {
                 public void actionPerformed(ActionEvent arg0) {
                     boolean isSelected = toggleStatusBarCheck.isSelected();
-                    configuration.setProperty("statusBar", isSelected);
+                    applicationPreferenceModel.setStatusBarVisible(isSelected);
                 }
             };
 
         toggleStatusBarAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_B);
         toggleStatusBarCheck.setAction(toggleStatusBarAction);
-        toggleStatusBarCheck.setSelected(configuration.getBoolean("statusBar", true));
+        toggleStatusBarCheck.setSelected(applicationPreferenceModel.isStatusBarVisible());
 
         activeTabMenu.add(pause);
         activeTabMenu.add(toggleCyclicMenuItem);
@@ -585,8 +585,8 @@ public class ChainsawToolBarAndMenus implements ChangeListener {
                 public void actionPerformed(ActionEvent arg0) {
                     // Since this action can be triggered from either a button
                     // or a check box, get the current value and invert it.
-                    boolean currentValue = configuration.getBoolean("showReceivers", false);
-                    configuration.setProperty("showReceivers", !currentValue);
+                    boolean currentValue = applicationPreferenceModel.isReceiversVisible();
+                    applicationPreferenceModel.setReceiversVisible(!currentValue);
                 }
             };
 
@@ -634,7 +634,7 @@ public class ChainsawToolBarAndMenus implements ChangeListener {
             new AbstractAction("Show Toolbar") {
                 public void actionPerformed(ActionEvent e) {
                     boolean isSelected = toggleShowToolbarCheck.isSelected();
-                    configuration.setProperty("toolbar", isSelected);
+                    applicationPreferenceModel.setToolbarVisible(isSelected);
                 }
             };
 
@@ -743,7 +743,7 @@ public class ChainsawToolBarAndMenus implements ChangeListener {
     }
 
     private void scanState() {
-        boolean showReceiversByDefault = configuration.getBoolean("showReceivers", false);
+        boolean showReceiversByDefault = applicationPreferenceModel.isReceiversVisible();
 
         toggleStatusBarCheck.setSelected(logui.isStatusBarVisible());
         toggleShowReceiversCheck.setSelected(
diff --git a/src/main/java/org/apache/log4j/chainsaw/EventContainer.java b/src/main/java/org/apache/log4j/chainsaw/EventContainer.java
index d69fcd1..6987a5c 100644
--- a/src/main/java/org/apache/log4j/chainsaw/EventContainer.java
+++ b/src/main/java/org/apache/log4j/chainsaw/EventContainer.java
@@ -100,12 +100,12 @@ public interface EventContainer extends SortTableModel, LoggerNameModel {
     /**
      * Returns a copied list of all the event in the model.
      */
-    List getAllEvents();
+    List<LoggingEventWrapper> getAllEvents();
 
     /**
      * Returns a copied list containing the events in the model with filter applied
      */
-    List getFilteredEvents();
+    List<LoggingEventWrapper> getFilteredEvents();
 
     /**
      * Returns the total number of events currently in the model (all, not just filtered)
diff --git a/src/main/java/org/apache/log4j/chainsaw/LoggerNameTreePanel.java b/src/main/java/org/apache/log4j/chainsaw/LoggerNameTreePanel.java
index 727f30e..6b45635 100644
--- a/src/main/java/org/apache/log4j/chainsaw/LoggerNameTreePanel.java
+++ b/src/main/java/org/apache/log4j/chainsaw/LoggerNameTreePanel.java
@@ -22,6 +22,7 @@ import org.apache.log4j.chainsaw.components.elements.SmallButton;
 import org.apache.log4j.chainsaw.components.elements.SmallToggleButton;
 import org.apache.log4j.chainsaw.components.logpanel.LogPanel;
 import org.apache.log4j.chainsaw.components.logpanel.LogPanelLoggerTreeModel;
+import org.apache.log4j.chainsaw.components.logpanel.LogPanelPreferenceModel;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.log4j.chainsaw.color.RuleColorizer;
@@ -55,6 +56,7 @@ public final class LoggerNameTreePanel extends JPanel implements LoggerNameListe
     //~ Static fields/initializers ==============================================
 
     private static final int WARN_DEPTH = 4;
+    private final LogPanelPreferenceModel logPanelPreferenceModel;
 
     //~ Instance fields =========================================================
 
@@ -82,7 +84,6 @@ public final class LoggerNameTreePanel extends JPanel implements LoggerNameListe
     private final Set hiddenSet = new HashSet();
     private final Action hideAction;
     private final Action hideSubLoggersAction;
-    private final AbstractConfiguration m_panelConfig;
 
     private final JList ignoreList = new JList();
     private final JEditorPane ignoreExpressionEntryField = new JEditorPane();
@@ -123,14 +124,14 @@ public final class LoggerNameTreePanel extends JPanel implements LoggerNameListe
      * @param logTreeModel
      */
     public LoggerNameTreePanel(LogPanelLoggerTreeModel logTreeModel,
-            AbstractConfiguration panelConfiguration,
+            LogPanelPreferenceModel logPanelPreferenceModel,
             LogPanel logPanel,
             RuleColorizer colorizer,
             FilterModel filterModel) {
         super();
         this.logTreeModel = logTreeModel;
-        m_panelConfig = panelConfiguration;
         this.logPanel = logPanel;
+        this.logPanelPreferenceModel = logPanelPreferenceModel;
         this.colorizer = colorizer;
 
         setLayout(new BorderLayout());
@@ -679,7 +680,7 @@ public final class LoggerNameTreePanel extends JPanel implements LoggerNameListe
     private Action createCloseAction() {
         Action action = new AbstractAction() {
             public void actionPerformed(ActionEvent e) {
-                m_panelConfig.setProperty("logpanel.logTreePanelVisible", false);
+                logPanelPreferenceModel.setLogTreePanelVisible(false);
             }
         };
 
diff --git a/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java b/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java
index c5461aa..8b9c886 100644
--- a/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java
+++ b/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java
@@ -92,7 +92,7 @@ public class TableColorizingRenderer extends DefaultTableCellRenderer {
      */
     public TableColorizingRenderer(SettingsManager settingsManager, RuleColorizer colorizer,
                                    EventContainer eventContainer, LogPanelPreferenceModel logPanelPreferenceModel,
-                                   boolean colorizeSearch) {
+                                   ApplicationPreferenceModel applicationPreferenceModel, boolean colorizeSearch) {
         this.settingsManager = settingsManager;
         this.applicationPreferenceModel = applicationPreferenceModel;
         this.logPanelPreferenceModel = logPanelPreferenceModel;
@@ -533,14 +533,10 @@ public class TableColorizingRenderer extends DefaultTableCellRenderer {
     /**
      * Changes the Logger precision.
      *
-     * @param loggerPrecisionText
+     * @param loggerPrecision
      */
-    public void setLoggerPrecision(String loggerPrecisionText) {
-        try {
-            loggerPrecision = Integer.parseInt(loggerPrecisionText);
-        } catch (NumberFormatException nfe) {
-            loggerPrecision = 0;
-        }
+    public void setLoggerPrecision(int loggerPrecision) {
+        this.loggerPrecision = loggerPrecision;
     }
 
     /**
diff --git a/src/main/java/org/apache/log4j/chainsaw/color/ColorPanel.java b/src/main/java/org/apache/log4j/chainsaw/color/ColorPanel.java
index 127dbed..f3ac3b3 100644
--- a/src/main/java/org/apache/log4j/chainsaw/color/ColorPanel.java
+++ b/src/main/java/org/apache/log4j/chainsaw/color/ColorPanel.java
@@ -229,7 +229,7 @@ public class ColorPanel extends JPanel {
                 Object selectedItem = loadPanelColorizersComboBox.getSelectedItem();
                 if (selectedItem != null) {
                     RuleColorizer sourceColorizer = allLogPanelColorizers.get(selectedItem.toString());
-                    RuleColorizer newColorizer = new RuleColorizer(settingsManager);
+                    RuleColorizer newColorizer = new RuleColorizer();
                     newColorizer.setRules(sourceColorizer.getRules());
                     parent.setRuleColorizer(newColorizer);
                     updateColors();
@@ -543,7 +543,7 @@ public class ColorPanel extends JPanel {
                         if( globalRulesCheckbox.isSelected() ){
                             parentLogPanel.setRuleColorizer(globalColorizer);
                         }else{
-                            parentLogPanel.setRuleColorizer(new RuleColorizer(settingsManager));
+                            parentLogPanel.setRuleColorizer(new RuleColorizer());
                         }
                         componentChanged();
                         parentLogPanel.getCurrentRuleColorizer().addPropertyChangeListener(
diff --git a/src/main/java/org/apache/log4j/chainsaw/color/RuleColorizer.java b/src/main/java/org/apache/log4j/chainsaw/color/RuleColorizer.java
index e61c482..fdf7867 100644
--- a/src/main/java/org/apache/log4j/chainsaw/color/RuleColorizer.java
+++ b/src/main/java/org/apache/log4j/chainsaw/color/RuleColorizer.java
@@ -51,8 +51,6 @@ public class RuleColorizer implements Colorizer {
 
     private Rule findRule;
     private Rule loggerRule;
-    private AbstractConfiguration configuration;
-    private final boolean isGlobal;
 
     private static final Color WARN_DEFAULT_COLOR = new Color(255, 255, 153);
     private static final Color FATAL_OR_ERROR_DEFAULT_COLOR = new Color(255, 153, 153);
@@ -61,7 +59,6 @@ public class RuleColorizer implements Colorizer {
     private static final String DEFAULT_WARN_EXPRESSION = "level == WARN";
     private static final String DEFAULT_FATAL_ERROR_EXCEPTION_EXPRESSION = "level == FATAL || level == ERROR || exception exists";
     private static final String DEFAULT_MARKER_EXPRESSION = "prop.marker exists";
-    private SettingsManager settingsManager;
 
     public static List<ColorRule> defaultRules(){
         List<ColorRule> rulesList = new ArrayList<>();
@@ -86,16 +83,8 @@ public class RuleColorizer implements Colorizer {
         return rulesList;
     }
 
-    public RuleColorizer(SettingsManager settingsManager) {
-        this.settingsManager = settingsManager;
+    public RuleColorizer() {
         this.rules = defaultRules();
-        isGlobal = false;
-    }
-
-    public RuleColorizer(SettingsManager settingsManager, boolean isGlobal){
-        this.settingsManager = settingsManager;
-        this.rules = defaultRules();
-        this.isGlobal = isGlobal;
     }
 
     public void setLoggerRule(Rule loggerRule) {
@@ -120,8 +109,6 @@ public class RuleColorizer implements Colorizer {
         this.rules.clear();
         this.rules.addAll(rules);
         colorChangeSupport.firePropertyChange(PROPERTY_CHANGED_COLORRULE, false, true);
-
-        saveColorSettings();
     }
 
     public List<ColorRule> getRules() {
@@ -132,8 +119,6 @@ public class RuleColorizer implements Colorizer {
         rules.add(rule);
 
         colorChangeSupport.firePropertyChange(PROPERTY_CHANGED_COLORRULE, false, true);
-
-        saveColorSettings();
     }
 
     /**
@@ -170,10 +155,6 @@ public class RuleColorizer implements Colorizer {
         colorChangeSupport.addPropertyChangeListener(listener);
     }
 
-    public void removePropertyChangeListener(PropertyChangeListener listener) {
-        colorChangeSupport.removePropertyChangeListener(listener);
-    }
-
     /**
      * @param propertyName
      * @param listener
@@ -183,18 +164,6 @@ public class RuleColorizer implements Colorizer {
         colorChangeSupport.addPropertyChangeListener(propertyName, listener);
     }
 
-    public void setConfiguration(AbstractConfiguration configuration){
-        this.configuration = configuration;
-    }
-
-    public void setUseDefaultSettings(boolean useDefaultSettings){
-        if( configuration == settingsManager.getGlobalConfiguration() ){
-            return;
-        }
-
-        configuration.setProperty( "color.rules.default", useDefaultSettings );
-    }
-
     public static String colorToRGBString( Color c ){
         return String.format( "#%02x%02x%02x",
                 c.getRed(),
@@ -202,76 +171,6 @@ public class RuleColorizer implements Colorizer {
                 c.getBlue());
     }
 
-    private void saveColorSettings(){
-        if( configuration == null ){
-            return;
-        }
-
-        DataConfiguration data = new DataConfiguration(configuration);
-
-        if( !isGlobal && configuration.getBoolean( "color.rules.default", true ) ){
-            // No need to save, using the default rules
-            return;
-        }
-
-        for( int x = 0; x < 32; x++ ){
-            String baseConfigKey = "color.rules(" + x + ")";
-
-            if( rules.size() <= x ){
-                break;
-            }
-            
-            ColorRule rule = rules.get(x);
-            
-            logger.debug( "Saving rule {}.  Expression: {}", x, rule.getExpression() );
-
-            configuration.setProperty( baseConfigKey + ".expression", rule.getExpression() );
-            String bgColorString = colorToRGBString(rule.getBackgroundColor());
-            String fgColorString = colorToRGBString(rule.getForegroundColor());
-            data.setProperty( baseConfigKey + ".backgroundColor", bgColorString );
-            data.setProperty( baseConfigKey + ".foregroundColor", fgColorString );
-        }
-
-        logger.debug( "all keys for {}:", configuration);
-        java.util.Iterator<String> s = configuration.getKeys();
-        while( s.hasNext() ){
-            logger.debug( "found key: {}", s.next() );
-        }
-    }
-    
-    public void loadColorSettings() {
-        // When we save/load the rule, we really need to load a map of rules
-        // There's no real good way to do this, so we will do this the somewhat
-        // dumb way and just load up to 32 color rules, since that seems like
-        // a good number
-        List<ColorRule> newRules = new ArrayList<>();
-
-        DataConfiguration data = new DataConfiguration(configuration);
-
-        for( int x = 0; x < 32; x++ ){
-            String baseConfigKey = "color.rules(" + x + ")";
-            String expression;
-            Color backgroundColor;
-            Color foregroundColor;
-
-            expression = configuration.getString( baseConfigKey + ".expression" );
-            backgroundColor = data.getColor( baseConfigKey + ".backgroundColor" );
-            foregroundColor = data.getColor( baseConfigKey + ".foregroundColor" );
-
-            if( expression == null ||
-                    backgroundColor == null ||
-                    foregroundColor == null ){
-                continue;
-            }
-
-            Rule simpleRule = ExpressionRule.getRule(expression);
-            ColorRule rule = new ColorRule( expression, simpleRule, backgroundColor, foregroundColor );
-            newRules.add( rule );
-        }
-
-        setRules(newRules);
-    }
-
     public static List<Color> getDefaultColors() {
         List<Color> vec = new ArrayList<>();
 
diff --git a/src/main/java/org/apache/log4j/chainsaw/components/logpanel/LogPanel.java b/src/main/java/org/apache/log4j/chainsaw/components/logpanel/LogPanel.java
index 0ff68c8..c2fb65e 100644
--- a/src/main/java/org/apache/log4j/chainsaw/components/logpanel/LogPanel.java
+++ b/src/main/java/org/apache/log4j/chainsaw/components/logpanel/LogPanel.java
@@ -17,7 +17,6 @@
 
 package org.apache.log4j.chainsaw.components.logpanel;
 
-import org.apache.commons.configuration2.event.EventListener;
 import org.apache.log4j.chainsaw.*;
 import org.apache.log4j.chainsaw.color.ColorPanel;
 import org.apache.log4j.chainsaw.color.RuleColorizer;
@@ -31,7 +30,6 @@ import org.apache.log4j.chainsaw.icons.LineIconFactory;
 import org.apache.log4j.chainsaw.layout.DefaultLayoutFactory;
 import org.apache.log4j.chainsaw.layout.EventDetailLayout;
 import org.apache.log4j.chainsaw.layout.LayoutEditorPane;
-import org.apache.log4j.chainsaw.prefs.LoadSettingsEvent;
 import org.apache.log4j.chainsaw.prefs.Profileable;
 import org.apache.log4j.chainsaw.prefs.SettingsManager;
 import org.apache.log4j.chainsaw.receiver.ChainsawReceiver;
@@ -61,8 +59,6 @@ import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.List;
 
-import org.apache.commons.configuration2.AbstractConfiguration;
-import org.apache.commons.configuration2.event.ConfigurationEvent;
 import org.apache.log4j.chainsaw.logevents.ChainsawLoggingEvent;
 import org.apache.log4j.chainsaw.logevents.Level;
 import org.apache.logging.log4j.LogManager;
@@ -120,9 +116,6 @@ import org.apache.logging.log4j.Logger;
  */
 public class LogPanel extends DockablePanel implements ChainsawEventBatchListener {
     private static final DateFormat TIMESTAMP_DATE_FORMAT = new SimpleDateFormat(Constants.TIMESTAMP_RULE_FORMAT);
-    private static final double DEFAULT_DETAIL_SPLIT_LOCATION = 0.71d;
-    private static final double DEFAULT_LOG_TREE_SPLIT_LOCATION = 0.2d;
-    private SettingsManager settingsManager;
     private final String identifier;
     private final ChainsawStatusBar statusBar;
     private final JFrame logPanelPreferencesFrame = new JFrame();
@@ -141,26 +134,21 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
     private final JPanel detailPanel = new JPanel(new BorderLayout());
     private final JSplitPane nameTreeAndMainPanelSplit;
     private final LoggerNameTreePanel logTreePanel;
-    private final LogPanelPreferenceModel preferenceModel = new LogPanelPreferenceModel();
-    private final LogPanelPreferencePanel logPanelPreferencesPanel;
+    private final LogPanelPreferenceModel logPanelPreferenceModel;
+    private final ApplicationPreferenceModel applicationPreferenceModel;
+    private final LogPanelPreferencePanel logPanelPreferencePanel;
     private final FilterModel filterModel = new FilterModel();
-    private RuleColorizer colorizer;
-    private final RuleColorizer m_globalColorizer;
+    private RuleColorizer currentColorizer;
+    private final RuleColorizer globalColorizer;
     private final RuleMediator tableRuleMediator = new RuleMediator(false);
     private final RuleMediator searchRuleMediator = new RuleMediator(true);
     private final EventDetailLayout detailLayout = new EventDetailLayout();
-    private double lastLogTreePanelSplitLocation = DEFAULT_LOG_TREE_SPLIT_LOCATION;
     private Point currentPoint;
     private JTable currentTable;
-    private boolean paused = false;
     private Rule findRule;
     private String currentFindRuleText;
     private Rule findMarkerRule;
     private final int dividerSize;
-    static final String TABLE_COLUMN_ORDER = "table.columns.order";
-    static final String TABLE_COLUMN_WIDTHS = "table.columns.widths";
-    static final String COLORS_EXTENSION = ".colors";
-    private static final int LOG_PANEL_SERIALIZATION_VERSION_NUMBER = 2; //increment when format changes
     private int previousLastIndex = -1;
     private final Logger logger = LogManager.getLogger();
     private AutoFilterComboBox filterCombo;
@@ -168,7 +156,6 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
     private JScrollPane eventsPane;
     private int currentSearchMatchCount;
     private Rule clearTableExpressionRule;
-    private int lowerPanelDividerLocation;
     private EventContainer searchModel;
     private JSortTable searchTable = null;
     private TableColorizingRenderer searchRenderer;
@@ -182,9 +169,8 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
     private boolean searchResultsDisplayed;
     private ColorizedEventAndSearchMatchThumbnail colorizedEventAndSearchMatchThumbnail;
     private EventTimeDeltaMatchThumbnail eventTimeDeltaMatchThumbnail;
-    private ChainsawReceiver m_receiver;
-    private AbstractConfiguration m_configuration;
-    private Map<String, RuleColorizer> m_allColorizers;
+    private ChainsawReceiver receiver;
+    private Map<String, RuleColorizer> allColorizers;
 
     /**
      * Creates a new LogPanel object.  If a LogPanel with this identifier has
@@ -194,22 +180,23 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
      * @param statusBar       shared status bar, provided by main application
      * @param identifier      used to load and save settings
      */
-    public LogPanel(SettingsManager settingsManager, final ChainsawStatusBar statusBar,
+    public LogPanel(SettingsManager settingsManager,
+                    ApplicationPreferenceModel applicationPreferenceModel,
+                    final ChainsawStatusBar statusBar,
                     final String identifier,
                     Map<String, RuleColorizer> allColorizers,
                     RuleColorizer globalRuleColorizer) {
-        this.settingsManager = settingsManager;
 
         this.identifier = identifier;
+        this.applicationPreferenceModel = applicationPreferenceModel;
+        logPanelPreferenceModel = new LogPanelPreferenceModel(settingsManager.getSettingsForReceiverTab(identifier));
         this.statusBar = statusBar;
-        this.logPanelPreferencesPanel = new LogPanelPreferencePanel(settingsManager, identifier);
-        this.colorizer = globalRuleColorizer;
-        this.m_globalColorizer = globalRuleColorizer;
-        this.m_allColorizers = allColorizers;
+        this.currentColorizer = globalRuleColorizer;
+        this.globalColorizer = globalRuleColorizer;
+        this.allColorizers = allColorizers;
         logger.debug("creating logpanel for {}", identifier);
 
-        m_configuration = settingsManager.getCombinedSettingsForRecevierTab(identifier);
-        AbstractConfiguration tabConfig = settingsManager.getSettingsForReceiverTab(identifier);
+        logPanelPreferencePanel = new LogPanelPreferencePanel(settingsManager, identifier, logPanelPreferenceModel);
 
         setLayout(new BorderLayout());
 
@@ -229,11 +216,11 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
         logPanelPreferencesFrame.setTitle("'" + identifier + "' Log Panel Preferences");
         logPanelPreferencesFrame.setIconImage(
             ((ImageIcon) ChainsawIcons.ICON_PREFERENCES).getImage());
-        logPanelPreferencesFrame.getContentPane().add(new JScrollPane(logPanelPreferencesPanel));
+        logPanelPreferencesFrame.getContentPane().add(new JScrollPane(logPanelPreferencePanel));
 
         logPanelPreferencesFrame.setSize(740, 520);
 
-        logPanelPreferencesPanel.setOkCancelActionListener(
+        logPanelPreferencePanel.setOkCancelActionListener(
             e -> logPanelPreferencesFrame.setVisible(false));
 
         KeyStroke escape = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false);
@@ -277,9 +264,9 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
         undockedFrame.setSize(new Dimension(1024, 768));
         undockedFrame.pack();
 
-        tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY,
+        logPanelPreferenceModel.addEventListener(
             evt -> {
-                if (evt.getPropertyName().equals("scrollToBottom")) {
+                if (evt.getPropertyName().equals(LogPanelPreferenceModel.SCROLL_TO_BOTTOM)) {
                     boolean value = (Boolean) evt.getPropertyValue();
                     if (value) {
                         scrollToBottom();
@@ -319,45 +306,33 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
         final JCheckBoxMenuItem menuItemLoggerTree =
             new JCheckBoxMenuItem("Show Logger Tree");
         menuItemLoggerTree.addActionListener(
-            e -> {
-                m_configuration.setProperty("logpanel.logTreePanelVisible",
-                    menuItemLoggerTree.isSelected());
-            });
+            e -> logPanelPreferenceModel.setLogTreePanelVisible(menuItemLoggerTree.isSelected()));
         menuItemLoggerTree.setIcon(new ImageIcon(ChainsawIcons.WINDOW_ICON));
 
         final JCheckBoxMenuItem menuItemToggleDetails =
             new JCheckBoxMenuItem("Show Detail Pane");
         menuItemToggleDetails.addActionListener(
-            e -> {
-                m_configuration.setProperty("logpanel.detailColumnVisible",
-                    menuItemToggleDetails.isSelected());
-            });
+            e -> logPanelPreferenceModel.setDetailPaneVisible(menuItemToggleDetails.isSelected()));
 
         menuItemToggleDetails.setIcon(new ImageIcon(ChainsawIcons.INFO));
 
         /*
          * add preferencemodel listeners
          */
-        m_configuration.addEventListener(ConfigurationEvent.SET_PROPERTY,
-            new EventListener<ConfigurationEvent>() {
-                @Override
-                public void onEvent(ConfigurationEvent evt) {
-                    if (evt.getPropertyName().equals("logpanel.wrapMessage")) {
+        logPanelPreferenceModel.addEventListener(
+                evt -> {
+                    if (evt.getPropertyName().equals(LogPanelPreferenceModel.WRAP_MSG)) {
                         boolean wrap = (Boolean) evt.getPropertyValue();
                         renderer.setWrapMessage(wrap);
                         table.tableChanged(new TableModelEvent(tableModel));
                         searchRenderer.setWrapMessage(wrap);
                         searchTable.tableChanged(new TableModelEvent(searchModel));
                     }
-                }
-
-            });
+                });
 
-        m_configuration.addEventListener(ConfigurationEvent.SET_PROPERTY,
-            new EventListener<ConfigurationEvent>() {
-                @Override
-                public void onEvent(ConfigurationEvent evt) {
-                    if (evt.getPropertyName().equals("logpanel.searchResultsVisible")) {
+        logPanelPreferenceModel.addEventListener(
+                evt -> {
+                    if (evt.getPropertyName().equals(LogPanelPreferenceModel.SEARCH_RESULTS_VISIBLE)) {
                         boolean displaySearchResultsInDetailsIfAvailable = (Boolean) evt.getPropertyValue();
                         if (displaySearchResultsInDetailsIfAvailable) {
                             showSearchResults();
@@ -365,30 +340,22 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
                             hideSearchResults();
                         }
                     }
-                }
-
-            });
+                });
 
-        m_configuration.addEventListener(ConfigurationEvent.SET_PROPERTY,
-            new EventListener<ConfigurationEvent>() {
-                @Override
-                public void onEvent(ConfigurationEvent evt) {
-                    if (evt.getPropertyName().equals("logpanel.highlightSearchMatchText")) {
+        logPanelPreferenceModel.addEventListener(
+                evt -> {
+                    if (evt.getPropertyName().equals(LogPanelPreferenceModel.HIGHLIGHT_SEARCH_MATCH_TEXT)) {
                         boolean highlightText = (Boolean) evt.getPropertyValue();
                         renderer.setHighlightSearchMatchText(highlightText);
                         table.tableChanged(new TableModelEvent(tableModel));
                         searchRenderer.setHighlightSearchMatchText(highlightText);
                         searchTable.tableChanged(new TableModelEvent(searchModel));
                     }
-                }
-
-            });
+                });
 
-        tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY,
-            new EventListener<ConfigurationEvent>() {
-                @Override
-                public void onEvent(ConfigurationEvent evt) {
-                    if (evt.getPropertyName().equals("logpanel.detailColumnVisible")) {
+        logPanelPreferenceModel.addEventListener(
+                evt -> {
+                    if (evt.getPropertyName().equals(LogPanelPreferenceModel.DETAIL_PANE_VISIBLE)) {
                         boolean detailPaneVisible = (Boolean) evt.getPropertyValue();
                         if (detailPaneVisible) {
                             showDetailPane();
@@ -398,112 +365,71 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
                                 hideDetailPane();
                             }
                         }
-                        firePropertyChange("detailColumnVisible", !detailPaneVisible, detailPaneVisible);
                     }
-                }
-
-            });
+                });
 
-        tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY,
-            new EventListener<ConfigurationEvent>() {
-                @Override
-                public void onEvent(ConfigurationEvent evt) {
-                    if (evt.getPropertyName().equals("logpanel.logTreePanelVisible")) {
+        logPanelPreferenceModel.addEventListener(
+                evt -> {
+                    if (evt.getPropertyName().equals(LogPanelPreferenceModel.LOG_TREE_PANEL_VISIBLE)) {
                         boolean newValue = (Boolean) evt.getPropertyValue();
                         if (newValue) {
                             showLogTreePanel();
                         } else {
                             hideLogTreePanel();
                         }
-                        firePropertyChange("logTreePanelVisible", !newValue, newValue);
                     }
-                }
-
-            });
+                });
 
-        m_configuration.addEventListener(ConfigurationEvent.SET_PROPERTY,
-            new EventListener<ConfigurationEvent>() {
-                @Override
-                public void onEvent(ConfigurationEvent evt) {
-                    if (evt.getPropertyName().equals("logpanel.toolTips")) {
+        logPanelPreferenceModel.addEventListener(
+                evt -> {
+                    if (evt.getPropertyName().equals(LogPanelPreferenceModel.TOOL_TIPS_VISIBLE)) {
                         boolean toolTips = (Boolean) evt.getPropertyValue();
                         renderer.setToolTipsVisible(toolTips);
                         searchRenderer.setToolTipsVisible(toolTips);
                         searchToggleToolTips.setSelected(toolTips);
                         mainToggleToolTips.setSelected(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();
+        logPanelPreferenceModel.addEventListener(
+            evt -> {
+            if (evt.getPropertyName().equals(LogPanelPreferenceModel.DATE_FORMAT_TIME_ZONE)) {
+                LogPanelPreferenceModel model = (LogPanelPreferenceModel) evt.getSource();
 
-                    isoButton.setSelected(model.isUseISO8601Format());
-                    simpleTimeButton.setSelected(!model.isUseISO8601Format() && !model.isCustomDateFormat());
+                isoButton.setSelected(model.isUseISO8601Format());
+                simpleTimeButton.setSelected(!model.isUseISO8601Format() && !model.isCustomDateFormat());
 
-                    if (model.getTimeZone() != null) {
-                        renderer.setTimeZone(model.getTimeZone());
-                        searchRenderer.setTimeZone(model.getTimeZone());
-                    }
+                if (model.getDateFormatTimeZone() != null) {
+                    renderer.setTimeZone(model.getDateFormatTimeZone());
+                    searchRenderer.setTimeZone(model.getDateFormatTimeZone());
+                }
 
-                    if (model.isUseISO8601Format()) {
+                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));
-                    } 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);
+                table.tableChanged(new TableModelEvent(tableModel));
+                searchTable.tableChanged(new TableModelEvent(searchModel));
+            }
+        });
 
-        m_configuration.addEventListener(ConfigurationEvent.SET_PROPERTY,
+        logPanelPreferenceModel.addEventListener(
             evt -> {
-                if (evt.getPropertyName().equals("logpanel.clearTableExpression")) {
+                if (evt.getPropertyName().equals(LogPanelPreferenceModel.CLEAR_TABLE_EXPRESSION)) {
                     LogPanelPreferenceModel model = (LogPanelPreferenceModel) evt.getSource();
                     String expression = model.getClearTableExpression();
                     try {
@@ -516,9 +442,9 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
                 }
             });
 
-        m_configuration.addEventListener(ConfigurationEvent.SET_PROPERTY,
+        logPanelPreferenceModel.addEventListener(
             evt -> {
-                if (evt.getPropertyName().equals("logpanel.loggerPrecision")) {
+                if (evt.getPropertyName().equals(LogPanelPreferenceModel.LOGGER_PRECISION)) {
                     LogPanelPreferenceModel model = (LogPanelPreferenceModel) evt.getSource();
 
                     renderer.setLoggerPrecision(model.getLoggerPrecision());
@@ -529,20 +455,19 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
                 }
             });
 
-        tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY,
+        logPanelPreferenceModel.addEventListener(
             evt -> {
-                if (evt.getPropertyName().equals("logpanel.logTreePanelVisible")) {
+                if (evt.getPropertyName().equals(LogPanelPreferenceModel.LOG_TREE_PANEL_VISIBLE)) {
                     boolean value = (Boolean) evt.getPropertyValue();
                     menuItemLoggerTree.setSelected(value);
                 }
             });
 
-        tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY,
+        logPanelPreferenceModel.addEventListener(
             evt -> {
-                if (evt.getPropertyName().equals("logpanel.detailColumnVisible")) {
+                if (evt.getPropertyName().equals(LogPanelPreferenceModel.DETAIL_PANE_VISIBLE)) {
                     boolean value = (Boolean) evt.getPropertyValue();
                     menuItemToggleDetails.setSelected(value);
-
                 }
             });
 
@@ -572,8 +497,8 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
          *End of preferenceModel listeners
          */
 
-        int cyclicBufferSize = settingsManager.getGlobalConfiguration().getInt("cyclicBufferSize", 50000);
-        tableModel = new ChainsawCyclicBufferTableModel(cyclicBufferSize, colorizer, "main");
+        int cyclicBufferSize = applicationPreferenceModel.getCyclicBufferSize();
+        tableModel = new ChainsawCyclicBufferTableModel(cyclicBufferSize, currentColorizer, "main");
         table = new JSortTable(tableModel);
 
         markerCellEditor = new MarkerCellEditor();
@@ -581,7 +506,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
         table.setColumnSelectionAllowed(false);
         table.setRowSelectionAllowed(true);
 
-        searchModel = new ChainsawCyclicBufferTableModel(cyclicBufferSize, colorizer, "search");
+        searchModel = new ChainsawCyclicBufferTableModel(cyclicBufferSize, currentColorizer, "search");
         searchTable = new JSortTable(searchModel);
 
         searchTable.setName("search");
@@ -630,7 +555,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
                 boolean warning100 = false;
 
                 public void eventCountChanged(int currentCount, int totalCount) {
-                    if (preferenceModel.isCyclic()) {
+                    if (logPanelPreferenceModel.isCyclic()) {
                         double percent =
                             ((double) totalCount) / tableModel.getMaxSize();
                         String msg;
@@ -665,7 +590,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
          *
          */
 
-        logTreePanel = createLoggerNameTreePanel(tabConfig);
+        logTreePanel = createLoggerNameTreePanel();
 
         /**
          * Set the LoggerRule to be the LoggerTreePanel, as this visual component
@@ -675,7 +600,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
         tableRuleMediator.setLoggerRule(logTreePanel.getLoggerVisibilityRule());
         searchRuleMediator.setLoggerRule(logTreePanel.getLoggerVisibilityRule());
 
-        colorizer.setLoggerRule(logTreePanel.getLoggerColorRule());
+        currentColorizer.setLoggerRule(logTreePanel.getLoggerColorRule());
 
         /*
          * Color rule frame and panel
@@ -684,8 +609,8 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
         colorFrame.setIconImage(
             ((ImageIcon) ChainsawIcons.ICON_PREFERENCES).getImage());
 
-        allColorizers.put(identifier, colorizer);
-        colorPanel = new ColorPanel(settingsManager, m_globalColorizer, filterModel, allColorizers, this);
+        allColorizers.put(identifier, currentColorizer);
+        colorPanel = new ColorPanel(settingsManager, globalColorizer, filterModel, allColorizers, this);
 
         colorFrame.getContentPane().add(colorPanel);
 
@@ -701,13 +626,13 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
         colorPanel.setCloseActionListener(
             e -> colorFrame.setVisible(false));
 
-        colorizer.addPropertyChangeListener(
+        currentColorizer.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()));
+                        loggingEventWrapper.updateColorRuleColors(currentColorizer.getBackgroundColor(loggingEventWrapper.getLoggingEvent()), currentColorizer.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
@@ -794,7 +719,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
 
                 boolean disableScrollToBottom = (lastIndexOnLastRow && lastIndexSame && previousLastIndex != evt.getFirstIndex());
                 if (disableScrollToBottom && isScrollToBottom() && table.getRowCount() > 0) {
-                    preferenceModel.setScrollToBottom(false);
+                    logPanelPreferenceModel.setScrollToBottom(false);
                 }
                 previousLastIndex = evt.getLastIndex();
             }
@@ -841,13 +766,13 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
                 }
             });
 
-        renderer = new TableColorizingRenderer(settingsManager, colorizer, tableModel, preferenceModel, true);
-        renderer.setToolTipsVisible(preferenceModel.isToolTips());
+        renderer = new TableColorizingRenderer(settingsManager, currentColorizer, tableModel, logPanelPreferenceModel, applicationPreferenceModel, true);
+        renderer.setToolTipsVisible(logPanelPreferenceModel.isToolTipsVisible());
 
         table.setDefaultRenderer(Object.class, renderer);
 
-        searchRenderer = new TableColorizingRenderer(settingsManager, colorizer, searchModel, preferenceModel, false);
-        searchRenderer.setToolTipsVisible(preferenceModel.isToolTips());
+        searchRenderer = new TableColorizingRenderer(settingsManager, currentColorizer, searchModel, logPanelPreferenceModel, applicationPreferenceModel, false);
+        searchRenderer.setToolTipsVisible(logPanelPreferenceModel.isToolTipsVisible());
 
         searchTable.setDefaultRenderer(Object.class, searchRenderer);
 
@@ -889,11 +814,11 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
                 TableColumn col = new TableColumn(e.getNewModelIndex());
                 col.setHeaderValue(e.getKey());
 
-                if (preferenceModel.addColumn(col)) {
-                    if (preferenceModel.isColumnVisible(col)) {
+                if (logPanelPreferenceModel.addColumn(col)) {
+                    if (logPanelPreferenceModel.isColumnVisible(col)) {
                         table.addColumn(col);
                         searchTable.addColumn(col);
-                        preferenceModel.setColumnVisible(e.getKey().toString(), true);
+                        logPanelPreferenceModel.setColumnVisible(e.getKey().toString(), true);
                     }
                 }
             }));
@@ -1002,21 +927,20 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
         eventsAndStatusPanel.add(eventsPane, BorderLayout.CENTER);
 
         Integer scrollBarWidth = (Integer) UIManager.get("ScrollBar.width");
+        Integer height = (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));
+        rightThumbNailPanel.add(Box.createVerticalStrut(height));
         colorizedEventAndSearchMatchThumbnail = new ColorizedEventAndSearchMatchThumbnail();
         rightThumbNailPanel.add(colorizedEventAndSearchMatchThumbnail);
-        rightThumbNailPanel.add(Box.createVerticalStrut(scrollBarWidth));
+        rightThumbNailPanel.add(Box.createVerticalStrut(height));
         rightPanel.add(rightThumbNailPanel);
         //set thumbnail width to be a bit narrower than scrollbar width
-        if (scrollBarWidth != null) {
-            rightThumbNailPanel.setPreferredSize(new Dimension(scrollBarWidth - 4, -1));
-        }
+        rightThumbNailPanel.setPreferredSize(new Dimension(scrollBarWidth - 4, -1));
         eventsAndStatusPanel.add(rightPanel, BorderLayout.EAST);
 
         JPanel leftPanel = new JPanel();
@@ -1024,16 +948,14 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
 
         JPanel leftThumbNailPanel = new JPanel();
         leftThumbNailPanel.setLayout(new BoxLayout(leftThumbNailPanel, BoxLayout.Y_AXIS));
-        leftThumbNailPanel.add(Box.createVerticalStrut(scrollBarWidth));
+        leftThumbNailPanel.add(Box.createVerticalStrut(height));
         eventTimeDeltaMatchThumbnail = new EventTimeDeltaMatchThumbnail();
         leftThumbNailPanel.add(eventTimeDeltaMatchThumbnail);
-        leftThumbNailPanel.add(Box.createVerticalStrut(scrollBarWidth));
+        leftThumbNailPanel.add(Box.createVerticalStrut(height));
         leftPanel.add(leftThumbNailPanel);
 
         //set thumbnail width to be a bit narrower than scrollbar width
-        if (scrollBarWidth != null) {
-            leftThumbNailPanel.setPreferredSize(new Dimension(scrollBarWidth - 4, -1));
-        }
+        leftThumbNailPanel.setPreferredSize(new Dimension(scrollBarWidth - 4, -1));
         eventsAndStatusPanel.add(leftPanel, BorderLayout.WEST);
 
         final JPanel statusLabelPanel = new JPanel();
@@ -1123,7 +1045,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
         Action closeDetailAction =
             new AbstractAction(null, LineIconFactory.createCloseIcon()) {
                 public void actionPerformed(ActionEvent arg0) {
-                    tabConfig.setProperty("logpanel.detailColumnVisible", false);
+                    hideDetailPane();
                 }
             };
 
@@ -1138,7 +1060,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
         lowerPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, eventsAndStatusPanel, detailPanel);
 
         dividerSize = lowerPanel.getDividerSize();
-        lowerPanel.setDividerLocation(-1);
+        lowerPanel.setDividerLocation(logPanelPreferenceModel.getLowerPanelDividerLocation());
 
         lowerPanel.setResizeWeight(1.0);
         lowerPanel.setBorder(null);
@@ -1332,7 +1254,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
                                 Color c = JColorChooser.showDialog(getRootPane(), "Choose a color", Color.red);
                                 if (c != null) {
                                     String expression = columnNameKeywordMapper.get(colName) + " " + operator + " '" + value + "'";
-                                    colorizer.addRule(new ColorRule(expression,
+                                    currentColorizer.addRule(new ColorRule(expression,
                                         ExpressionRule.getRule(expression), c, ChainsawConstants.COLOR_DEFAULT_FOREGROUND));
                                 }
                             }
@@ -1631,37 +1553,30 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
         searchTable.addMouseListener(searchTablePopupListener);
 
         loadSettings();
+        loadColumnSettings();
     }
 
-    private LoggerNameTreePanel createLoggerNameTreePanel(AbstractConfiguration tabConfig) {
+    public void saveSettings() {
+        if (isDetailVisible()) {
+            logPanelPreferenceModel.setLowerPanelDividerLocation(lowerPanel.getDividerLocation());
+        }
+        logPanelPreferenceModel.setDetailPaneVisible(isDetailVisible());
+        if (isLogTreeVisible()) {
+            logPanelPreferenceModel.setLogTreeDividerLocation(nameTreeAndMainPanelSplit.getDividerLocation());
+        }
+        logPanelPreferenceModel.setLogTreePanelVisible(isLogTreeVisible());
+    }
+
+    private LoggerNameTreePanel createLoggerNameTreePanel() {
         final LoggerNameTreePanel logTreePanel;
         LogPanelLoggerTreeModel logTreeModel = new LogPanelLoggerTreeModel();
-        logTreePanel = new LoggerNameTreePanel(logTreeModel, tabConfig, this, colorizer, filterModel);
+        logTreePanel = new LoggerNameTreePanel(logTreeModel, logPanelPreferenceModel, this, currentColorizer, filterModel);
         logTreePanel.getLoggerVisibilityRule().addPropertyChangeListener(evt -> {
             if (evt.getPropertyName().equals("searchExpression")) {
                 findCombo.setSelectedItem(evt.getNewValue().toString());
                 findNext();
             }
         });
-        logTreePanel.addComponentListener(new ComponentListener() {
-            @Override
-            public void componentResized(ComponentEvent ce) {
-                Dimension dim = ce.getComponent().getSize();
-                tabConfig.setProperty("logpanel.treeDividerLocation", dim.width);
-            }
-
-            @Override
-            public void componentMoved(ComponentEvent ce) {
-            }
-
-            @Override
-            public void componentShown(ComponentEvent ce) {
-            }
-
-            @Override
-            public void componentHidden(ComponentEvent ce) {
-            }
-        });
 
         tableModel.addLoggerNameListener(logTreeModel);
         tableModel.addLoggerNameListener(logTreePanel);
@@ -1884,7 +1799,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
      * @return scrollToBottom
      */
     public boolean isScrollToBottom() {
-        return preferenceModel.isScrollToBottom();
+        return logPanelPreferenceModel.isScrollToBottom();
     }
 
     public void setRefineFocusText(String refineFocusText) {
@@ -1901,7 +1816,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
      * Mutator
      */
     public void toggleScrollToBottom() {
-        preferenceModel.setScrollToBottom(!preferenceModel.isScrollToBottom());
+        logPanelPreferenceModel.setScrollToBottom(!logPanelPreferenceModel.isScrollToBottom());
     }
 
     private void scrollToBottom() {
@@ -1945,75 +1860,20 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
     private void loadSettings() {
         logger.info("Loading settings for panel with identifier {}", identifier);
 
-        AbstractConfiguration config = m_configuration;
-        Iterator<String> iter = config.getKeys();
-        while (iter.hasNext()) {
-            logger.debug("Key: {}", iter.next());
-        }
-
-        lowerPanelDividerLocation = config.getInt("logpanel.lowerPanelDividerLocation");
-        int treeDividerLocation = config.getInt("logpanel.treeDividerLocation");
-        String conversionPattern = config.getString("logpanel.conversionPattern", DefaultLayoutFactory.getDefaultPatternLayout());
-        String[] savedComboSettings = config.getStringArray("logpanel.savedComboSettings");
-        for (String comboSetting : savedComboSettings) {
-            filterCombo.insertItemAt(comboSetting, 0);
-            findCombo.insertItemAt(comboSetting, 0);
-        }
-
-        String[] columnsOrder = config.getStringArray("table.columns.order");
-        Integer[] columnWidths = (Integer[]) config.getArray(Integer.class, "table.columns.widths");
-        List<TableColumn> columns = new ArrayList<>();
-        for (int index = 0; index < columnsOrder.length; index++) {
-            int columnIndex = 0;
-            for (String s : ChainsawColumns.getColumnsNames()) {
-                if (s.equals(columnsOrder[index])) {
-                    logger.debug("Loading column {}.  Index of data: {}", columnsOrder[index], columnIndex);
-                    TableColumn column = new TableColumn(columnIndex);
-                    column.setHeaderValue(columnsOrder[index]);
-                    column.setPreferredWidth(columnWidths[index]);
-                    columns.add(column);
-                    break;
-                }
-                columnIndex++;
-            }
-
-//            preferenceModel.addColumn(column);
-//            preferenceModel.setColumnVisible(columnsOrder[index], true);
-        }
-        TableColumnModel columnModel = table.getColumnModel();
-        //remove previous columns
-        while (columnModel.getColumnCount() > 0) {
-            columnModel.removeColumn(columnModel.getColumn(0));
-        }
-        //add columns in order
-        for (TableColumn col : columns) {
-            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);
-//        }
-
-        boolean isCyclic = config.getBoolean("logpanel.cyclic");
+        //TODO: Add column support
+        boolean isCyclic = logPanelPreferenceModel.isCyclic();
         tableModel.setCyclic(isCyclic);
         searchModel.setCyclic(isCyclic);
-        lowerPanel.setDividerLocation(config.getInt("logpanel.lowerPanelDividerLocation"));
-        nameTreeAndMainPanelSplit.setDividerLocation(config.getInt("logpanel.treeDividerLocation"));
-        detailLayout.setConversionPattern(conversionPattern);
+        lowerPanel.setDividerLocation(logPanelPreferenceModel.getLowerPanelDividerLocation());
+        nameTreeAndMainPanelSplit.setDividerLocation(logPanelPreferenceModel.getLogTreeDividerLocation());
+        detailLayout.setConversionPattern(logPanelPreferenceModel.getConversionPattern());
         undockedFrame.setLocation(0, 0);
         undockedFrame.setSize(new Dimension(1024, 768));
 
-        logTreePanel.ignore(Arrays.asList(config.getStringArray("logpanel.hiddenLoggers")));
-        logTreePanel.setHiddenExpression(config.getString("logpanel.hiddenExpression"));
-        logTreePanel.setAlwaysDisplayExpression(config.getString("logpanel.alwaysDisplayExpression"));
-        String clearTableExpression = config.getString("logpanel.clearTableExpression", null);
+        logTreePanel.ignore(logPanelPreferenceModel.getHiddenLoggers());
+        logTreePanel.setHiddenExpression(logPanelPreferenceModel.getHiddenExpression());
+        logTreePanel.setAlwaysDisplayExpression(logPanelPreferenceModel.getAlwaysDisplayExpression());
+        String clearTableExpression = logPanelPreferenceModel.getClearTableExpression();
         if (clearTableExpression != null && clearTableExpression.length() > 1) {
             try {
                 clearTableExpressionRule = ExpressionRule.getRule(clearTableExpression);
@@ -2022,16 +1882,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
             }
         }
 
-        AbstractConfiguration configuration = settingsManager.getSettingsForReceiverTab(identifier);
-
-        if (configuration.getBoolean("color.rules.default", true)) {
-            colorizer = m_globalColorizer;
-        } else {
-            setRuleColorizer(new RuleColorizer(settingsManager));
-            colorizer.setConfiguration(configuration);
-            colorizer.loadColorSettings();
-        }
-
+        setRuleColorizer(new RuleColorizer());
 
 //        if (xmlFile.exists()) {
 //            XStream stream = buildXStreamForLogPanelPreference();
@@ -2145,30 +1996,17 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
 //        colorizer.loadColorSettings(identifier);
     }
 
-    public void setRuleColorizer(RuleColorizer newRuleColor) {
-        if (newRuleColor == colorizer) {
+    public void setRuleColorizer(RuleColorizer newRuleColorizer) {
+        if (newRuleColorizer == currentColorizer) {
             return;
         }
 
-        if (colorizer == m_globalColorizer) {
-            // Current colorizer is the global one, so set our new colorizer
-            colorizer = newRuleColor;
-            AbstractConfiguration configuration = settingsManager.getSettingsForReceiverTab(identifier);
-
-            colorizer.setConfiguration(configuration);
-            colorizer.setUseDefaultSettings(false);
-            colorizer.loadColorSettings();
-            m_allColorizers.put(identifier, colorizer);
-            m_configuration.setProperty("color.rules.default", false);
-        } else {
-            m_allColorizers.remove(identifier);
-            colorizer = newRuleColor;
-            m_configuration.setProperty("color.rules.default", true);
-        }
+        currentColorizer = newRuleColorizer;
+        allColorizers.put(identifier, currentColorizer);
     }
 
     public RuleColorizer getCurrentRuleColorizer() {
-        return colorizer;
+        return currentColorizer;
     }
 
     /**
@@ -2199,10 +2037,8 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
      * Toggle panel preference for detail visibility on or off
      */
     public void toggleDetailVisible() {
-        AbstractConfiguration config = settingsManager.getSettingsForReceiverTab(identifier);
-
-        boolean visible = config.getBoolean("logpanel.detailColumnVisible");
-        config.setProperty("logpanel.detailColumnVisible", !visible);
+        boolean visible = logPanelPreferenceModel.isDetailPaneVisible();
+        logPanelPreferenceModel.setDetailPaneVisible(!visible);
     }
 
     /**
@@ -2211,24 +2047,19 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
      * @return detail visibility flag
      */
     public boolean isDetailVisible() {
-        AbstractConfiguration config = settingsManager.getSettingsForReceiverTab(identifier);
-
-        boolean visible = config.getBoolean("logpanel.detailColumnVisible");
-        return visible;
+        return logPanelPreferenceModel.isDetailPaneVisible();
     }
 
     boolean isSearchResultsVisible() {
-        return preferenceModel.isSearchResultsVisible();
+        return logPanelPreferenceModel.isSearchResultsVisible();
     }
 
     /**
      * Toggle panel preference for logger tree visibility on or off
      */
     public void toggleLogTreeVisible() {
-        AbstractConfiguration config = settingsManager.getSettingsForReceiverTab(identifier);
-
-        boolean visible = config.getBoolean("logpanel.logTreePanelVisible");
-        config.setProperty("logpanel.logTreePanelVisible", !visible);
+        boolean visible = logPanelPreferenceModel.isLogTreePanelVisible();
+        logPanelPreferenceModel.setLogTreePanelVisible(!visible);
     }
 
     /**
@@ -2237,9 +2068,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
      * @return logger tree visibility flag
      */
     public boolean isLogTreeVisible() {
-        AbstractConfiguration config = settingsManager.getSettingsForReceiverTab(identifier);
-
-        return config.getBoolean("logpanel.logTreePanelVisible");
+        return logPanelPreferenceModel.isLogTreePanelVisible();
     }
 
     /**
@@ -2247,7 +2076,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
      *
      * @return list of LoggingEvents
      */
-    List getEvents() {
+    List<LoggingEventWrapper> getEvents() {
         return tableModel.getAllEvents();
     }
 
@@ -2256,7 +2085,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
      *
      * @return list of LoggingEvents
      */
-    public List getFilteredEvents() {
+    public List<LoggingEventWrapper> getFilteredEvents() {
         return tableModel.getFilteredEvents();
     }
 
@@ -2317,7 +2146,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
      * @return paused flag
      */
     public boolean isPaused() {
-        return paused;
+        return logPanelPreferenceModel.isPaused();
     }
 
     /**
@@ -2326,9 +2155,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
      * @param paused
      */
     public void setPaused(boolean paused) {
-        boolean oldValue = this.paused;
-        this.paused = paused;
-        firePropertyChange("paused", oldValue, paused);
+        logPanelPreferenceModel.setPaused(paused);
     }
 
     /**
@@ -2340,30 +2167,21 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
     public int setSelectedEvent(int eventNumber) {
         int row = tableModel.locate(ExpressionRule.getRule("prop.log4jid == " + eventNumber), 0, true);
         if (row > -1) {
-            preferenceModel.setScrollToBottom(false);
+            logPanelPreferenceModel.setScrollToBottom(false);
 
             table.scrollToRow(row);
         }
         return row;
     }
 
-    /**
-     * Add a preference propertyChangeListener
-     *
-     * @param listener
-     */
-    public void addPreferencePropertyChangeListener(PropertyChangeListener listener) {
-        preferenceModel.addPropertyChangeListener(listener);
-    }
-
     /**
      * Toggle the LoggingEvent container from either managing a cyclic buffer of
      * events or an ArrayList of events
      */
     public void toggleCyclic() {
-        boolean toggledCyclic = !preferenceModel.isCyclic();
+        boolean toggledCyclic = !logPanelPreferenceModel.isCyclic();
 
-        preferenceModel.setCyclic(toggledCyclic);
+        logPanelPreferenceModel.setCyclic(toggledCyclic);
         tableModel.setCyclic(toggledCyclic);
         searchModel.setCyclic(toggledCyclic);
     }
@@ -2374,14 +2192,14 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
      * @return flag answering if LoggingEvent container is a cyclic buffer
      */
     public boolean isCyclic() {
-        return preferenceModel.isCyclic();
+        return logPanelPreferenceModel.isCyclic();
     }
 
     public void updateFindRule(String ruleText) {
         if ((ruleText == null) || (ruleText.trim().isEmpty())) {
             findRule = null;
             tableModel.updateEventsWithFindRule(null);
-            colorizer.setFindRule(null);
+            currentColorizer.setFindRule(null);
             tableRuleMediator.setFindRule(null);
             searchRuleMediator.setFindRule(null);
             //reset background color in case we were previously an invalid expression
@@ -2397,7 +2215,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
             }
         } else {
             //only turn off scrolltobottom when finding something (find not empty)
-            preferenceModel.setScrollToBottom(false);
+            logPanelPreferenceModel.setScrollToBottom(false);
             if (ruleText.equals(currentFindRuleText)) {
                 //don't update events if rule hasn't changed (we're finding next/previous)
                 return;
@@ -2410,7 +2228,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
                 findRule = ExpressionRule.getRule(ruleText);
                 currentSearchMatchCount = tableModel.updateEventsWithFindRule(findRule);
                 searchModel.updateEventsWithFindRule(findRule);
-                colorizer.setFindRule(findRule);
+                currentColorizer.setFindRule(findRule);
                 tableRuleMediator.setFindRule(findRule);
                 searchRuleMediator.setFindRule(findRule);
                 //valid expression, reset background color in case we were previously an invalid expression
@@ -2424,7 +2242,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
                 final JTextField findText = (JTextField) findCombo.getEditor().getEditorComponent();
                 findText.setToolTipText(re.getMessage());
                 findText.setBackground(ChainsawConstants.INVALID_EXPRESSION_BACKGROUND);
-                colorizer.setFindRule(null);
+                currentColorizer.setFindRule(null);
                 tableRuleMediator.setFindRule(null);
                 searchRuleMediator.setFindRule(null);
                 tableModel.updateEventsWithFindRule(null);
@@ -2494,15 +2312,11 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
      */
     private void showDetailPane() {
         lowerPanel.setDividerSize(dividerSize);
-        if (lowerPanelDividerLocation == 0) {
-            lowerPanel.setDividerLocation(DEFAULT_DETAIL_SPLIT_LOCATION);
-            lowerPanelDividerLocation = lowerPanel.getDividerLocation();
-        } else {
-            lowerPanel.setDividerLocation(lowerPanelDividerLocation);
-        }
+        lowerPanel.setDividerLocation(logPanelPreferenceModel.getLowerPanelDividerLocation());
         detailPanel.setVisible(true);
         detailPanel.repaint();
         lowerPanel.repaint();
+        logPanelPreferenceModel.setLowerPanelDividerLocation(lowerPanel.getDividerLocation());
     }
 
     /**
@@ -2510,11 +2324,10 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
      */
     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);
+        detailPanel.repaint();
+        lowerPanel.repaint();
     }
 
     /**
@@ -2522,23 +2335,16 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
      */
     private void showLogTreePanel() {
         nameTreeAndMainPanelSplit.setDividerSize(dividerSize);
-        nameTreeAndMainPanelSplit.setDividerLocation(
-            lastLogTreePanelSplitLocation);
+        nameTreeAndMainPanelSplit.setDividerLocation(logPanelPreferenceModel.getLogTreeDividerLocation());
         logTreePanel.setVisible(true);
         nameTreeAndMainPanelSplit.repaint();
+        logPanelPreferenceModel.setLogTreeDividerLocation(nameTreeAndMainPanelSplit.getDividerLocation());
     }
 
     /**
      * 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();
@@ -2575,9 +2381,13 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
 
         dockPauseButton.getModel().setSelected(isPaused());
 
-        addPropertyChangeListener(
-            "paused",
-            evt -> dockPauseButton.getModel().setSelected(isPaused()));
+        logPanelPreferenceModel.addEventListener(
+            evt -> {
+            if (evt.getPropertyName().equals(LogPanelPreferenceModel.PAUSED)) {
+                dockPauseButton.getModel().setSelected((boolean)evt.getPropertyValue());
+            }
+        });
+
         toolbar.add(dockPauseButton);
 
         SmallButton showDockButton =
@@ -2607,7 +2417,12 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
 
         final SmallToggleButton toggleLogTreeButton =
             new SmallToggleButton(dockToggleLogTreeAction);
-        preferenceModel.addPropertyChangeListener("logTreePanelVisible", evt -> toggleLogTreeButton.setSelected(preferenceModel.isLogTreePanelVisible()));
+        logPanelPreferenceModel.addEventListener(
+            evt -> {
+            if (evt.getPropertyName().equals(LogPanelPreferenceModel.LOG_TREE_PANEL_VISIBLE)) {
+                toggleLogTreeButton.setSelected((Boolean)evt.getPropertyValue());
+            }
+        });
 
         toggleLogTreeButton.setSelected(isLogTreeVisible());
         toolbar.add(toggleLogTreeButton);
@@ -2650,7 +2465,13 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
 
         final SmallToggleButton toggleScrollToBottomButton =
             new SmallToggleButton(dockToggleScrollToBottomAction);
-        preferenceModel.addPropertyChangeListener("scrollToBottom", evt -> toggleScrollToBottomButton.setSelected(isScrollToBottom()));
+
+        logPanelPreferenceModel.addEventListener(
+            evt -> {
+            if (evt.getPropertyName().equals(LogPanelPreferenceModel.SCROLL_TO_BOTTOM)) {
+                toggleScrollToBottomButton.setSelected((Boolean)evt.getPropertyValue());
+            }
+        });
 
         toggleScrollToBottomButton.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
             KeyStroke.getKeyStroke(KeyEvent.VK_B, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
@@ -2795,7 +2616,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
                 } catch (IllegalArgumentException iae) {
                     findText.setToolTipText(iae.getMessage());
                     findText.setBackground(ChainsawConstants.INVALID_EXPRESSION_BACKGROUND);
-                    colorizer.setFindRule(null);
+                    currentColorizer.setFindRule(null);
                     tableRuleMediator.setFindRule(null);
                     searchRuleMediator.setFindRule(null);
                 }
@@ -2858,79 +2679,42 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
     /**
      * 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);
-
+    private void loadColumnSettings() {
         TableColumnModel columnModel = table.getColumnModel();
-        TableColumnModel searchColumnModel = searchTable.getColumnModel();
-
+        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
         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));
+            TableColumn thisColumn = columnModel.getColumn(i);
+            columnNameMap.put(table.getColumnName(i).toUpperCase(), thisColumn);
         }
 
-        for (int i = 0; i < searchColumnModel.getColumnCount(); i++) {
-            searchColumnNameMap.put(searchTable.getColumnName(i).toUpperCase(), searchColumnModel.getColumn(i));
+        for (int i = 0; i < columnModel.getColumnCount(); i++) {
+            TableColumn thisColumn = columnModel.getColumn(i);
+            columnNameMap.put(table.getColumnName(i).toUpperCase(), thisColumn);
         }
 
-        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);
-            }
+        while (table.getColumnCount() > 0) {
+            table.removeColumn(columnModel.getColumn(0));
         }
-        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"));
-
-        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);
+        Map<String, Integer> columnNamesAndWidths = logPanelPreferenceModel.getAllColumnNamesAndWidths();
+        for (String tableColumnName : logPanelPreferenceModel.getVisibleOrderedColumnNames()) {
+            TableColumn column = columnNameMap.get(tableColumnName);
+            if (column != null) {
+                Integer preferredWidth = columnNamesAndWidths.get(tableColumnName);
+                if (null != preferredWidth) {
+                    column.setPreferredWidth(preferredWidth);
                 }
-
-                index++;
-            } catch (NumberFormatException e) {
-                logger.error("Error decoding a Table width", e);
+                table.addColumn(column);
             }
         }
+
         undockedFrame.setSize(getSize());
         undockedFrame.setLocation(getBounds().x, getBounds().y);
 
-        repaint();
+        table.validate();
     }
 
     /**
@@ -3032,7 +2816,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
     }
 
     public void layoutComponents() {
-        if (preferenceModel.isDetailPaneVisible()) {
+        if (logPanelPreferenceModel.isDetailPaneVisible()) {
             showDetailPane();
         } else {
             hideDetailPane();
@@ -3053,13 +2837,13 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
     }
 
     public void setReceiver(ChainsawReceiver rx) {
-        m_receiver = rx;
-        m_receiver.addPropertyChangeListener(((pce) -> {
+        receiver = rx;
+        receiver.addPropertyChangeListener(((pce) -> {
             if (pce.getPropertyName().equals("name")) {
 //                this.identifier = pce.getNewValue();
             }
         }));
-        m_receiver.addChainsawEventBatchListener(this);
+        receiver.addChainsawEventBatchListener(this);
     }
 
     public void receiveChainsawEventBatch(List<ChainsawLoggingEvent> events) {
@@ -3330,7 +3114,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
             currentPoint = evt.getPoint();
             currentTable = detailTable;
 
-            if (preferenceModel.isToolTips()) {
+            if (logPanelPreferenceModel.isToolTipsVisible()) {
                 int row = detailTable.rowAtPoint(evt.getPoint());
 
                 if ((row == currentRow) || (row == -1)) {
@@ -3438,7 +3222,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
              * 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()) {
+            if (!logPanelPreferenceModel.isDetailPaneVisible()) {
                 return;
             }
 
@@ -3829,7 +3613,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
             super();
             addMouseMotionListener(new MouseMotionAdapter() {
                 public void mouseMoved(MouseEvent e) {
-                    if (preferenceModel.isThumbnailBarToolTips()) {
+                    if (logPanelPreferenceModel.isThumbnailBarToolTipsVisible()) {
                         int yPosition = e.getPoint().y;
                         ThumbnailLoggingEventWrapper event = getEventWrapperAtPosition(yPosition);
                         if (event != null) {
@@ -4065,7 +3849,7 @@ public class LogPanel extends DockablePanel implements ChainsawEventBatchListene
         public ToggleToolTips() {
             super("Show ToolTips", new ImageIcon(ChainsawIcons.TOOL_TIP));
             addActionListener(
-                evt -> preferenceModel.setToolTips(isSelected()));
+                evt -> logPanelPreferenceModel.setToolTipsVisible(isSelected()));
         }
     }
 }
diff --git a/src/main/java/org/apache/log4j/chainsaw/components/logpanel/LogPanelPreferenceModel.java b/src/main/java/org/apache/log4j/chainsaw/components/logpanel/LogPanelPreferenceModel.java
index e2a464c..1d6fcf8 100644
--- a/src/main/java/org/apache/log4j/chainsaw/components/logpanel/LogPanelPreferenceModel.java
+++ b/src/main/java/org/apache/log4j/chainsaw/components/logpanel/LogPanelPreferenceModel.java
@@ -19,12 +19,14 @@
  */
 package org.apache.log4j.chainsaw.components.logpanel;
 
+import org.apache.commons.configuration2.AbstractConfiguration;
+import org.apache.commons.configuration2.event.ConfigurationEvent;
+import org.apache.commons.configuration2.event.EventListener;
+import org.apache.log4j.chainsaw.ChainsawConstants;
+import org.apache.log4j.chainsaw.layout.DefaultLayoutFactory;
 import org.apache.log4j.helpers.Constants;
 
 import javax.swing.table.TableColumn;
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
-import java.io.Serializable;
 import java.util.*;
 
 /**
@@ -32,77 +34,76 @@ import java.util.*;
  *
  * @author Paul Smith
  */
-public class LogPanelPreferenceModel implements Serializable {
+public class LogPanelPreferenceModel {
     public static final String ISO8601 = "ISO8601";
-    public static final Collection DATE_FORMATS;
-
-    private static final long serialVersionUID = 7526472295622776147L;
-
-    static {
-        Collection list = new ArrayList();
-
-        Properties properties = new Properties(); //SettingsManager.getInstance().getDefaultSettings();
-
-        for (Map.Entry<Object, Object> objectObjectEntry : properties.entrySet()) {
-            Map.Entry<Object, Object> entry = objectObjectEntry;
-
-            if (entry.getKey().toString().startsWith("DateFormat")) {
-                list.add(entry.getValue());
-            }
-        }
-
-        DATE_FORMATS = Collections.unmodifiableCollection(list);
-    }
-
-    private transient final PropertyChangeSupport propertySupport =
-        new PropertyChangeSupport(this);
-    private String dateFormatPattern = Constants.SIMPLE_TIME_PATTERN;
-    private boolean levelIcons;
-    private List allColumns = new ArrayList();
-    private List visibleColumns = new ArrayList();
-    private List visibleColumnOrder = new ArrayList();
-    //set to true to match default 'detailPaneVisible' setting
-    private boolean detailPaneVisible = true;
-    private boolean toolTips;
-    //default thumbnail bar tooltips to true
-    private boolean thumbnailBarToolTips = true;
-    private boolean scrollToBottom;
-    private boolean logTreePanelVisible;
-    private String loggerPrecision = "";
-
-    private Collection hiddenLoggers = new HashSet();
-    private String timeZone;
-    //default wrapMsg to true
-    private boolean wrapMsg = true;
-    private boolean highlightSearchMatchText;
-    private String hiddenExpression;
-    private String alwaysDisplayExpression;
-    private String clearTableExpression;
-    //default to cyclic mode off
-    private boolean cyclic = false;
-    private boolean showMillisDeltaAsGap;
-    //default search results to visible
-    private boolean searchResultsVisible = true;
-
-    /**
-     * Returns an <b>unmodifiable</b> list of the columns.
-     * <p>
-     * The reason it is unmodifiable is to enforce the requirement that
-     * the List is actually unique columns.  IT _could_ be a set,
-     * but we need to maintain the order of insertion.
-     *
-     * @return
-     */
-    public List getColumns() {
-        return Collections.unmodifiableList(allColumns);
+    public static final Collection<String> DATE_FORMATS = Collections.singletonList(ISO8601);
+    public static final String PAUSED = "logpanel.paused";
+    public static final String CLEAR_TABLE_EXPRESSION = "logpanel.clearTableExpression";
+    public static final String ALWAYS_DISPLAY_EXPRESSION = "logpanel.alwaysDisplayExpression";
+    public static final String HIDDEN_EXPRESSION = "logpanel.hiddenExpression";
+    public static final String DATE_FORMAT_TIME_ZONE = "logpanel.dateFormatTimeZone";
+    public static final String HIDDEN_LOGGERS = "logpanel.hiddenLoggers";
+    public static final String LOG_TREE_PANEL_VISIBLE = "logpanel.logTreePanelVisible";
+    public static final String TOOL_TIPS_VISIBLE = "logpanel.toolTipsVisible";
+    public static final String THUMBNAIL_BAR_TOOL_TIPS_VISIBLE = "logpanel.thumbnailBarToolTipsVisible";
+    public static final String SHOW_MILLIS_DELTA_AS_GAP = "logpanel.showMillisDeltaAsGap";
+    public static final String SCROLL_TO_BOTTOM = "logpanel.scrollToBottom";
+    public static final String DETAIL_PANE_VISIBLE = "logpanel.detailPaneVisible";
+    public static final String LOGGER_PRECISION = "logpanel.loggerPrecision";
+    public static final String SEARCH_RESULTS_VISIBLE = "logpanel.searchResultsVisible";
+    public static final String WRAP_MSG = "logpanel.wrapMsg";
+    public static final String VISIBLE_ORDERED_COLUMN_NAMES = "logpanel.visibleOrderedColumnNames";
+    public static final String LEVEL_ICONS_DISPLAYED = "logpanel.levelIconsDisplayed";
+    public static final String HIGHLIGHT_SEARCH_MATCH_TEXT = "logpanel.highlightSearchMatchText";
+    private static final String LOWER_PANEL_DIVIDER_LOCATION = "logpanel.lowerPanelDividerLocation";
+    private static final String LOG_TREE_DIVIDER_LOCATION = "logpanel.logTreeDividerLocation";
+    private static final String CONVERSION_PATTERN = "logpanel.conversionPattern";
+    public static final String DATE_FORMAT_PATTERN = "dateFormatPattern";
+    AbstractConfiguration tabConfig;
+
+    private final String defaultDateFormatPattern = Constants.SIMPLE_TIME_PATTERN;
+    private Map<String, Integer> allColumnsAndWidths = new HashMap<>();
+    private List<String> visibleOrderedColumnNames = new ArrayList<>();
+    private final boolean pausedDefault = false;
+    private final boolean logTreePanelVisibleDefault = true;
+    private final boolean toolTipsVisibleDefault = false;
+    private final boolean thumbnailBarToolTipsVisibleDefault = false;
+    private final boolean showMillisDeltaAsGapDefault = false;
+    private final boolean scrollToBottomDefault = true;
+    private final int loggerPrecisionDefault = 0;
+    private final boolean searchResultsVisibleDefault = true;
+    private final boolean highlightSearchMatchTextDefault = true;
+    private final boolean wrapMsgDefault = true;
+    private final boolean levelIconsDisplayedDefault = false;
+
+    private static final int lowerPanelDividerLocationDefault = 700;
+    private static final int logTreeDividerLocationDefault = 230;
+
+    private static final String conversionPatternDefault = DefaultLayoutFactory.getDefaultPatternLayout();
+
+    private static final List<String> defaultOrderedColumnNames = List.of(ChainsawConstants.ID_COL_NAME,
+        ChainsawConstants.TIMESTAMP_COL_NAME, ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE.toUpperCase(),
+        ChainsawConstants.LEVEL_COL_NAME, ChainsawConstants.LOGGER_COL_NAME, ChainsawConstants.MESSAGE_COL_NAME);
+
+    private static final Map<String, Integer> defaultOrderedColumnNamesAndWidths =
+        Map.of(ChainsawConstants.ID_COL_NAME, 75, ChainsawConstants.TIMESTAMP_COL_NAME, 100,
+            ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE.toUpperCase(), 120, ChainsawConstants.LEVEL_COL_NAME, 75,
+            ChainsawConstants.LOGGER_COL_NAME, 125, ChainsawConstants.MESSAGE_COL_NAME, 650);
+
+    public LogPanelPreferenceModel(AbstractConfiguration tabConfig) {
+        this.tabConfig = tabConfig;
+    }
+
+    public void addEventListener(EventListener<ConfigurationEvent> listener) {
+        tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY, listener);
     }
 
     public void setCyclic(boolean cyclic) {
-        this.cyclic = cyclic;
+        tabConfig.setProperty("cyclic", cyclic);
     }
 
     public boolean isCyclic() {
-        return cyclic;
+        return tabConfig.getBoolean("cyclic", false);
     }
 
     /**
@@ -112,97 +113,39 @@ public class LogPanelPreferenceModel implements Serializable {
      * the List is actually unique columns.  IT _could_ be a set,
      * but we need to maintain the order of insertion.
      *
-     * @return
      */
-    public List getVisibleColumns() {
-        return Collections.unmodifiableList(visibleColumns);
+    public List<String> getVisibleOrderedColumnNames() {
+        return defaultOrderedColumnNames;
     }
 
-    public void clearColumns() {
-        Object oldValue = this.allColumns;
-        allColumns = new ArrayList();
-        propertySupport.firePropertyChange("columns", oldValue, allColumns);
-    }
-
-    private TableColumn findColumnByHeader(List list, String header) {
-        for (Object aList : list) {
-            TableColumn c = (TableColumn) aList;
-            //columns may have changed - header may not exist
-            if (c != null && c.getHeaderValue() != null && c.getHeaderValue().equals(header)) {
-                return c;
-            }
-        }
-        return null;
-    }
-
-    public void setVisibleColumnOrder(List visibleColumnOrder) {
-        this.visibleColumnOrder = visibleColumnOrder;
-    }
-
-    public List getVisibleColumnOrder() {
-        return visibleColumnOrder;
+    public void setVisibleOrderedColumnNames(List<String> visibleOrderedColumNames) {
+        this.visibleOrderedColumnNames = visibleOrderedColumNames;
     }
 
     public boolean addColumn(TableColumn column) {
-        if (findColumnByHeader(allColumns, column.getHeaderValue().toString()) != null) {
+        if (allColumnsAndWidths.containsKey(column.getHeaderValue().toString())) {
             return false;
         }
 
-        Object oldValue = allColumns;
-        allColumns = new ArrayList(allColumns);
-        allColumns.add(column);
-
-        propertySupport.firePropertyChange("columns", oldValue, allColumns);
+        allColumnsAndWidths.put(column.getHeaderValue().toString(), column.getWidth());
         return true;
     }
 
-    private void setColumns(List columns) {
-        Object oldValue = allColumns;
-        allColumns = new ArrayList(columns);
-        propertySupport.firePropertyChange("columns", oldValue, columns);
-    }
-
     /**
      * Returns the Date Pattern string for the alternate date formatter.
      *
      * @return date pattern
      */
     public final String getDateFormatPattern() {
-        return dateFormatPattern;
+        return tabConfig.getString(DATE_FORMAT_PATTERN, defaultDateFormatPattern);
     }
 
     public final void setDefaultDatePatternFormat() {
-        String oldVal = this.dateFormatPattern;
-        this.dateFormatPattern = Constants.SIMPLE_TIME_PATTERN;
-        propertySupport.firePropertyChange(
-            "dateFormatPattern", oldVal, this.dateFormatPattern);
+        tabConfig.setProperty(DATE_FORMAT_PATTERN, defaultDateFormatPattern);
     }
 
     public final void setDateFormatPattern(String dateFormatPattern) {
-        String oldVal = this.dateFormatPattern;
-        this.dateFormatPattern = dateFormatPattern;
-        propertySupport.firePropertyChange(
-            "dateFormatPattern", oldVal, this.dateFormatPattern);
-    }
-
-    public synchronized void addPropertyChangeListener(
-        PropertyChangeListener listener) {
-        propertySupport.addPropertyChangeListener(listener);
-    }
-
-    public synchronized void addPropertyChangeListener(
-        String propertyName, PropertyChangeListener listener) {
-        propertySupport.addPropertyChangeListener(propertyName, listener);
-    }
-
-    public synchronized void removePropertyChangeListener(
-        PropertyChangeListener listener) {
-        propertySupport.removePropertyChangeListener(listener);
-    }
-
-    public synchronized void removePropertyChangeListener(
-        String propertyName, PropertyChangeListener listener) {
-        propertySupport.removePropertyChangeListener(propertyName, listener);
+        tabConfig.setProperty(DATE_FORMAT_PATTERN, dateFormatPattern);
     }
 
     /**
@@ -215,21 +158,18 @@ public class LogPanelPreferenceModel implements Serializable {
         setCyclic(model.isCyclic());
         setLoggerPrecision(model.getLoggerPrecision());
         setDateFormatPattern(model.getDateFormatPattern());
-        setLevelIcons(model.isLevelIcons());
+        setLevelIconsDisplayed(model.isLevelIconsDisplayed());
         setWrapMessage(model.isWrapMessage());
         setHighlightSearchMatchText(model.isHighlightSearchMatchText());
-        setTimeZone(model.getTimeZone());
-        setToolTips(model.isToolTips());
-        setThumbnailBarToolTips((model.isThumbnailBarToolTips()));
+        setDateFormatTimeZone(model.getDateFormatTimeZone());
+        setToolTipsVisible(model.isToolTipsVisible());
+        setThumbnailBarToolTipsVisible((model.isThumbnailBarToolTipsVisible()));
         setScrollToBottom(model.isScrollToBottom());
         setDetailPaneVisible(model.isDetailPaneVisible());
         setLogTreePanelVisible(model.isLogTreePanelVisible());
-        setVisibleColumnOrder(model.getVisibleColumnOrder());
+        setVisibleOrderedColumnNames(model.getVisibleOrderedColumnNames());
         setSearchResultsVisible(model.isSearchResultsVisible());
-        // we have to copy the list, because getColumns() is unmodifiable
-        setColumns(model.getColumns());
-
-        setVisibleColumns(model.getVisibleColumns());
+        setVisibleOrderedColumnNames(model.getVisibleOrderedColumnNames());
         setHiddenLoggers(model.getHiddenLoggers());
         setHiddenExpression(model.getHiddenExpression());
         setAlwaysDisplayExpression(model.getAlwaysDisplayExpression());
@@ -250,51 +190,44 @@ public class LogPanelPreferenceModel implements Serializable {
     /**
      * @return level icons flag
      */
-    public boolean isLevelIcons() {
-        return levelIcons;
+    public boolean isLevelIconsDisplayed() {
+        return tabConfig.getBoolean(LEVEL_ICONS_DISPLAYED, levelIconsDisplayedDefault);
     }
 
     public boolean isWrapMessage() {
-        return wrapMsg;
+        return tabConfig.getBoolean(WRAP_MSG, wrapMsgDefault);
     }
 
     public boolean isHighlightSearchMatchText() {
-        return highlightSearchMatchText;
+        return tabConfig.getBoolean(HIGHLIGHT_SEARCH_MATCH_TEXT, highlightSearchMatchTextDefault);
     }
 
-    public void setLevelIcons(boolean levelIcons) {
-        this.levelIcons = levelIcons;
-        propertySupport.firePropertyChange("levelIcons", !levelIcons, levelIcons);
+    public void setLevelIconsDisplayed(boolean isLevelIconsDisplayed) {
+        tabConfig.setProperty(LEVEL_ICONS_DISPLAYED, isLevelIconsDisplayed);
     }
 
-    public void setSearchResultsVisible(boolean searchResultsVisible) {
-        boolean oldValue = this.searchResultsVisible;
-        this.searchResultsVisible = searchResultsVisible;
-        propertySupport.firePropertyChange("searchResultsVisible", oldValue, searchResultsVisible);
+    public void setSearchResultsVisible(boolean isSearchResultsVisible) {
+        tabConfig.setProperty(SEARCH_RESULTS_VISIBLE, isSearchResultsVisible);
     }
 
     public boolean isSearchResultsVisible() {
-        return searchResultsVisible;
+        return tabConfig.getBoolean(SEARCH_RESULTS_VISIBLE, searchResultsVisibleDefault);
     }
 
-    public void setWrapMessage(boolean wrapMsg) {
-        this.wrapMsg = wrapMsg;
-        propertySupport.firePropertyChange("wrapMessage", !wrapMsg, wrapMsg);
+    public void setWrapMessage(boolean isWrapMsg) {
+        tabConfig.setProperty(WRAP_MSG, isWrapMsg);
     }
 
     public void setHighlightSearchMatchText(boolean highlightSearchMatchText) {
-        this.highlightSearchMatchText = highlightSearchMatchText;
-        propertySupport.firePropertyChange("highlightSearchMatchText", !highlightSearchMatchText, highlightSearchMatchText);
+        tabConfig.setProperty(HIGHLIGHT_SEARCH_MATCH_TEXT, highlightSearchMatchText);
     }
 
     /**
      * @param loggerPrecision - an integer representing the number of packages to display,
-     *                        or an empty string representing 'display all packages'
+     *                        or zero, representing 'display all packages'
      */
-    public void setLoggerPrecision(String loggerPrecision) {
-        String oldVal = this.loggerPrecision;
-        this.loggerPrecision = loggerPrecision;
-        propertySupport.firePropertyChange("loggerPrecision", oldVal, this.loggerPrecision);
+    public void setLoggerPrecision(int loggerPrecision) {
+        tabConfig.setProperty(LOGGER_PRECISION, loggerPrecision);
     }
 
     /**
@@ -302,8 +235,8 @@ public class LogPanelPreferenceModel implements Serializable {
      *
      * @return logger precision
      */
-    public final String getLoggerPrecision() {
-        return loggerPrecision;
+    public final int getLoggerPrecision() {
+        return tabConfig.getInt(LOGGER_PRECISION, loggerPrecisionDefault);
     }
 
     /**
@@ -314,32 +247,18 @@ public class LogPanelPreferenceModel implements Serializable {
      * @return column visible flag
      */
     public boolean isColumnVisible(TableColumn column) {
-        return (findColumnByHeader(visibleColumns, column.getHeaderValue().toString()) != null);
-    }
-
-    private void setVisibleColumns(List visibleColumns) {
-        Object oldValue = new ArrayList();
-        this.visibleColumns = new ArrayList(visibleColumns);
-
-        propertySupport.firePropertyChange("visibleColumns", oldValue, this.visibleColumns);
+        return visibleOrderedColumnNames.contains(column.getHeaderValue().toString());
     }
 
     public void setColumnVisible(String columnName, boolean isVisible) {
-        boolean wasVisible = findColumnByHeader(visibleColumns, columnName) != null;
-
-        //because we're a list and not a set, ensure we keep at most
-        //one entry for a tablecolumn
-        Object col = findColumnByHeader(allColumns, columnName);
-        if (isVisible && !wasVisible) {
-            visibleColumns.add(col);
-            visibleColumnOrder.add(col);
-            propertySupport.firePropertyChange("visibleColumns", Boolean.valueOf(isVisible), Boolean.valueOf(wasVisible));
-        }
-        if (!isVisible && wasVisible) {
-            visibleColumns.remove(col);
-            visibleColumnOrder.remove(col);
-            propertySupport.firePropertyChange("visibleColumns", Boolean.valueOf(isVisible), Boolean.valueOf(wasVisible));
+        if (isVisible) {
+            if (!visibleOrderedColumnNames.contains(columnName)) {
+                visibleOrderedColumnNames.add(columnName);
+            }
+        } else {
+            visibleOrderedColumnNames.remove(columnName);
         }
+        tabConfig.setProperty(VISIBLE_ORDERED_COLUMN_NAMES, visibleOrderedColumnNames);
     }
 
     /**
@@ -355,77 +274,60 @@ public class LogPanelPreferenceModel implements Serializable {
      * @return detail pane visible flag
      */
     public final boolean isDetailPaneVisible() {
-        return detailPaneVisible;
+        return tabConfig.getBoolean(DETAIL_PANE_VISIBLE, true);
     }
 
     public final void setDetailPaneVisible(boolean detailPaneVisible) {
-        boolean oldValue = this.detailPaneVisible;
-        this.detailPaneVisible = detailPaneVisible;
-        propertySupport.firePropertyChange(
-            "detailPaneVisible", oldValue, this.detailPaneVisible);
+        tabConfig.setProperty(DETAIL_PANE_VISIBLE, detailPaneVisible);
     }
 
     /**
      * @return scroll to bottom flag
      */
     public final boolean isScrollToBottom() {
-        return scrollToBottom;
+        return tabConfig.getBoolean(SCROLL_TO_BOTTOM, scrollToBottomDefault);
     }
 
-
     public final boolean isShowMillisDeltaAsGap() {
-        return showMillisDeltaAsGap;
+        return tabConfig.getBoolean(SHOW_MILLIS_DELTA_AS_GAP, showMillisDeltaAsGapDefault);
     }
 
     public final void setScrollToBottom(boolean scrollToBottom) {
-        boolean oldValue = this.scrollToBottom;
-        this.scrollToBottom = scrollToBottom;
-        propertySupport.firePropertyChange(
-            "scrollToBottom", oldValue, this.scrollToBottom);
+        tabConfig.setProperty(SCROLL_TO_BOTTOM, scrollToBottom);
     }
 
     public final void setShowMillisDeltaAsGap(boolean showMillisDeltaAsGap) {
-        boolean oldValue = this.showMillisDeltaAsGap;
-        this.showMillisDeltaAsGap = showMillisDeltaAsGap;
-        propertySupport.firePropertyChange(
-            "showMillisDeltaAsGap", oldValue, this.showMillisDeltaAsGap);
+        tabConfig.setProperty(SHOW_MILLIS_DELTA_AS_GAP, showMillisDeltaAsGap);
     }
 
-    public final void setThumbnailBarToolTips(boolean thumbnailBarToolTips) {
-        boolean oldValue = this.thumbnailBarToolTips;
-        this.thumbnailBarToolTips = thumbnailBarToolTips;
-        propertySupport.firePropertyChange("thumbnailBarToolTips", oldValue, this.thumbnailBarToolTips);
+    public final void setThumbnailBarToolTipsVisible(boolean thumbnailBarToolTipsVisible) {
+        tabConfig.setProperty(THUMBNAIL_BAR_TOOL_TIPS_VISIBLE, thumbnailBarToolTipsVisible);
     }
 
-    public final boolean isThumbnailBarToolTips() {
-        return thumbnailBarToolTips;
+    public final boolean isThumbnailBarToolTipsVisible() {
+        return tabConfig.getBoolean(THUMBNAIL_BAR_TOOL_TIPS_VISIBLE, thumbnailBarToolTipsVisibleDefault);
     }
 
     /**
      * @return tool tips enabled flag
      */
-    public final boolean isToolTips() {
-        return toolTips;
+    public final boolean isToolTipsVisible() {
+        return tabConfig.getBoolean(TOOL_TIPS_VISIBLE, toolTipsVisibleDefault);
     }
 
-    public final void setToolTips(boolean toolTips) {
-        boolean oldValue = this.toolTips;
-        this.toolTips = toolTips;
-        propertySupport.firePropertyChange("toolTips", oldValue, this.toolTips);
+    public final void setToolTipsVisible(boolean toolTipsVisible) {
+        tabConfig.setProperty(TOOL_TIPS_VISIBLE, toolTipsVisible);
     }
 
     /**
      * @return log tree panel visible flag
      */
     public final boolean isLogTreePanelVisible() {
-        return logTreePanelVisible;
+        return tabConfig.getBoolean(LOG_TREE_PANEL_VISIBLE, logTreePanelVisibleDefault);
     }
 
     public final void setLogTreePanelVisible(boolean logTreePanelVisible) {
-        boolean oldValue = this.logTreePanelVisible;
-        this.logTreePanelVisible = logTreePanelVisible;
-        propertySupport.firePropertyChange(
-            "logTreePanelVisible", oldValue, this.logTreePanelVisible);
+        tabConfig.setProperty(LOG_TREE_PANEL_VISIBLE, logTreePanelVisible);
     }
 
     /**
@@ -435,57 +337,79 @@ public class LogPanelPreferenceModel implements Serializable {
         return !DATE_FORMATS.contains(getDateFormatPattern()) && !isUseISO8601Format();
     }
 
-    public void setHiddenLoggers(Collection hiddenSet) {
-        Object oldValue = this.hiddenLoggers;
-        this.hiddenLoggers = hiddenSet;
-        propertySupport.firePropertyChange("hiddenLoggers", oldValue, this.hiddenLoggers);
+    public void setHiddenLoggers(Collection<String> hiddenLoggers) {
+        tabConfig.setProperty(HIDDEN_LOGGERS, hiddenLoggers);
     }
 
-    public Collection getHiddenLoggers() {
-        return hiddenLoggers;
+    public Collection<String> getHiddenLoggers() {
+        return tabConfig.getList(String.class, HIDDEN_LOGGERS, Collections.emptyList());
     }
 
-    public String getTimeZone() {
-        return timeZone;
+    public String getDateFormatTimeZone() {
+        return tabConfig.getString(DATE_FORMAT_TIME_ZONE, "");
     }
 
-    public void setTimeZone(String timeZone) {
-        Object oldValue = this.timeZone;
-        this.timeZone = timeZone;
-        propertySupport.firePropertyChange("dateFormatTimeZone", oldValue, this.timeZone);
+    public void setDateFormatTimeZone(String dateFormatTimeZone) {
+        tabConfig.setProperty(DATE_FORMAT_TIME_ZONE, dateFormatTimeZone);
     }
 
     public void setHiddenExpression(String hiddenExpression) {
-        Object oldValue = this.hiddenExpression;
-        this.hiddenExpression = hiddenExpression;
-        propertySupport.firePropertyChange("hiddenExpression", oldValue, this.hiddenExpression);
+        tabConfig.setProperty(HIDDEN_EXPRESSION, hiddenExpression);
     }
 
     public String getHiddenExpression() {
-        return hiddenExpression;
+        return tabConfig.getString(HIDDEN_EXPRESSION, "");
     }
 
     public void setAlwaysDisplayExpression(String alwaysDisplayExpression) {
-        Object oldValue = this.hiddenExpression;
-        this.alwaysDisplayExpression = alwaysDisplayExpression;
-        propertySupport.firePropertyChange("alwaysDisplayExpression", oldValue, this.alwaysDisplayExpression);
+        tabConfig.setProperty(ALWAYS_DISPLAY_EXPRESSION, alwaysDisplayExpression);
     }
 
     public String getAlwaysDisplayExpression() {
-        return alwaysDisplayExpression;
+        return tabConfig.getString(ALWAYS_DISPLAY_EXPRESSION, "");
     }
 
     public void setClearTableExpression(String clearTableExpression) {
-        Object oldValue = this.clearTableExpression;
-        this.clearTableExpression = clearTableExpression;
-        //no propertychange if both null
-        if (oldValue == null && this.clearTableExpression == null) {
-            return;
-        }
-        propertySupport.firePropertyChange("clearTableExpression", oldValue, this.clearTableExpression);
+        tabConfig.setProperty(CLEAR_TABLE_EXPRESSION, clearTableExpression);
     }
 
     public String getClearTableExpression() {
-        return clearTableExpression;
+        return tabConfig.getString(CLEAR_TABLE_EXPRESSION, "");
+    }
+
+    public void setPaused(boolean paused) {
+        tabConfig.setProperty(PAUSED, paused);
+    }
+
+    public boolean isPaused() {
+        return tabConfig.getBoolean(PAUSED, pausedDefault);
+    }
+
+    public int getLowerPanelDividerLocation() {
+        return tabConfig.getInt(LOWER_PANEL_DIVIDER_LOCATION, lowerPanelDividerLocationDefault);
+    }
+
+    public void setLowerPanelDividerLocation(int lowerPanelDividerLocation) {
+        tabConfig.setProperty(LOWER_PANEL_DIVIDER_LOCATION, lowerPanelDividerLocation);
+    }
+
+    public int getLogTreeDividerLocation() {
+        return tabConfig.getInt(LOG_TREE_DIVIDER_LOCATION, logTreeDividerLocationDefault);
+    }
+
+    public void setLogTreeDividerLocation(int logTreeDividerLocation) {
+        tabConfig.setProperty(LOG_TREE_DIVIDER_LOCATION, logTreeDividerLocation);
+    }
+
+    public String getConversionPattern() {
+        return tabConfig.getString(CONVERSION_PATTERN, conversionPatternDefault);
+    }
+
+    public void setConversionPattern(String conversionPattern) {
+        tabConfig.setProperty(CONVERSION_PATTERN, conversionPatternDefault);
+    }
+
+    public Map<String, Integer> getAllColumnNamesAndWidths() {
+        return defaultOrderedColumnNamesAndWidths;
     }
 }
diff --git a/src/main/java/org/apache/log4j/chainsaw/components/logpanel/LogPanelPreferencePanel.java b/src/main/java/org/apache/log4j/chainsaw/components/logpanel/LogPanelPreferencePanel.java
index 098feca..e2f4f03 100644
--- a/src/main/java/org/apache/log4j/chainsaw/components/logpanel/LogPanelPreferencePanel.java
+++ b/src/main/java/org/apache/log4j/chainsaw/components/logpanel/LogPanelPreferencePanel.java
@@ -17,10 +17,8 @@
 package org.apache.log4j.chainsaw.components.logpanel;
 
 import org.apache.commons.configuration2.AbstractConfiguration;
-import org.apache.commons.configuration2.Configuration;
 import org.apache.commons.configuration2.event.ConfigurationEvent;
 import org.apache.log4j.chainsaw.AbstractPreferencePanel;
-import org.apache.log4j.chainsaw.ApplicationPreferenceModel;
 import org.apache.log4j.chainsaw.BasicPrefPanel;
 import org.apache.log4j.chainsaw.CheckListCellRenderer;
 import org.apache.log4j.chainsaw.JTextComponentFormatter;
@@ -32,7 +30,6 @@ import javax.swing.tree.DefaultMutableTreeNode;
 import javax.swing.tree.DefaultTreeModel;
 import javax.swing.tree.TreeModel;
 import java.awt.*;
-import java.awt.event.ActionListener;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.util.ArrayList;
@@ -48,15 +45,16 @@ public class LogPanelPreferencePanel extends AbstractPreferencePanel {
     //~ Instance fields =========================================================
 
     private final ModifiableListModel columnListModel = new ModifiableListModel();
-    private ApplicationPreferenceModel appPreferenceModel;
+    private final LogPanelPreferenceModel logPanelPreferenceModel;
     private SettingsManager settingsManager;
-    private final String m_panelIdentifier;
+    private final String tabIdentifier;
 
     //~ Constructors ============================================================
 
-    public LogPanelPreferencePanel(SettingsManager settingsManager, String panelIdent) {
+    public LogPanelPreferencePanel(SettingsManager settingsManager, String panelIdent, LogPanelPreferenceModel logPanelPreferenceModel) {
         this.settingsManager = settingsManager;
-        m_panelIdentifier = panelIdent;
+        tabIdentifier = panelIdent;
+        this.logPanelPreferenceModel = logPanelPreferenceModel;
         initComponents();
 
         getOkButton().addActionListener(e -> hidePanel());
@@ -111,10 +109,10 @@ public class LogPanelPreferencePanel extends AbstractPreferencePanel {
             final JList columnList = new JList();
             columnList.setVisibleRowCount(17);
 
-            AbstractConfiguration mergedConfig = settingsManager.getCombinedSettingsForRecevierTab(m_panelIdentifier);
-
-            String[] columnsOrder = mergedConfig.getStringArray( "table.columns.order" );
+            AbstractConfiguration readOnlyCombinedConfig = settingsManager.getCombinedSettingsForRecevierTab(tabIdentifier);
 
+//            String[] columnsOrder = readOnlyCombinedConfig.getStringArray( "table.columns.order" );
+//
 //            for (Object o : preferenceModel.getColumns()) {
 //                TableColumn col = (TableColumn) o;
 //                Enumeration enumeration = columnListModel.elements();
@@ -199,7 +197,7 @@ public class LogPanelPreferencePanel extends AbstractPreferencePanel {
         private void initComponents() {
             setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
 
-            AbstractConfiguration config = settingsManager.getCombinedSettingsForRecevierTab(m_panelIdentifier);
+            AbstractConfiguration config = settingsManager.getCombinedSettingsForRecevierTab(tabIdentifier);
 
 
             JPanel dateFormatPanel = new JPanel();
@@ -284,7 +282,7 @@ public class LogPanelPreferencePanel extends AbstractPreferencePanel {
             bgLevel.add(rdLevelIcons);
             bgLevel.add(rdLevelText);
 
-            rdLevelIcons.setSelected(config.getBoolean("logpanel.levelIcons"));
+            rdLevelIcons.setSelected(logPanelPreferenceModel.isLevelIconsDisplayed());
 
             levelFormatPanel.add(rdLevelIcons);
             levelFormatPanel.add(rdLevelText);
@@ -447,7 +445,7 @@ public class LogPanelPreferencePanel extends AbstractPreferencePanel {
          * DOCUMENT ME!
          */
         private void initPanelComponents() {
-            AbstractConfiguration config = settingsManager.getCombinedSettingsForRecevierTab(m_panelIdentifier);
+            AbstractConfiguration updatableTabConfig = settingsManager.getSettingsForReceiverTab(tabIdentifier);
 
             JTextComponentFormatter.applySystemFontAndSize(clearTableExpression);
             setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
@@ -469,111 +467,103 @@ public class LogPanelPreferencePanel extends AbstractPreferencePanel {
             JPanel clearPanel = new JPanel(new BorderLayout());
             clearPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
             clearPanel.add(new JLabel("Clear all events if expression matches"), BorderLayout.NORTH);
-            clearTableExpression.setText(config.getString("logpanel.clearTableExpression"));
             clearTableExpression.setPreferredSize(new Dimension(300, 50));
             JPanel clearTableScrollPanel = new JPanel(new BorderLayout());
             clearTableScrollPanel.add(new JScrollPane(clearTableExpression), BorderLayout.NORTH);
             clearPanel.add(clearTableScrollPanel, BorderLayout.CENTER);
             add(clearPanel);
 
-            toolTips.setSelected(config.getBoolean("logpanel.toolTips"));
-            thumbnailBarToolTips.setSelected(config.getBoolean("logpanel.thumbnailBarToolTips"));
-            detailPanelVisible.setSelected(config.getBoolean("logpanel.detailColumnVisible"));
-            searchResultsVisible.setSelected(config.getBoolean("logpanel.searchResultsVisible"));
-            loggerTreePanel.setSelected(config.getBoolean("logpanel.logTreePanelVisible"));
+            clearTableExpression.setText(logPanelPreferenceModel.getClearTableExpression());
+            toolTips.setSelected(logPanelPreferenceModel.isToolTipsVisible());
+            thumbnailBarToolTips.setSelected(logPanelPreferenceModel.isThumbnailBarToolTipsVisible());
+            detailPanelVisible.setSelected(logPanelPreferenceModel.isDetailPaneVisible());
+            searchResultsVisible.setSelected(logPanelPreferenceModel.isSearchResultsVisible());
+            loggerTreePanel.setSelected(logPanelPreferenceModel.isLogTreePanelVisible());
         }
 
         /**
          * DOCUMENT ME!
          */
         private void setupListeners() {
-            Configuration config = settingsManager.getCombinedSettingsForRecevierTab(m_panelIdentifier).getConfiguration(0);
-            AbstractConfiguration tabConfig = settingsManager.getSettingsForReceiverTab(m_panelIdentifier);
-
-            ActionListener wrapMessageListener = e -> config.setProperty("logpanel.wrapMsg", wrapMessage.isSelected());
+            AbstractConfiguration tabConfig = settingsManager.getSettingsForReceiverTab(tabIdentifier);
 
-            wrapMessage.addActionListener(wrapMessageListener);
+            wrapMessage.addActionListener(e -> logPanelPreferenceModel.setWrapMessage(wrapMessage.isSelected()));
 
-            ActionListener searchResultsVisibleListener = e -> config.setProperty("logpanel.searchResultsVisible", searchResultsVisible.isSelected());
+            searchResultsVisible.addActionListener(e -> logPanelPreferenceModel.setSearchResultsVisible(searchResultsVisible.isSelected()));
 
-            searchResultsVisible.addActionListener(searchResultsVisibleListener);
-
-            ActionListener highlightSearchMatchTextListener = e -> config.setProperty("logpanel.highlightSearchMatchText", highlightSearchMatchText.isSelected());
-
-            highlightSearchMatchText.addActionListener(highlightSearchMatchTextListener);
+            highlightSearchMatchText.addActionListener(e -> logPanelPreferenceModel.setHighlightSearchMatchText(highlightSearchMatchText.isSelected()));
 
             tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY,
                 evt -> {
-                    if(!evt.getPropertyName().equals("logpanel.wrapMsg")) return;
+                    if(!evt.getPropertyName().equals(LogPanelPreferenceModel.WRAP_MSG)) return;
                     boolean value = (Boolean) evt.getPropertyValue();
                     wrapMessage.setSelected(value);
                 });
 
-            tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY,
-                evt -> {
-                    if(!evt.getPropertyName().equals("logpanel.searchResultsVisible")) return;
-                    boolean value = (Boolean) evt.getPropertyValue();
-                    searchResultsVisible.setSelected(value);
-                });
+            tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY, evt -> {
+                if (!evt.getPropertyName().equals(LogPanelPreferenceModel.SEARCH_RESULTS_VISIBLE)) return;
+                boolean value = (Boolean) evt.getPropertyValue();
+                searchResultsVisible.setSelected(value);
+            });
 
             tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY,
                 evt -> {
-                    if(!evt.getPropertyName().equals("logpanel.highlightSearchMatchText")) return;
+                    if(!evt.getPropertyName().equals(LogPanelPreferenceModel.HIGHLIGHT_SEARCH_MATCH_TEXT)) return;
                     boolean value = (Boolean) evt.getPropertyValue();
                     highlightSearchMatchText.setSelected(value);
                 });
 
-            toolTips.addActionListener(e -> config.setProperty("logpanel.toolTips", toolTips.isSelected()));
+            toolTips.addActionListener(e -> logPanelPreferenceModel.setToolTipsVisible(toolTips.isSelected()));
 
-            thumbnailBarToolTips.addActionListener(e -> config.setProperty("logpanel.thumbnailBarToolTips", thumbnailBarToolTips.isSelected()));
+            thumbnailBarToolTips.addActionListener(e -> logPanelPreferenceModel.setThumbnailBarToolTipsVisible(thumbnailBarToolTips.isSelected()));
 
-            getOkButton().addActionListener(e -> config.setProperty("logpanel.clearTableExpression", clearTableExpression.getText().trim()));
+            getOkButton().addActionListener(e -> logPanelPreferenceModel.setClearTableExpression(clearTableExpression.getText().trim()));
 
             tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY,
                 evt -> {
-                    if(!evt.getPropertyName().equals("logpanel.toolTips")) return;
+                    if(!evt.getPropertyName().equals(LogPanelPreferenceModel.TOOL_TIPS_VISIBLE)) return;
                     boolean value = (Boolean) evt.getPropertyValue();
                     toolTips.setSelected(value);
                 });
 
             tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY,
                 evt -> {
-                    if(!evt.getPropertyName().equals("logpanel.thumbnailBarToolTips")) return;
+                    if(!evt.getPropertyName().equals(LogPanelPreferenceModel.THUMBNAIL_BAR_TOOL_TIPS_VISIBLE)) return;
                     boolean value = (Boolean) evt.getPropertyValue();
                     thumbnailBarToolTips.setSelected(value);
                 });
 
-            detailPanelVisible.addActionListener(e -> config.setProperty("logpanel.detailColumnVisible", detailPanelVisible.isSelected()));
+            detailPanelVisible.addActionListener(e -> logPanelPreferenceModel.setDetailPaneVisible(detailPanelVisible.isSelected()));
 
             tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY,
                 evt -> {
-                    if(!evt.getPropertyName().equals("logpanel.detailColumnVisible")) return;
+                    if(!evt.getPropertyName().equals(LogPanelPreferenceModel.DETAIL_PANE_VISIBLE)) return;
                     boolean value = (Boolean) evt.getPropertyValue();
                     detailPanelVisible.setSelected(value);
                 });
 
-            scrollToBottom.addActionListener(e -> config.setProperty("logpanel.scrollToBottom", scrollToBottom.isSelected()));
+            scrollToBottom.addActionListener(e -> logPanelPreferenceModel.setScrollToBottom(scrollToBottom.isSelected()));
 
-            showMillisDeltaAsGap.addActionListener(e -> config.setProperty("logpanel.showMillisDeltaAsGap", showMillisDeltaAsGap.isSelected()));
+            showMillisDeltaAsGap.addActionListener(e -> logPanelPreferenceModel.setShowMillisDeltaAsGap(showMillisDeltaAsGap.isSelected()));
 
             tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY,
                 evt -> {
-                if(!evt.getPropertyName().equals("logpanel.showMillisDeltaAsGap")) return;
+                if(!evt.getPropertyName().equals(LogPanelPreferenceModel.SHOW_MILLIS_DELTA_AS_GAP)) return;
                 boolean value = (Boolean) evt.getPropertyValue();
                 showMillisDeltaAsGap.setSelected(value);
             });
             tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY,
                 evt -> {
-                    if(!evt.getPropertyName().equals("logpanel.scrollToBottom")) return;
+                    if(!evt.getPropertyName().equals(LogPanelPreferenceModel.SCROLL_TO_BOTTOM)) return;
                     boolean value = (Boolean) evt.getPropertyValue();
                     scrollToBottom.setSelected(value);
                 });
 
-            loggerTreePanel.addActionListener(e -> config.setProperty("logpanel.logTreePanelVisible", loggerTreePanel.isSelected()));
+            loggerTreePanel.addActionListener(e -> logPanelPreferenceModel.setLogTreePanelVisible(loggerTreePanel.isSelected()));
 
             tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY,
                 evt -> {
-                    if(!evt.getPropertyName().equals("logpanel.logTreePanelVisible")) return;
+                    if(!evt.getPropertyName().equals(LogPanelPreferenceModel.LOG_TREE_PANEL_VISIBLE)) return;
                     boolean value = (Boolean) evt.getPropertyValue();
                     loggerTreePanel.setSelected(value);
                 });
@@ -602,7 +592,7 @@ public class LogPanelPreferencePanel extends AbstractPreferencePanel {
 
             tabConfig.addEventListener(ConfigurationEvent.SET_PROPERTY,
                 evt -> {
-                    if(!evt.getPropertyName().equals("logpanel.clearTableExpression")) return;
+                    if(!evt.getPropertyName().equals(LogPanelPreferenceModel.CLEAR_TABLE_EXPRESSION)) return;
                     clearTableExpression.setText(evt.getPropertyValue().toString());
                 });
         }
diff --git a/src/main/java/org/apache/log4j/chainsaw/logui/LogUI.java b/src/main/java/org/apache/log4j/chainsaw/logui/LogUI.java
index b055051..323b504 100644
--- a/src/main/java/org/apache/log4j/chainsaw/logui/LogUI.java
+++ b/src/main/java/org/apache/log4j/chainsaw/logui/LogUI.java
@@ -50,12 +50,8 @@ import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
 import java.io.File;
 import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.*;
 import java.util.List;
-import java.util.Map;
-import java.util.ServiceLoader;
-import java.util.Set;
 
 /**
  * The main entry point for Chainsaw, this class represents the first frame
@@ -107,6 +103,7 @@ public class LogUI extends JFrame {
 
     private final ShutdownManager shutdownManager;
     private LogUIPanelBuilder logUIPanelBuilder;
+    private final ApplicationPreferenceModel applicationPreferenceModel;
 
     /**
      * Constructor which builds up all the visual elements of the frame including
@@ -117,6 +114,7 @@ public class LogUI extends JFrame {
 
         this.settingsManager = settingsManager;
         this.configuration = settingsManager.getGlobalConfiguration();
+        applicationPreferenceModel = new ApplicationPreferenceModel(settingsManager.getGlobalConfiguration());
 
         setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
 
@@ -133,12 +131,11 @@ public class LogUI extends JFrame {
      */
     private void initGUI() {
         setupHelpSystem();
-        statusBar = new ChainsawStatusBar(this, configuration);
+        statusBar = new ChainsawStatusBar(this, applicationPreferenceModel);
 
-        boolean showStatusBar = configuration.getBoolean("statusBar", true);
-        setStatusBarVisible(showStatusBar);
+        setStatusBarVisible(applicationPreferenceModel.isStatusBarVisible());
 
-        chainsawToolBarAndMenus = new ChainsawToolBarAndMenus(this, configuration);
+        chainsawToolBarAndMenus = new ChainsawToolBarAndMenus(this, applicationPreferenceModel);
         toolbar = chainsawToolBarAndMenus.getToolbar();
         setJMenuBar(chainsawToolBarAndMenus.getMenubar());
 
@@ -146,7 +143,7 @@ public class LogUI extends JFrame {
 
         createDragAndDrop();
 
-        applicationPreferenceModelPanel = new ApplicationPreferenceModelPanel(settingsManager);
+        applicationPreferenceModelPanel = new ApplicationPreferenceModelPanel(settingsManager, applicationPreferenceModel);
 
         applicationPreferenceModelPanel.setOkCancelActionListener(e -> preferencesFrame.setVisible(false));
 
@@ -160,7 +157,7 @@ public class LogUI extends JFrame {
         preferencesFrame.getRootPane().
             getActionMap().put("ESCAPE", closeAction);
 
-        logUIPanelBuilder = new LogUIPanelBuilder(tabbedPane, identifierPanels, chainsawToolBarAndMenus, panelMap, settingsManager, statusBar, zeroConf);
+        logUIPanelBuilder = new LogUIPanelBuilder(tabbedPane, identifierPanels, chainsawToolBarAndMenus, panelMap, settingsManager, applicationPreferenceModel, statusBar, zeroConf);
 
         OSXIntegration.init(this);
     }
@@ -368,7 +365,7 @@ public class LogUI extends JFrame {
     }
 
     private void createReceiversPanel(JPanel panePanel) {
-        LogUiReceiversPanel logUiReceiversPanel = new LogUiReceiversPanel(settingsManager, receivers, this, statusBar, panePanel);
+        LogUiReceiversPanel logUiReceiversPanel = new LogUiReceiversPanel(settingsManager, applicationPreferenceModel, receivers, this, statusBar, panePanel);
         getContentPane().add(logUiReceiversPanel.getMainReceiverSplitPane(), BorderLayout.CENTER);
     }
 
@@ -457,6 +454,12 @@ public class LogUI extends JFrame {
             settingsManager.saveSettingsForReceiver(rx);
         }
 
+        for (Component comp :  panelMap.values()) {
+            if (comp instanceof LogPanel) {
+                ((LogPanel)comp).saveSettings();
+            }
+        }
+
         settingsManager.saveAllSettings();
         return shutdownManager.shutdown();
     }
@@ -513,7 +516,6 @@ public class LogUI extends JFrame {
      */
     public LogPanel getCurrentLogPanel() {
         Component selectedTab = tabbedPane.getSelectedComponent();
-
         if (selectedTab instanceof LogPanel) {
             return (LogPanel) selectedTab;
         }
diff --git a/src/main/java/org/apache/log4j/chainsaw/logui/LogUIPanelBuilder.java b/src/main/java/org/apache/log4j/chainsaw/logui/LogUIPanelBuilder.java
index 09add8e..33c77dd 100644
--- a/src/main/java/org/apache/log4j/chainsaw/logui/LogUIPanelBuilder.java
+++ b/src/main/java/org/apache/log4j/chainsaw/logui/LogUIPanelBuilder.java
@@ -17,6 +17,7 @@
 
 package org.apache.log4j.chainsaw.logui;
 
+import org.apache.log4j.chainsaw.ApplicationPreferenceModel;
 import org.apache.log4j.chainsaw.ChainsawConstants;
 import org.apache.log4j.chainsaw.ChainsawStatusBar;
 import org.apache.log4j.chainsaw.ChainsawToolBarAndMenus;
@@ -40,6 +41,7 @@ import java.util.Map;
 
 public class LogUIPanelBuilder {
     private static Logger logger = LogManager.getLogger(LogUIPanelBuilder.class);
+    private final ApplicationPreferenceModel applicationPreferenceModel;
 
     ChainsawTabbedPane tabbedPane;
     List<LogPanel> identifierPanels;
@@ -51,11 +53,12 @@ public class LogUIPanelBuilder {
     private ZeroConfPlugin zeroConfPlugin;
 
     private Map<String, RuleColorizer> allColorizers = new HashMap<>();
-    private RuleColorizer globalRuleColorizer = new RuleColorizer(settingsManager, true);
+    private RuleColorizer globalRuleColorizer = new RuleColorizer();
 
     public LogUIPanelBuilder(ChainsawTabbedPane tabbedPane, List<LogPanel> identifierPanels,
                              ChainsawToolBarAndMenus chainsawToolBarAndMenus, Map<String, Component> panelMap,
-                             SettingsManager settingsManager, ChainsawStatusBar chainsawStatusBar, ZeroConfPlugin zeroConfPlugin) {
+                             SettingsManager settingsManager, ApplicationPreferenceModel applicationPreferenceModel,
+                             ChainsawStatusBar chainsawStatusBar, ZeroConfPlugin zeroConfPlugin) {
         this.tabbedPane = tabbedPane;
         this.identifierPanels = identifierPanels;
         this.chainsawToolBarAndMenus = chainsawToolBarAndMenus;
@@ -63,16 +66,15 @@ public class LogUIPanelBuilder {
         this.settingsManager = settingsManager;
         this.chainsawStatusBar = chainsawStatusBar;
         this.zeroConfPlugin = zeroConfPlugin;
+        this.applicationPreferenceModel = applicationPreferenceModel;
 
-        RuleColorizer colorizer = new RuleColorizer(settingsManager);
+        RuleColorizer colorizer = new RuleColorizer();
         allColorizers.put(ChainsawConstants.DEFAULT_COLOR_RULE_NAME, colorizer);
-        globalRuleColorizer.setConfiguration(settingsManager.getGlobalConfiguration());
-        globalRuleColorizer.loadColorSettings();
     }
 
     void buildLogPanel(boolean customExpression, final String ident, final ChainsawReceiver rx)
         throws IllegalArgumentException {
-        final LogPanel thisPanel = new LogPanel(settingsManager, chainsawStatusBar, ident, allColorizers, globalRuleColorizer);
+        final LogPanel thisPanel = new LogPanel(settingsManager, applicationPreferenceModel, chainsawStatusBar, ident, allColorizers, globalRuleColorizer);
 
         if (!customExpression && rx != null) {
             thisPanel.setReceiver(rx);
@@ -95,7 +97,7 @@ public class LogUIPanelBuilder {
             evt -> chainsawToolBarAndMenus.stateChange();
 
         thisPanel.addPropertyChangeListener(toolbarMenuUpdateListener);
-        thisPanel.addPreferencePropertyChangeListener(toolbarMenuUpdateListener);
+        thisPanel.addPropertyChangeListener(toolbarMenuUpdateListener);
 
         thisPanel.addPropertyChangeListener(
             "docked",
diff --git a/src/main/java/org/apache/log4j/chainsaw/logui/LogUiReceiversPanel.java b/src/main/java/org/apache/log4j/chainsaw/logui/LogUiReceiversPanel.java
index 8696caf..ab0899f 100644
--- a/src/main/java/org/apache/log4j/chainsaw/logui/LogUiReceiversPanel.java
+++ b/src/main/java/org/apache/log4j/chainsaw/logui/LogUiReceiversPanel.java
@@ -16,8 +16,7 @@
  */
 package org.apache.log4j.chainsaw.logui;
 
-import org.apache.commons.configuration2.AbstractConfiguration;
-import org.apache.commons.configuration2.event.ConfigurationEvent;
+import org.apache.log4j.chainsaw.ApplicationPreferenceModel;
 import org.apache.log4j.chainsaw.ChainsawStatusBar;
 import org.apache.log4j.chainsaw.prefs.SettingsManager;
 import org.apache.log4j.chainsaw.receiver.ChainsawReceiver;
@@ -34,7 +33,8 @@ public class LogUiReceiversPanel {
     private int dividerSize;
     private static final double DEFAULT_MAIN_RECEIVER_SPLIT_LOCATION = 0.85d;
     private double lastMainReceiverSplitLocation = DEFAULT_MAIN_RECEIVER_SPLIT_LOCATION;
-    public LogUiReceiversPanel(SettingsManager settingsManager, List<ChainsawReceiver> receivers, LogUI logUI, ChainsawStatusBar statusBar, JPanel panePanel) {
+    public LogUiReceiversPanel(SettingsManager settingsManager, ApplicationPreferenceModel applicationPreferenceModel,
+                               List<ChainsawReceiver> receivers, LogUI logUI, ChainsawStatusBar statusBar, JPanel panePanel) {
         receiversPanel = new ReceiversPanel(settingsManager, receivers, logUI, statusBar);
         mainReceiverSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, panePanel, receiversPanel);
         mainReceiverSplitPane.setContinuousLayout(true);
@@ -42,12 +42,11 @@ public class LogUiReceiversPanel {
         mainReceiverSplitPane.setDividerLocation(-1);
         mainReceiverSplitPane.setResizeWeight(1.0);
 
-        AbstractConfiguration configuration = settingsManager.getGlobalConfiguration();
-        boolean showReceivers = configuration.getBoolean("showReceivers", false);
+        boolean showReceivers = applicationPreferenceModel.isReceiversVisible();
 
-        configuration.addEventListener(ConfigurationEvent.SET_PROPERTY,
+        applicationPreferenceModel.addEventListener(
             evt -> {
-                if (evt.getPropertyName().equals("showReceivers")) {
+                if (evt.getPropertyName().equals(ApplicationPreferenceModel.RECEIVERS_VISIBLE)) {
                     boolean value = (Boolean) evt.getPropertyValue();
                     if (value) {
                         showReceiverPanel();
diff --git a/src/main/java/org/apache/log4j/chainsaw/prefs/SettingsManager.java b/src/main/java/org/apache/log4j/chainsaw/prefs/SettingsManager.java
index 7012ed8..4532693 100644
--- a/src/main/java/org/apache/log4j/chainsaw/prefs/SettingsManager.java
+++ b/src/main/java/org/apache/log4j/chainsaw/prefs/SettingsManager.java
@@ -50,7 +50,7 @@ import java.util.ServiceLoader;
 public final class SettingsManager {
     private static final Logger logger = LogManager.getLogger(SettingsManager.class);
 
-    private static final String GLOBAL_SETTINGS_FILE_NAME = "chainsaw.settings.properties";
+    private static final String GLOBAL_SETTINGS_FILE_NAME = "chainsaw.global.properties";
 
     private static class TabSettingsData {
         FileBasedConfigurationBuilder<PropertiesConfiguration> file;
diff --git a/src/main/resources/org/apache/log4j/chainsaw/prefs/default.properties b/src/main/resources/org/apache/log4j/chainsaw/prefs/default.properties
index 1c4ec4d..36e9353 100644
--- a/src/main/resources/org/apache/log4j/chainsaw/prefs/default.properties
+++ b/src/main/resources/org/apache/log4j/chainsaw/prefs/default.properties
@@ -25,39 +25,16 @@ main.window.y=0
 main.window.width=-1
 main.window.height=-1
 
-# Note: order also implies visibility.  If the column does not exist in this array, it will not be shown
-table.columns.order=ID,TIMESTAMP,MARKER,LEVEL,LOGGER,MESSAGE,THROWABLE,THREAD,NDC,CLASS,METHOD,FILE,LINE,MILLISDELTA
-table.columns.widths=50,80,95,50,100,500,100,100,100,100,100,100,100,100
-
-SavedConfigs.Size=0
-DateFormat.1=HH:mm:ss
-DateFormat.2=HH:mm
-
-tabPlacement=1
-statusBar=true
-toolbar=true
-showReceivers=false
+showNoReceiverWarning=true
+identifierExpression=PROP.hostname - PROP.application
+cyclicBufferSize=50000
+toolTipDisplayMillis=4000
+responsiveness=3
+tabPlacement=3
+statusBarVisible=true
+receiversVisible=false
+toolbarVisible=true
 confirmExit=true
+showSplash=true
+bypassSearchColors=false
 
-# These are the default LogPanel settings
-dateFormatPattern=HH:mm:ss
-levelIcons=false
-loggerPrecision=
-toolTips=false
-scrollToBottom=true
-logTreePanelVisible=true
-detailPaneVisible=true
-highlightSearchMatchText=true
-wrapMessage=true
-searchResultsVisible=true
-
-# Default color settings
-color.rules(0).expression = level == FATAL || level == ERROR || exception exists
-color.rules(0).backgroundColor = #ff9999
-color.rules(0).foregroundColor = #000000
-color.rules(1).expression = level == WARN
-color.rules(1).backgroundColor = #ffff99
-color.rules(1).foregroundColor = #000000
-color.rules(2).expression = prop.marker exists
-color.rules(2).backgroundColor = #99ff99
-color.rules(2).foregroundColor = #000000
diff --git a/src/main/resources/org/apache/log4j/chainsaw/prefs/logpanel.properties b/src/main/resources/org/apache/log4j/chainsaw/prefs/logpanel.properties
index 1a06cd0..41163ea 100644
--- a/src/main/resources/org/apache/log4j/chainsaw/prefs/logpanel.properties
+++ b/src/main/resources/org/apache/log4j/chainsaw/prefs/logpanel.properties
@@ -16,23 +16,24 @@
 # ====================================
 # The Default Settings for a log panel within Chainsaw
 # ====================================
-
-logpanel.dateFormatPattern=HH:mm:ss
-logpanel.levelIcons=false
-logpanel.detailColumnVisible=true
-logpanel.toolTips=false
-logpanel.thumbnailBarToolTips=true
-logpanel.scrollToBottom=false
+logpanel.paused=false
+logpanel.clearTableExpression=
+logpanel.alwaysDisplayExpression=
+logpanel.hiddenExpression=
+logpanel.dateFormatTimeZone=
+logpanel.hiddenLoggers=
 logpanel.logTreePanelVisible=true
-logpanel.hiddenloggers=
-logpanel.wrapMsg=true
-logpanel.highlightSearchMatchText=true
-logpanel.cyclic=false
+logpanel.toolTipsVisible=false
+logpanel.thumbnailBarToolTipsVisible=false
 logpanel.showMillisDeltaAsGap=false
+logpanel.scrollToBottom=true
+logpanel.detailPaneVisible=true
+logpanel.loggerPrecision=0
 logpanel.searchResultsVisible=true
-logpanel.lowerPanelDividerLocation=0
-logpanel.treeDividerLocation=120
-logpanel.hiddenLoggers=
-logpanel.hiddenExpression=
-logpanel.alwaysDisplayExpression=
-logpanel.clearTableExpression=
+logpanel.wrapMsg=true
+logpanel.visibleOrderedColumnNames=
+logpanel.levelIconsDisplayed=false
+logpanel.highlightSearchMatchText=true
+logpanel.lowerPanelDividerLocation=475
+logpanel.logTreeDividerLocation=230
+dateFormatPattern=HH:mm:ss