LogPanel is now loading some settings from the new settings file
diff --git a/src/main/java/org/apache/log4j/chainsaw/LogPanel.java b/src/main/java/org/apache/log4j/chainsaw/LogPanel.java
index b2cb46c..7e077d8 100644
--- a/src/main/java/org/apache/log4j/chainsaw/LogPanel.java
+++ b/src/main/java/org/apache/log4j/chainsaw/LogPanel.java
@@ -59,6 +59,7 @@
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.List;
+import org.apache.commons.configuration2.AbstractConfiguration;
import org.apache.log4j.chainsaw.logevents.ChainsawLoggingEvent;
import org.apache.log4j.chainsaw.logevents.Level;
import org.apache.log4j.spi.LoggingEventFieldResolver;
@@ -115,7 +116,7 @@
* @see org.apache.log4j.rule.ExpressionRule
* @see org.apache.log4j.spi.LoggingEventFieldResolver
*/
-public class LogPanel extends DockablePanel implements Profileable, ChainsawEventBatchListener {
+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;
@@ -1761,6 +1762,8 @@
final PopupListener searchTablePopupListener = new PopupListener(searchPopup);
searchPane.addMouseListener(searchTablePopupListener);
searchTable.addMouseListener(searchTablePopupListener);
+
+ loadSettings();
}
private String getValueOf(int row, int column) {
@@ -1945,128 +1948,169 @@
/**
* Load settings from the panel preference model
*
- * @param event
- * @see LogPanelPreferenceModel
*/
- public void loadSettings(LoadSettingsEvent event) {
+ private void loadSettings() {
+ logger.info( "Loading settings for panel with identifier {}", identifier );
- File xmlFile = null;
- try {
- xmlFile = new File(SettingsManager.getInstance().getSettingsDirectory(), URLEncoder.encode(identifier, "UTF-8") + ".xml");
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
+ AbstractConfiguration config = SettingsManager.getInstance().getSettingsForReceiverTab(identifier);
+ Iterator<String> iter = config.getKeys();
+ while( iter.hasNext() ){
+ logger.debug( "Key: {}", iter.next() );
}
- if (xmlFile.exists()) {
- XStream stream = buildXStreamForLogPanelPreference();
- ObjectInputStream in = null;
- try {
- logger.info("configuration for panel exists: " + xmlFile + " - " + identifier + ", loading");
- FileReader r = new FileReader(xmlFile);
- in = stream.createObjectInputStream(r);
- LogPanelPreferenceModel storedPrefs = (LogPanelPreferenceModel) in.readObject();
- lowerPanelDividerLocation = in.readInt();
- int treeDividerLocation = in.readInt();
- String conversionPattern = in.readObject().toString();
- //this version number is checked to identify whether there is a Vector comming next
- int versionNumber = 0;
- try {
- versionNumber = in.readInt();
- } catch (EOFException eof) {
- }
-
- Vector savedVector;
- //read the vector only if the version number is greater than 0. higher version numbers can be
- //used in the future to save more data structures
- if (versionNumber > 0) {
- savedVector = (Vector) in.readObject();
- for (Object item : savedVector) {
- //insert each row at index zero (so last row in vector will be row zero)
- filterCombo.insertItemAt(item, 0);
- findCombo.insertItemAt(item, 0);
- }
- if (versionNumber > 1) {
- //update prefModel columns to include defaults
- int index = 0;
- String columnOrder = event.getSetting(TABLE_COLUMN_ORDER);
- StringTokenizer tok = new StringTokenizer(columnOrder, ",");
- while (tok.hasMoreElements()) {
- String element = tok.nextElement().toString().trim().toUpperCase();
- TableColumn column = new TableColumn(index++);
- column.setHeaderValue(element);
- preferenceModel.addColumn(column);
- }
-
- TableColumnModel columnModel = table.getColumnModel();
- //remove previous columns
- while (columnModel.getColumnCount() > 0) {
- columnModel.removeColumn(columnModel.getColumn(0));
- }
- //add visible column order columns
- for (Object o1 : preferenceModel.getVisibleColumnOrder()) {
- TableColumn col = (TableColumn) o1;
- columnModel.addColumn(col);
- }
-
- TableColumnModel searchColumnModel = searchTable.getColumnModel();
- //remove previous columns
- while (searchColumnModel.getColumnCount() > 0) {
- searchColumnModel.removeColumn(searchColumnModel.getColumn(0));
- }
- //add visible column order columns
- for (Object o : preferenceModel.getVisibleColumnOrder()) {
- TableColumn col = (TableColumn) o;
- searchColumnModel.addColumn(col);
- }
-
- preferenceModel.apply(storedPrefs);
- } else {
- loadDefaultColumnSettings(event);
- }
- //ensure tablemodel cyclic flag is updated
- //may be panel configs that don't have these values
- tableModel.setCyclic(preferenceModel.isCyclic());
- searchModel.setCyclic(preferenceModel.isCyclic());
- lowerPanel.setDividerLocation(lowerPanelDividerLocation);
- nameTreeAndMainPanelSplit.setDividerLocation(treeDividerLocation);
- detailLayout.setConversionPattern(conversionPattern);
- undockedFrame.setLocation(0, 0);
- undockedFrame.setSize(new Dimension(1024, 768));
- } else {
- loadDefaultColumnSettings(event);
- }
- } catch (Exception e) {
- logger.info("unable to load configuration for panel: " + xmlFile + " - " + identifier + " - using default settings", e);
- loadDefaultColumnSettings(event);
- // TODO need to log this..
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (IOException ioe) {
- }
- }
- }
- } else {
- //not setting lower panel divider location here - will do that after the UI is visible
- loadDefaultColumnSettings(event);
+ 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);
}
- //ensure tablemodel cyclic flag is updated
- tableModel.setCyclic(preferenceModel.isCyclic());
- searchModel.setCyclic(preferenceModel.isCyclic());
- logTreePanel.ignore(preferenceModel.getHiddenLoggers());
- logTreePanel.setHiddenExpression(preferenceModel.getHiddenExpression());
- logTreePanel.setAlwaysDisplayExpression(preferenceModel.getAlwaysDisplayExpression());
- if (preferenceModel.getClearTableExpression() != null) {
+
+ String[] columnsOrder = config.getStringArray( "table.columns.order" );
+ Integer[] columnWidths = (Integer[])config.getArray(Integer.class, "table.columns.widths" );
+ TableColumnModel columnModel = table.getColumnModel();
+ for( int index = 0; index < columnsOrder.length; index++ ){
+ logger.debug( "Loading column {}", columnsOrder[index] );
+ TableColumn column = new TableColumn(index);
+ column.setHeaderValue(columnsOrder[index]);
+ preferenceModel.addColumn(column);
+ }
+
+ boolean isCyclic = config.getBoolean( "logpanel.cyclic" );
+ tableModel.setCyclic( isCyclic );
+ searchModel.setCyclic( isCyclic );
+ lowerPanel.setDividerLocation(config.getInt( "logpanel.lowerPanelDividerLocation" ));
+ nameTreeAndMainPanelSplit.setDividerLocation(config.getInt( "logpanel.treeDividerLocation" ));
+ detailLayout.setConversionPattern(conversionPattern);
+ 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);
+ if (clearTableExpression != null && clearTableExpression.length() > 1) {
try {
- clearTableExpressionRule = ExpressionRule.getRule(preferenceModel.getClearTableExpression());
+ clearTableExpressionRule = ExpressionRule.getRule(clearTableExpression);
} catch (Exception e) {
clearTableExpressionRule = null;
}
}
- //attempt to load color settings - no need to URL encode the identifier
- colorizer.loadColorSettings(identifier);
+ colorizer.loadColorSettings(config);
+
+
+// if (xmlFile.exists()) {
+// XStream stream = buildXStreamForLogPanelPreference();
+// ObjectInputStream in = null;
+// try {
+// logger.info("configuration for panel exists: " + xmlFile + " - " + identifier + ", loading");
+// FileReader r = new FileReader(xmlFile);
+// in = stream.createObjectInputStream(r);
+// LogPanelPreferenceModel storedPrefs = (LogPanelPreferenceModel) in.readObject();
+// lowerPanelDividerLocation = in.readInt();
+// int treeDividerLocation = in.readInt();
+// String conversionPattern = in.readObject().toString();
+// //this version number is checked to identify whether there is a Vector comming next
+// int versionNumber = 0;
+// try {
+// versionNumber = in.readInt();
+// } catch (EOFException eof) {
+// }
+//
+// Vector savedVector;
+// //read the vector only if the version number is greater than 0. higher version numbers can be
+// //used in the future to save more data structures
+// if (versionNumber > 0) {
+// savedVector = (Vector) in.readObject();
+// for (Object item : savedVector) {
+// //insert each row at index zero (so last row in vector will be row zero)
+// filterCombo.insertItemAt(item, 0);
+// findCombo.insertItemAt(item, 0);
+// }
+// if (versionNumber > 1) {
+// //update prefModel columns to include defaults
+// int index = 0;
+// String columnOrder = event.getSetting(TABLE_COLUMN_ORDER);
+// StringTokenizer tok = new StringTokenizer(columnOrder, ",");
+// while (tok.hasMoreElements()) {
+// String element = tok.nextElement().toString().trim().toUpperCase();
+// TableColumn column = new TableColumn(index++);
+// column.setHeaderValue(element);
+// preferenceModel.addColumn(column);
+// }
+//
+// TableColumnModel columnModel = table.getColumnModel();
+// //remove previous columns
+// while (columnModel.getColumnCount() > 0) {
+// columnModel.removeColumn(columnModel.getColumn(0));
+// }
+// //add visible column order columns
+// for (Object o1 : preferenceModel.getVisibleColumnOrder()) {
+// TableColumn col = (TableColumn) o1;
+// columnModel.addColumn(col);
+// }
+//
+// TableColumnModel searchColumnModel = searchTable.getColumnModel();
+// //remove previous columns
+// while (searchColumnModel.getColumnCount() > 0) {
+// searchColumnModel.removeColumn(searchColumnModel.getColumn(0));
+// }
+// //add visible column order columns
+// for (Object o : preferenceModel.getVisibleColumnOrder()) {
+// TableColumn col = (TableColumn) o;
+// searchColumnModel.addColumn(col);
+// }
+//
+// preferenceModel.apply(storedPrefs);
+// } else {
+// loadDefaultColumnSettings(event);
+// }
+// //ensure tablemodel cyclic flag is updated
+// //may be panel configs that don't have these values
+// tableModel.setCyclic(preferenceModel.isCyclic());
+// searchModel.setCyclic(preferenceModel.isCyclic());
+// lowerPanel.setDividerLocation(lowerPanelDividerLocation);
+// nameTreeAndMainPanelSplit.setDividerLocation(treeDividerLocation);
+// detailLayout.setConversionPattern(conversionPattern);
+// undockedFrame.setLocation(0, 0);
+// undockedFrame.setSize(new Dimension(1024, 768));
+// } else {
+// loadDefaultColumnSettings(event);
+// }
+// } catch (Exception e) {
+// logger.info("unable to load configuration for panel: " + xmlFile + " - " + identifier + " - using default settings", e);
+// loadDefaultColumnSettings(event);
+// // TODO need to log this..
+// } finally {
+// if (in != null) {
+// try {
+// in.close();
+// } catch (IOException ioe) {
+// }
+// }
+// }
+// } else {
+// //not setting lower panel divider location here - will do that after the UI is visible
+// loadDefaultColumnSettings(event);
+// }
+// //ensure tablemodel cyclic flag is updated
+// tableModel.setCyclic(preferenceModel.isCyclic());
+// searchModel.setCyclic(preferenceModel.isCyclic());
+// logTreePanel.ignore(preferenceModel.getHiddenLoggers());
+// logTreePanel.setHiddenExpression(preferenceModel.getHiddenExpression());
+// logTreePanel.setAlwaysDisplayExpression(preferenceModel.getAlwaysDisplayExpression());
+// if (preferenceModel.getClearTableExpression() != null) {
+// try {
+// clearTableExpressionRule = ExpressionRule.getRule(preferenceModel.getClearTableExpression());
+// } catch (Exception e) {
+// clearTableExpressionRule = null;
+// }
+// }
+//
+// //attempt to load color settings - no need to URL encode the identifier
+// colorizer.loadColorSettings(identifier);
}
/**
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 4965cdc..aa197cf 100644
--- a/src/main/java/org/apache/log4j/chainsaw/color/RuleColorizer.java
+++ b/src/main/java/org/apache/log4j/chainsaw/color/RuleColorizer.java
@@ -41,10 +41,10 @@
* @author Scott Deboy <sdeboy@apache.org>
*/
public class RuleColorizer implements Colorizer {
- private Map rules;
+ private Map<String,List<ColorRule>> rules;
private final PropertyChangeSupport colorChangeSupport =
new PropertyChangeSupport(this);
- private Map defaultRules = new HashMap();
+ private Map<String,List<ColorRule>> defaultRules = new HashMap<>();
private String currentRuleSet = ChainsawConstants.DEFAULT_COLOR_RULE_NAME;
private Rule findRule;
private Rule loggerRule;
@@ -60,7 +60,7 @@
private final String DEFAULT_MARKER_EXPRESSION = "prop.marker exists";
public RuleColorizer() {
- List rulesList = new ArrayList();
+ List<ColorRule> rulesList = new ArrayList<>();
String expression = DEFAULT_FATAL_ERROR_EXCEPTION_EXPRESSION;
rulesList.add(
@@ -101,26 +101,25 @@
return loggerRule;
}
- public void setRules(Map rules) {
+ public void setRules(Map<String,List<ColorRule>> rules) {
this.rules = rules;
colorChangeSupport.firePropertyChange("colorrule", false, true);
}
- public Map getRules() {
+ public Map<String,List<ColorRule>> getRules() {
return rules;
}
- public List getCurrentRules() {
- return (List) rules.get(currentRuleSet);
+ public List<ColorRule> getCurrentRules() {
+ return rules.get(currentRuleSet);
}
- public void addRules(Map newRules) {
+ public void addRules(Map<String,List<ColorRule>> newRules) {
- for (Object o : newRules.entrySet()) {
- Map.Entry entry = (Map.Entry) o;
+ for (Map.Entry<String,List<ColorRule>> entry : newRules.entrySet()) {
if (rules.containsKey(entry.getKey())) {
- ((List) rules.get(entry.getKey())).addAll((List) entry.getValue());
+ rules.get(entry.getKey()).addAll( entry.getValue() );
} else {
rules.put(entry.getKey(), entry.getValue());
}
@@ -131,9 +130,9 @@
public void addRule(String ruleSetName, ColorRule rule) {
if (rules.containsKey(ruleSetName)) {
- ((List) rules.get(ruleSetName)).add(rule);
+ rules.get(ruleSetName).add(rule);
} else {
- List list = new ArrayList();
+ List<ColorRule> list = new ArrayList<>();
list.add(rule);
rules.put(ruleSetName, list);
}
@@ -143,10 +142,10 @@
public void removeRule(String ruleSetName, String expression) {
if (rules.containsKey(ruleSetName)) {
- List list = (List) rules.get(ruleSetName);
+ List<ColorRule> list = rules.get(ruleSetName);
for (int i = 0; i < list.size(); i++) {
- ColorRule rule = (ColorRule) list.get(i);
+ ColorRule rule = list.get(i);
if (rule.getExpression().equals(expression)) {
list.remove(rule);
@@ -163,10 +162,9 @@
public Color getBackgroundColor(ChainsawLoggingEvent event) {
if (rules.containsKey(currentRuleSet)) {
- List list = (List) rules.get(currentRuleSet);
+ List<ColorRule> list = rules.get(currentRuleSet);
- for (Object aList : list) {
- ColorRule rule = (ColorRule) aList;
+ for (ColorRule rule : list) {
if ((rule.getBackgroundColor() != null) && (rule.evaluate(event, null))) {
return rule.getBackgroundColor();
@@ -179,10 +177,9 @@
public Color getForegroundColor(ChainsawLoggingEvent event) {
if (rules.containsKey(currentRuleSet)) {
- List list = (List) rules.get(currentRuleSet);
+ List<ColorRule> list = rules.get(currentRuleSet);
- for (Object aList : list) {
- ColorRule rule = (ColorRule) aList;
+ for (ColorRule rule : list) {
if ((rule.getForegroundColor() != null) && (rule.evaluate(event, null))) {
return rule.getForegroundColor();
@@ -246,11 +243,29 @@
// 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
-// configuration.get
-// configuration.getInt( "colors.", 0)
-// if (!doLoadColorSettings(name)) {
-// doLoadColorSettings(ChainsawConstants.DEFAULT_COLOR_RULE_NAME);
+ // This needs to be done for each rule set, so we first need to get a
+ // list of the rule sets
+ String[] ruleSets = configuration.getStringArray( "color.rulesets" );
+ if( ruleSets.length == 0 ){
+ // Default rule set is already defined
+ return;
+ }
+
+ /*
+ ColorRule(final String expression,
+ final Rule rule,
+ final Color backgroundColor,
+ final Color foregroundColor)
+ */
+// Map<String,List<ColorRule>> rules = new HashMap<>();
+// for( String ruleSet : ruleSets ){
+// String[] rulesForRuleSet = configuration.getStringArray( "color.rules." + ruleSet );
+// for( String individualRule : rulesForRuleSet ){
+//
+// }
// }
+//
+// setRules(rules);
}
private boolean doLoadColorSettings(String name) {
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 9309aaf..6fbe25a 100644
--- a/src/main/java/org/apache/log4j/chainsaw/prefs/SettingsManager.java
+++ b/src/main/java/org/apache/log4j/chainsaw/prefs/SettingsManager.java
@@ -25,12 +25,15 @@
import java.util.Map;
import java.util.Properties;
import org.apache.commons.configuration2.AbstractConfiguration;
+import org.apache.commons.configuration2.CombinedConfiguration;
import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.builder.BasicConfigurationBuilder;
import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
+import org.apache.commons.configuration2.builder.fluent.FileBasedBuilderParameters;
import org.apache.commons.configuration2.builder.fluent.Parameters;
import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
import org.apache.commons.configuration2.ex.ConfigurationException;
+import org.apache.commons.configuration2.tree.OverrideCombiner;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -47,9 +50,14 @@
private static final SettingsManager instance = new SettingsManager();
private static final String GLOBAL_SETTINGS_FILE_NAME = "chainsaw.settings.properties";
+ private class TabSettingsData{
+ FileBasedConfigurationBuilder<PropertiesConfiguration> file;
+ CombinedConfiguration combined;
+ }
+
private PropertiesConfiguration m_configuration;
private FileBasedConfigurationBuilder<PropertiesConfiguration> m_builder;
- private Map<String,FileBasedConfigurationBuilder<PropertiesConfiguration>> m_tabSettings;
+ private Map<String,TabSettingsData> m_tabSettings;
/**
* Initialises the SettingsManager by loading the default Properties from
@@ -74,6 +82,7 @@
PropertiesConfiguration.class)
.configure(params.fileBased()
.setURL(defaultPrefs)
+ .setListDelimiterHandler(new DefaultListDelimiterHandler(','))
);
try{
@@ -110,32 +119,49 @@
}
public AbstractConfiguration getSettingsForReceiverTab(String identifier){
+ if( m_tabSettings.containsKey( identifier ) ){
+ return m_tabSettings.get( identifier ).combined;
+ }
+
+ // Override combiner: nodes in the first structure take precedence over the second
+ CombinedConfiguration combinedConfig = new CombinedConfiguration(new OverrideCombiner());
PropertiesConfiguration configuration = null;
- if( m_tabSettings.containsKey( identifier ) ){
- try{
- return m_tabSettings.get( identifier ).getConfiguration();
- }catch( ConfigurationException ex ){}
- }
-
// Either we don't contain the key, or we got an exception. Regardless,
// create a new configuration that we can use
- Parameters params = new Parameters();
+ FileBasedBuilderParameters params = new Parameters().fileBased();
File f = new File(getSettingsDirectory(), identifier + "-receiver.properties");
+ if( !f.exists() ){
+ URL defaultPrefs = this.getClass().getClassLoader()
+ .getResource("org/apache/log4j/chainsaw/prefs/logpanel.properties");
+ params.setURL(defaultPrefs);
+ }else{
+ params.setFile( f );
+ }
+
FileBasedConfigurationBuilder<PropertiesConfiguration> builder =
new FileBasedConfigurationBuilder<PropertiesConfiguration>(
PropertiesConfiguration.class)
- .configure(params.fileBased()
- .setListDelimiterHandler(
- new DefaultListDelimiterHandler(','))
- .setFile(f)
+ .configure(params
+ .setListDelimiterHandler(new DefaultListDelimiterHandler(','))
);
- m_tabSettings.put( identifier, builder );
+ TabSettingsData data = new TabSettingsData();
+ data.file = builder;
try{
- return builder.getConfiguration();
+ AbstractConfiguration config = builder.getConfiguration();
+
+ builder.getFileHandler().setFile(f);
+
+ combinedConfig.addConfiguration(config);
+ combinedConfig.addConfiguration(getGlobalConfiguration());
+
+ data.combined = combinedConfig;
+ m_tabSettings.put( identifier, data );
+
+ return combinedConfig;
}catch( ConfigurationException ex ){}
return null;
@@ -162,7 +188,7 @@
for( String key : m_tabSettings.keySet() ){
try{
- m_tabSettings.get(key).save();
+ m_tabSettings.get(key).file.save();
}catch( ConfigurationException ex ){
logger.error( "Unable to save settings for {}", key );
}
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 302135c..41d3a03 100644
--- a/src/main/resources/org/apache/log4j/chainsaw/prefs/default.properties
+++ b/src/main/resources/org/apache/log4j/chainsaw/prefs/default.properties
@@ -25,6 +25,7 @@
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
@@ -48,4 +49,4 @@
detailPaneVisible=true
highlightSearchMatchText=true
wrapMessage=true
-searchResultsVisible=true
\ No newline at end of file
+searchResultsVisible=true
diff --git a/src/main/resources/org/apache/log4j/chainsaw/prefs/logpanel.properties b/src/main/resources/org/apache/log4j/chainsaw/prefs/logpanel.properties
new file mode 100644
index 0000000..2c284e5
--- /dev/null
+++ b/src/main/resources/org/apache/log4j/chainsaw/prefs/logpanel.properties
@@ -0,0 +1,38 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# ====================================
+# 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.logTreePanelVisible=true
+logpanel.hiddenloggers=
+logpanel.wrapMsg=true
+logpanel.highlightSearchMatchText=true
+logpanel.cyclic=false
+logpanel.showMillisDeltaAsGap=false
+logpanel.searchResultsVisible=true
+logpanel.lowerPanelDividerLocation=0
+logpanel.treeDividerLocation=0
+logpanel.hiddenLoggers=
+logpanel.hiddenExpression=
+logpanel.alwaysDisplayExpression=
+