You are viewing a plain text version of this content. The canonical link for it is here.
Posted to general@logging.apache.org by sd...@apache.org on 2010/09/15 10:20:35 UTC
svn commit: r997222 - in /logging/chainsaw/trunk/src/main:
java/org/apache/log4j/chainsaw/ resources/org/apache/log4j/chainsaw/help/
Author: sdeboy
Date: Wed Sep 15 08:20:34 2010
New Revision: 997222
URL: http://svn.apache.org/viewvc?rev=997222&view=rev
Log:
Updated table rendering logic when in line-wrap mode
Updated row selection logic (goto/search) to make sure event is on the screen
Capped the event time delta rendering in the table to a max of 50 pixels tall
Modified:
logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/JSortTable.java
logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java
logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanelPreferenceModel.java
logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java
logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html
Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/JSortTable.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/JSortTable.java?rev=997222&r1=997221&r2=997222&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/JSortTable.java (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/JSortTable.java Wed Sep 15 08:20:34 2010
@@ -41,6 +41,7 @@ public class JSortTable extends JTable i
protected int sortedColumnIndex = -1;
protected boolean sortedColumnAscending = true;
private String sortedColumn;
+ private int lastSelectedColumn = -1;
public JSortTable() {
super();
@@ -63,6 +64,19 @@ public class JSortTable extends JTable i
initSortHeader();
}
+ public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
+ //selection of the msg field causes rendering to flash...skip over it
+ int colToSelect = columnIndex;
+ //CHAINSAW columns are 1-based indexes
+ if (columnIndex + 1 == ChainsawColumns.INDEX_MESSAGE_COL_NAME) {
+ colToSelect = lastSelectedColumn < columnIndex ? columnIndex + 1 : columnIndex - 1;
+ super.changeSelection(rowIndex, colToSelect, toggle, extend);
+ } else {
+ super.changeSelection(rowIndex, columnIndex, toggle, extend);
+ }
+ lastSelectedColumn = colToSelect;
+ }
+
protected void initSortHeader() {
JTableHeader header = getTableHeader();
header.setDefaultRenderer(new SortHeaderRenderer());
@@ -95,13 +109,14 @@ public class JSortTable extends JTable i
//Allow synchronous updates if already on the EDT
public void scrollTo(final int row, final int col) {
+ final int currentRow = getSelectedRow();
SwingHelper.invokeOnEDT(new Runnable() {
public void run() {
if ((row > -1) && (row < getRowCount())) {
try {
//get the requested row off of the bottom and top of the screen by making the 5 rows around the requested row visible
- int currentRow = getSelectedRow();
- //if new past current row, scroll to display the 5th row past new selected row
+ //if new past current row, scroll to display the 20th row past new selected row
+ scrollRectToVisible(getCellRect(row, col, true));
if (row > currentRow) {
scrollRectToVisible(getCellRect(row + 5, col, true));
}
Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java?rev=997222&r1=997221&r2=997222&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java Wed Sep 15 08:20:34 2010
@@ -644,6 +644,8 @@ public class LogPanel extends DockablePa
*/
tableModel = new ChainsawCyclicBufferTableModel(cyclicBufferSize, colorizer);
table = new JSortTable(tableModel);
+ table.setColumnSelectionAllowed(false);
+ table.setRowSelectionAllowed(true);
//we've mapped f2, shift f2 and ctrl-f2 to marker-related actions, unmap them from the table
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("F2"), "none");
@@ -3276,6 +3278,7 @@ public class LogPanel extends DockablePa
JTextField textField = new JTextField();
Set cellEditorListeners = new HashSet();
private ExtendedLoggingEvent currentEvent;
+ private final Object mutex = new Object();
public Object getCellEditorValue()
{
@@ -3302,7 +3305,12 @@ public class LogPanel extends DockablePa
}
tableModel.fireRowUpdated(table.getSelectedRow(), true);
ChangeEvent event = new ChangeEvent(table);
- for (Iterator iter = cellEditorListeners.iterator();iter.hasNext();) {
+ Set cellEditorListenersCopy;
+ synchronized(mutex) {
+ cellEditorListenersCopy = new HashSet(cellEditorListeners);
+ }
+
+ for (Iterator iter = cellEditorListenersCopy.iterator();iter.hasNext();) {
((CellEditorListener)iter.next()).editingStopped(event);
}
return true;
@@ -3310,20 +3318,29 @@ public class LogPanel extends DockablePa
public void cancelCellEditing()
{
+ Set cellEditorListenersCopy;
+ synchronized(mutex) {
+ cellEditorListenersCopy = new HashSet(cellEditorListeners);
+ }
+
ChangeEvent event = new ChangeEvent(table);
- for (Iterator iter = cellEditorListeners.iterator();iter.hasNext();) {
+ for (Iterator iter = cellEditorListenersCopy.iterator();iter.hasNext();) {
((CellEditorListener)iter.next()).editingCanceled(event);
}
}
public void addCellEditorListener(CellEditorListener l)
{
- cellEditorListeners.add(l);
+ synchronized(mutex) {
+ cellEditorListeners.add(l);
+ }
}
public void removeCellEditorListener(CellEditorListener l)
{
- cellEditorListeners.remove(l);
+ synchronized(mutex) {
+ cellEditorListeners.remove(l);
+ }
}
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanelPreferenceModel.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanelPreferenceModel.java?rev=997222&r1=997221&r2=997222&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanelPreferenceModel.java (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanelPreferenceModel.java Wed Sep 15 08:20:34 2010
@@ -254,6 +254,7 @@ public class LogPanelPreferenceModel imp
setVisibleColumns(model.getVisibleColumns());
setHiddenLoggers(model.getHiddenLoggers());
setHiddenExpression(model.getHiddenExpression());
+ setShowMillisDeltaAsGap(model.isShowMillisDeltaAsGap());
setClearTableExpression(model.getClearTableExpression());
}
Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java?rev=997222&r1=997221&r2=997222&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java Wed Sep 15 08:20:34 2010
@@ -17,6 +17,7 @@
package org.apache.log4j.chainsaw;
+import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
@@ -104,9 +105,9 @@ public class TableColorizingRenderer ext
private final JTextPane levelTextPane = new JTextPane();
private JTextPane singleLineTextPane = new JTextPane();
- private final JPanel multiLinePanel = new JPanel();
- private final JPanel generalPanel = new JPanel();
- private final JPanel levelPanel = new JPanel();
+ private final JPanel multiLinePanel = new JPanel(new BorderLayout());
+ private final JPanel generalPanel = new JPanel(new BorderLayout());
+ private final JPanel levelPanel = new JPanel(new BorderLayout());
private ApplicationPreferenceModel applicationPreferenceModel;
private JTextPane multiLineTextPane;
private MutableAttributeSet boldAttributeSet;
@@ -143,7 +144,6 @@ public class TableColorizingRenderer ext
levelTextPane.setOpaque(true);
levelTextPane.setText("");
- generalPanel.add(singleLineTextPane);
levelPanel.add(levelTextPane);
this.colorizer = colorizer;
@@ -172,6 +172,7 @@ public class TableColorizingRenderer ext
ExtendedLoggingEvent loggingEvent = container.getRow(row);
value = formatField(value, row, loggingEvent);
TableColumn tableColumn = table.getColumnModel().getColumn(col);
+ int width = tableColumn.getWidth();
JLabel label = (JLabel)super.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, col);
@@ -186,7 +187,7 @@ public class TableColorizingRenderer ext
if (row > 0) {
LoggingEvent previous = eventContainer.getRow(row - 1);
float deltaFactor = .002F;
- delta = (long) ((loggingEvent.getTimeStamp() - previous.getTimeStamp()) * deltaFactor);
+ delta = Math.min(50, Math.max(0, (long) ((loggingEvent.getTimeStamp() - previous.getTimeStamp()) * deltaFactor)));
}
Map matches = loggingEvent.getSearchMatches();
@@ -210,6 +211,7 @@ public class TableColorizingRenderer ext
} else {
singleLineTextPane.setText("");
}
+ layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
component = generalPanel;
break;
case ChainsawColumns.INDEX_LOGGER_COL_NAME:
@@ -222,38 +224,45 @@ public class TableColorizingRenderer ext
break;
}
}
- singleLineTextPane.setText(logger.substring(startPos + 1));
- setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.LOGGER_FIELD), (StyledDocument) singleLineTextPane.getDocument());
- component = generalPanel;
+ singleLineTextPane.setText(logger.substring(startPos + 1));
+ setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.LOGGER_FIELD), (StyledDocument) singleLineTextPane.getDocument());
+ layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
+ component = generalPanel;
break;
case ChainsawColumns.INDEX_ID_COL_NAME:
singleLineTextPane.setText(value.toString());
setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.PROP_FIELD + "LOG4JID"), (StyledDocument) singleLineTextPane.getDocument());
+ layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
component = generalPanel;
break;
case ChainsawColumns.INDEX_CLASS_COL_NAME:
singleLineTextPane.setText(value.toString());
setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.CLASS_FIELD), (StyledDocument) singleLineTextPane.getDocument());
+ layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
component = generalPanel;
break;
case ChainsawColumns.INDEX_FILE_COL_NAME:
singleLineTextPane.setText(value.toString());
setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.FILE_FIELD), (StyledDocument) singleLineTextPane.getDocument());
+ layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
component = generalPanel;
break;
case ChainsawColumns.INDEX_LINE_COL_NAME:
singleLineTextPane.setText(value.toString());
setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.LINE_FIELD), (StyledDocument) singleLineTextPane.getDocument());
+ layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
component = generalPanel;
break;
case ChainsawColumns.INDEX_NDC_COL_NAME:
singleLineTextPane.setText(value.toString());
setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.NDC_FIELD), (StyledDocument) singleLineTextPane.getDocument());
+ layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
component = generalPanel;
break;
case ChainsawColumns.INDEX_THREAD_COL_NAME:
singleLineTextPane.setText(value.toString());
setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.THREAD_FIELD), (StyledDocument) singleLineTextPane.getDocument());
+ layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
component = generalPanel;
break;
case ChainsawColumns.INDEX_TIMESTAMP_COL_NAME:
@@ -265,18 +274,19 @@ public class TableColorizingRenderer ext
} else {
singleLineTextPane.setText(value.toString());
}
+ layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
component = generalPanel;
break;
case ChainsawColumns.INDEX_METHOD_COL_NAME:
singleLineTextPane.setText(value.toString());
setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.METHOD_FIELD), (StyledDocument) singleLineTextPane.getDocument());
+ layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
component = generalPanel;
break;
case ChainsawColumns.INDEX_LOG4J_MARKER_COL_NAME:
case ChainsawColumns.INDEX_MESSAGE_COL_NAME:
String thisString = value.toString().trim();
multiLineTextPane.setText(thisString);
- int width = tableColumn.getWidth();
if (colIndex == ChainsawColumns.INDEX_LOG4J_MARKER_COL_NAME) {
//property keys are set as all uppercase
@@ -285,7 +295,36 @@ public class TableColorizingRenderer ext
setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.MSG_FIELD), (StyledDocument) multiLineTextPane.getDocument());
}
multiLinePanel.removeAll();
- multiLinePanel.add(multiLineTextPane);
+ if (delta > 0 && logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
+ JPanel newPanel = new JPanel();
+ newPanel.setOpaque(true);
+ newPanel.setBackground(getDeltaColor());
+ newPanel.setPreferredSize(new Dimension(width, (int) delta));
+ multiLinePanel.add(newPanel, BorderLayout.NORTH);
+ }
+ multiLinePanel.add(multiLineTextPane, BorderLayout.SOUTH);
+
+ if (delta == 0 || !logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
+ if (col == 0) {
+ multiLineTextPane.setBorder(getLeftBorder(isSelected, delta));
+ } else if (col == table.getColumnCount() - 1) {
+ multiLineTextPane.setBorder(getRightBorder(isSelected, delta));
+ } else {
+ multiLineTextPane.setBorder(getMiddleBorder(isSelected, delta));
+ }
+ } else {
+ if (col == 0) {
+ multiLineTextPane.setBorder(getLeftBorder(isSelected, 0));
+ } else if (col == table.getColumnCount() - 1) {
+ multiLineTextPane.setBorder(getRightBorder(isSelected, 0));
+ } else {
+ multiLineTextPane.setBorder(getMiddleBorder(isSelected, 0));
+ }
+ }
+ int currentMarkerHeight = loggingEvent.getMarkerHeight();
+ int currentMsgHeight = loggingEvent.getMsgHeight();
+ int newRowHeight = ChainsawConstants.DEFAULT_ROW_HEIGHT;
+ boolean setHeight = false;
if (wrap) {
/*
@@ -298,29 +337,32 @@ public class TableColorizingRenderer ext
*/
//instead, set size to max height
multiLineTextPane.setSize(new Dimension(width, maxHeight));
- boolean setHeight = false;
int multiLinePanelPrefHeight = multiLinePanel.getPreferredSize().height;
- int newRowHeight = Math.max(ChainsawConstants.DEFAULT_ROW_HEIGHT, multiLinePanelPrefHeight);
- if (colIndex == ChainsawColumns.INDEX_LOG4J_MARKER_COL_NAME) {
- int currentMarkerHeight = loggingEvent.getMarkerHeight();
- loggingEvent.setMarkerHeight(newRowHeight);
- if (newRowHeight != currentMarkerHeight && newRowHeight >= loggingEvent.getMsgHeight()) {
- setHeight = true;
- }
- }
+ newRowHeight = Math.max(ChainsawConstants.DEFAULT_ROW_HEIGHT, multiLinePanelPrefHeight);
- if (colIndex == ChainsawColumns.INDEX_MESSAGE_COL_NAME) {
- int currentMsgHeight = loggingEvent.getMsgHeight();
- loggingEvent.setMsgHeight(newRowHeight);
- if (newRowHeight != currentMsgHeight && newRowHeight >= loggingEvent.getMarkerHeight()) {
- setHeight = true;
- }
- }
- if (setHeight) {
- table.setRowHeight(row, newRowHeight);
+ }
+ if (!wrap && logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
+ multiLineTextPane.setSize(new Dimension(Integer.MAX_VALUE, ChainsawConstants.DEFAULT_ROW_HEIGHT));
+ newRowHeight = (int) (ChainsawConstants.DEFAULT_ROW_HEIGHT + delta);
+ }
+
+ if (colIndex == ChainsawColumns.INDEX_LOG4J_MARKER_COL_NAME) {
+ loggingEvent.setMarkerHeight(newRowHeight);
+ if (newRowHeight != currentMarkerHeight && newRowHeight >= loggingEvent.getMsgHeight()) {
+ setHeight = true;
}
+ }
+ if (colIndex == ChainsawColumns.INDEX_MESSAGE_COL_NAME) {
+ loggingEvent.setMsgHeight(newRowHeight);
+ if (newRowHeight != currentMsgHeight && newRowHeight >= loggingEvent.getMarkerHeight()) {
+ setHeight = true;
+ }
}
+ if (setHeight) {
+ table.setRowHeight(row, newRowHeight);
+ }
+
component = multiLinePanel;
break;
case ChainsawColumns.INDEX_LEVEL_COL_NAME:
@@ -342,6 +384,7 @@ public class TableColorizingRenderer ext
}
levelTextPane.setForeground(label.getForeground());
levelTextPane.setBackground(label.getBackground());
+ layoutRenderingPanel(levelPanel, levelTextPane, delta, isSelected, width, col, table);
component = levelPanel;
break;
@@ -366,6 +409,7 @@ public class TableColorizingRenderer ext
} else {
singleLineTextPane.setText("");
}
+ layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
component = generalPanel;
break;
}
@@ -403,17 +447,38 @@ public class TableColorizingRenderer ext
updateColors(levelTextPane, background, foreground);
updateColors(singleLineTextPane, background, foreground);
- if (col == 0) {
- component.setBorder(getLeftBorder(isSelected, delta));
- } else if (col == table.getColumnCount() - 1) {
- component.setBorder(getRightBorder(isSelected, delta));
- } else {
- component.setBorder(getMiddleBorder(isSelected, delta));
- }
-
return component;
}
+ private void layoutRenderingPanel(JComponent container, JComponent bottomComponent, long delta, boolean isSelected,
+ int width, int col, JTable table) {
+ container.removeAll();
+ if (delta == 0 || !logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
+ if (col == 0) {
+ bottomComponent.setBorder(getLeftBorder(isSelected, delta));
+ } else if (col == table.getColumnCount() - 1) {
+ bottomComponent.setBorder(getRightBorder(isSelected, delta));
+ } else {
+ bottomComponent.setBorder(getMiddleBorder(isSelected, delta));
+ }
+ } else {
+ JPanel newPanel = new JPanel();
+ newPanel.setOpaque(true);
+ newPanel.setBackground(getDeltaColor());
+ newPanel.setPreferredSize(new Dimension(width, (int) delta));
+ container.add(newPanel, BorderLayout.NORTH);
+ if (col == 0) {
+ bottomComponent.setBorder(getLeftBorder(isSelected, 0));
+ } else if (col == table.getColumnCount() - 1) {
+ bottomComponent.setBorder(getRightBorder(isSelected, 0));
+ } else {
+ bottomComponent.setBorder(getMiddleBorder(isSelected, 0));
+ }
+ }
+
+ container.add(bottomComponent, BorderLayout.SOUTH);
+ }
+
private Border getLeftBorder(boolean isSelected, long delta) {
Border LEFT_BORDER = BorderFactory.createMatteBorder(borderWidth, borderWidth, borderWidth, 0, borderColor);
Border LEFT_EMPTY_BORDER = BorderFactory.createEmptyBorder(borderWidth, borderWidth, borderWidth, 0);
Modified: logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html?rev=997222&r1=997221&r2=997222&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html (original)
+++ logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html Wed Sep 15 08:20:34 2010
@@ -10,6 +10,12 @@
<b>NOTE:</b> The mechanism and format used to persist settings in Chainsaw is subject to change. If you are experiencing problems displaying events in Chainsaw, please delete everything in the $user.dir/.chainsaw directory and restart Chainsaw.
<br>
<h1>2.1</h1>
+<h2>15 Sep 2010</h2>
+<ul>
+<li>Updated table rendering logic when in line-wrap mode</li>
+<li>Updated row selection logic (goto/search) to make sure event is on the screen</li>
+<li>Capped the event time delta rendering in the table to a max of 50 pixels tall</li>
+</ul>
<h2>13 Sep 2010</h2>
<ul>
<li>Added new 'Display timestamp delta between displayed events as space between rows' preference to log panel preferences screen - feature adds a gap between rows proportionate to the time delta between displayed events (off by default)</li>