Author: sdeboy
Date: Tue Apr 20 08:14:47 2010
New Revision: 935828
URL: http://svn.apache.org/viewvc?rev=935828&view=rev
Log:
Fully implement multi-line row rendering without hacks
- embed jtextarea in a boxlayout to get multi-line rendering to work correctly
- wrap other renderers (level, general renderer) in boxlayout as well to ensure alignment of all columns
Modified:
logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java
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=935828&r1=935827&r2=935828&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 Tue Apr 20 08:14:47 2010
@@ -19,8 +19,8 @@ package org.apache.log4j.chainsaw;
import java.awt.Color;
import java.awt.Component;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
+import java.awt.Dimension;
+import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextAttribute;
import java.awt.font.TextLayout;
@@ -36,9 +36,11 @@ import java.util.Set;
import java.util.TimeZone;
import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JLabel;
+import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;
@@ -66,7 +68,6 @@ public class TableColorizingRenderer ext
private static final DateFormat DATE_FORMATTER = new SimpleDateFormat(Constants.SIMPLE_TIME_PATTERN);
private static final Map iconMap = LevelIconFactory.getInstance().getLevelToIconMap();
private RuleColorizer colorizer;
- private final JLabel levelComponent = new JLabel();
private boolean levelUseIcons = false;
private boolean wrapMsg = false;
private DateFormat dateFormatInUse = DATE_FORMATTER;
@@ -75,8 +76,8 @@ public class TableColorizingRenderer ext
private String dateFormatTZ;
private boolean useRelativeTimes = false;
private long relativeTimestampBase;
+
private static int borderWidth = 2;
- private JTextArea msgRenderer = new JTextArea();
private static Color borderColor = (Color)UIManager.get("Table.selectionBackground");
private static final Border LEFT_BORDER = BorderFactory.createMatteBorder(borderWidth, borderWidth, borderWidth, 0, borderColor);
@@ -87,18 +88,38 @@ public class TableColorizingRenderer ext
private static final Border MIDDLE_EMPTY_BORDER = BorderFactory.createEmptyBorder(borderWidth, 0, borderWidth, 0);
private static final Border RIGHT_EMPTY_BORDER = BorderFactory.createEmptyBorder(borderWidth, 0, borderWidth, borderWidth);
+ private final JTextArea msgTextArea = new JTextArea();
+ private final JLabel levelLabel = new JLabel();
+ private final JLabel generalLabel = new JLabel();
+
+ private final JPanel msgPanel = new JPanel();
+ private final JPanel generalPanel = new JPanel();
+ private final JPanel levelPanel = new JPanel();
/**
* Creates a new TableColorizingRenderer object.
*/
public TableColorizingRenderer(RuleColorizer colorizer) {
- this.colorizer = colorizer;
-
- levelComponent.setOpaque(true);
- levelComponent.setVerticalAlignment(SwingConstants.TOP);
+ msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.Y_AXIS));
+ generalPanel.setLayout(new BoxLayout(generalPanel, BoxLayout.Y_AXIS));
+ levelPanel.setLayout(new BoxLayout(levelPanel, BoxLayout.Y_AXIS));
+
+ msgPanel.setAlignmentX(TOP_ALIGNMENT);
+ generalPanel.setAlignmentX(TOP_ALIGNMENT);
+ levelPanel.setAlignmentX(TOP_ALIGNMENT);
+
+ generalLabel.setVerticalAlignment(SwingConstants.TOP);
+ levelLabel.setVerticalAlignment(SwingConstants.TOP);
+ levelLabel.setOpaque(true);
+ levelLabel.setText("");
+
+ msgTextArea.setMargin(null);
+ msgTextArea.setEditable(false);
+
+ msgPanel.add(msgTextArea);
+ generalPanel.add(generalLabel);
+ levelPanel.add(levelLabel);
- levelComponent.setText("");
- levelComponent.setVerticalAlignment(SwingConstants.TOP);
- msgRenderer.setEditable(false);
+ this.colorizer = colorizer;
}
public void setToolTipsVisible(boolean toolTipsVisible) {
@@ -110,23 +131,12 @@ public class TableColorizingRenderer ext
int row, int col) {
value = formatField(value);
- JLabel labelRenderer = (JLabel)super.getTableCellRendererComponent(table, value,
+ JLabel label = (JLabel)super.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, col);
- labelRenderer.setVerticalAlignment(SwingConstants.TOP);
- JComponent component;
TableColumn tableColumn = table.getColumnModel().getColumn(col);
//chainsawcolumns uses one-based indexing
int colIndex = tableColumn.getModelIndex() + 1;
- if(colIndex == ChainsawColumns.INDEX_MESSAGE_COL_NAME) {
- msgRenderer.setFont(labelRenderer.getFont());
- component = msgRenderer;
- } else if (colIndex == ChainsawColumns.INDEX_LEVEL_COL_NAME) {
- component = levelComponent;
- } else {
- component = labelRenderer;
- }
-
EventContainer container = (EventContainer) table.getModel();
ExtendedLoggingEvent loggingEvent = container.getRow(row);
//no event, use default renderer
@@ -134,21 +144,17 @@ public class TableColorizingRenderer ext
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
}
+ JComponent component = null;
switch (colIndex) {
- case ChainsawColumns.INDEX_ID_COL_NAME:
- labelRenderer.setText(value.toString());
- break;
-
case ChainsawColumns.INDEX_THROWABLE_COL_NAME:
if (value instanceof String[] && ((String[])value).length > 0){
- labelRenderer.setText(((String[]) value)[0]);
+ generalLabel.setText(((String[]) value)[0]);
+ } else {
+ generalLabel.setText("");
}
+ component = generalPanel;
break;
-
case ChainsawColumns.INDEX_LOGGER_COL_NAME:
- if (loggerPrecision == 0) {
- break;
- }
String logger = value.toString();
int startPos = -1;
@@ -158,9 +164,10 @@ public class TableColorizingRenderer ext
break;
}
}
-
- labelRenderer.setText(logger.substring(startPos + 1));
+ generalLabel.setText(logger.substring(startPos + 1));
+ component = generalPanel;
break;
+ case ChainsawColumns.INDEX_ID_COL_NAME:
case ChainsawColumns.INDEX_LOG4J_MARKER_COL_NAME:
case ChainsawColumns.INDEX_CLASS_COL_NAME:
case ChainsawColumns.INDEX_FILE_COL_NAME:
@@ -169,53 +176,57 @@ public class TableColorizingRenderer ext
case ChainsawColumns.INDEX_THREAD_COL_NAME:
case ChainsawColumns.INDEX_TIMESTAMP_COL_NAME:
case ChainsawColumns.INDEX_METHOD_COL_NAME:
- labelRenderer.setText(value.toString());
+ generalLabel.setText(value.toString());
+ component = generalPanel;
break;
case ChainsawColumns.INDEX_MESSAGE_COL_NAME:
String string = value.toString().trim();
- msgRenderer.setLineWrap(wrapMsg);
- msgRenderer.setWrapStyleWord(wrapMsg);
- if (wrapMsg && string.length() > 0) {
- int width = tableColumn.getWidth();
- int tableRowHeight = table.getRowHeight(row);
+ int width = tableColumn.getWidth();
+ msgTextArea.setLineWrap(wrapMsg);
+ msgTextArea.setWrapStyleWord(wrapMsg);
+ msgTextArea.setFont(label.getFont());
+ msgTextArea.setText(string);
+ int tableRowHeight = table.getRowHeight(row);
+ if (wrapMsg) {
Map paramMap = new HashMap();
- //using font here causes text to be truncated (height is too small)..using family & a larger size (to ensure all text is displayed) instead
- paramMap.put(TextAttribute.FAMILY, labelRenderer.getFont().getFamily());
- //set size to size + 1.5 (will make sure long entries aren't truncated)
- paramMap.put(TextAttribute.SIZE, new Float(labelRenderer.getFont().getSize() + 1.5));
-
- int preferredHeight = calculateHeight(table.getGraphics(), string, width, paramMap);
- if(preferredHeight != tableRowHeight) {
- table.setRowHeight(row, preferredHeight);
+ paramMap.put(TextAttribute.FONT, msgTextArea.getFont());
+ int calculatedHeight = calculateHeight(string, width, paramMap);
+ msgTextArea.setSize(new Dimension(width, calculatedHeight));
+ int msgPanelPrefHeight = msgPanel.getPreferredSize().height;
+ if(tableRowHeight < msgPanelPrefHeight/* && calculatedHeight > tableRowHeight*/) {
+ table.setRowHeight(row, Math.max(ChainsawConstants.DEFAULT_ROW_HEIGHT, msgPanelPrefHeight));
}
- msgRenderer.setText(string);
} else {
- msgRenderer.setText(string);
+ msgTextArea.setSize(new Dimension(width, ChainsawConstants.DEFAULT_ROW_HEIGHT));
+ int msgPanelPrefHeight = msgPanel.getPreferredSize().height;
+ table.setRowHeight(Math.max(ChainsawConstants.DEFAULT_ROW_HEIGHT, msgPanelPrefHeight));
}
- break;
+ component = msgPanel;
+ break;
case ChainsawColumns.INDEX_LEVEL_COL_NAME:
if (levelUseIcons) {
- levelComponent.setIcon((Icon) iconMap.get(value.toString()));
+ levelLabel.setIcon((Icon) iconMap.get(value.toString()));
- if (levelComponent.getIcon() != null) {
- levelComponent.setText("");
+ if (levelLabel.getIcon() != null) {
+ levelLabel.setText("");
}
if (!toolTipsVisible) {
- levelComponent.setToolTipText(value.toString());
+ levelLabel.setToolTipText(value.toString());
}
} else {
- levelComponent.setIcon(null);
- levelComponent.setText(value.toString());
+ levelLabel.setIcon(null);
+ levelLabel.setText(value.toString());
if (!toolTipsVisible) {
- levelComponent.setToolTipText(null);
+ levelLabel.setToolTipText(null);
}
}
if (toolTipsVisible) {
- levelComponent.setToolTipText(labelRenderer.getToolTipText());
+ levelLabel.setToolTipText(label.getToolTipText());
}
- levelComponent.setForeground(labelRenderer.getForeground());
- levelComponent.setBackground(labelRenderer.getBackground());
+ levelLabel.setForeground(label.getForeground());
+ levelLabel.setBackground(label.getBackground());
+ component = levelPanel;
break;
//remaining entries are properties
@@ -232,8 +243,11 @@ public class TableColorizingRenderer ext
}
}
if (thisProp != null) {
- labelRenderer.setText(loggingEvent.getProperty(headerName));
+ generalLabel.setText(loggingEvent.getProperty(headerName));
+ } else {
+ generalLabel.setText("");
}
+ component = generalPanel;
break;
}
@@ -263,6 +277,14 @@ public class TableColorizingRenderer ext
component.setBackground(background);
component.setForeground(foreground);
+ //set the colors of the components inside 'component'
+ msgTextArea.setBackground(background);
+ msgTextArea.setForeground(foreground);
+ levelLabel.setBackground(background);
+ levelLabel.setForeground(foreground);
+ generalLabel.setBackground(background);
+ generalLabel.setForeground(foreground);
+
if (isSelected) {
if (col == 0) {
component.setBorder(LEFT_BORDER);
@@ -280,7 +302,6 @@ public class TableColorizingRenderer ext
component.setBorder(MIDDLE_EMPTY_BORDER);
}
}
-
return component;
}
@@ -366,9 +387,12 @@ public class TableColorizingRenderer ext
useRelativeTimes = false;
}
- private int calculateHeight(Graphics g, String string, int width, Map paramMap) {
+ private int calculateHeight(String string, int width, Map paramMap) {
+ if (string.trim().length() == 0) {
+ return ChainsawConstants.DEFAULT_ROW_HEIGHT;
+ }
AttributedCharacterIterator paragraph = new AttributedString(string, paramMap).getIterator();
- LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, ((Graphics2D)g).getFontRenderContext());
+ LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, new FontRenderContext(null, true, true));
float height = 0;
lineMeasurer.setPosition(paragraph.getBeginIndex());
TextLayout layout;
@@ -377,7 +401,6 @@ public class TableColorizingRenderer ext
float layoutHeight = layout.getAscent() + layout.getDescent() + layout.getLeading();
height += layoutHeight;
}
- //pad total by 4 or default row height
- return Math.max(ChainsawConstants.DEFAULT_ROW_HEIGHT, (int) height + 4);
+ return Math.max(ChainsawConstants.DEFAULT_ROW_HEIGHT, (int) height);
}
}
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.