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>
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.