in src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java [153:441]
public Component getTableCellRendererComponent(
final JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int col) {
EventContainer container = (EventContainer) table.getModel();
LoggingEventWrapper loggingEventWrapper = container.getRow(row);
value = formatField(value, loggingEventWrapper);
TableColumn tableColumn = table.getColumnModel().getColumn(col);
int width = tableColumn.getWidth();
JLabel label = (JLabel) super.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, col);
//chainsawcolumns uses one-based indexing
int colIndex = tableColumn.getModelIndex() + 1;
//no event, use default renderer
if (loggingEventWrapper == null) {
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
}
long delta = 0;
if (row > 0) {
LoggingEventWrapper previous = eventContainer.getRow(row - 1);
long millisBetween = ChronoUnit.MILLIS.between( loggingEventWrapper.getLoggingEvent().m_timestamp, previous.getLoggingEvent().m_timestamp );
delta = Math.min(ChainsawConstants.MILLIS_DELTA_RENDERING_HEIGHT_MAX,
Math.max(0, (long) ((millisBetween) * ChainsawConstants.MILLIS_DELTA_RENDERING_FACTOR)));
}
Map matches = loggingEventWrapper.getSearchMatches();
JComponent component;
switch (colIndex) {
case ChainsawColumns.INDEX_THROWABLE_COL_NAME:
if (value instanceof String[] && ((String[]) value).length > 0) {
Style tabStyle = singleLineTextPane.getLogicalStyle();
StyleConstants.setTabSet(tabStyle, tabs);
//set the 1st tab at position 3
singleLineTextPane.setLogicalStyle(tabStyle);
//exception string is split into an array..just highlight the first line completely if anything in the exception matches if we have a match for the exception field
Set exceptionMatches = (Set) matches.get(LoggingEventFieldResolver.EXCEPTION_FIELD);
if (exceptionMatches != null && exceptionMatches.size() > 0) {
singleLineTextPane.setText(((String[]) value)[0]);
boldAll((StyledDocument) singleLineTextPane.getDocument());
} else {
singleLineTextPane.setText(((String[]) value)[0]);
}
} else {
singleLineTextPane.setText("");
}
layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
component = generalPanel;
break;
case ChainsawColumns.INDEX_LOGGER_COL_NAME:
String logger = value.toString();
int startPos = -1;
for (int i = 0; i < loggerPrecision; i++) {
startPos = logger.indexOf(".", startPos + 1);
if (startPos < 0) {
break;
}
}
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:
//timestamp matches contain the millis..not the display text..just highlight if we have a match for the timestamp field
Set timestampMatches = (Set) matches.get(LoggingEventFieldResolver.TIMESTAMP_FIELD);
if (timestampMatches != null && timestampMatches.size() > 0) {
singleLineTextPane.setText(value.toString());
boldAll((StyledDocument) singleLineTextPane.getDocument());
} 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();
JTextPane textPane = wrap ? multiLineTextPane : singleLineTextPane;
JComponent textPaneContainer = wrap ? multiLinePanel : generalPanel;
textPane.setText(thisString);
if (colIndex == ChainsawColumns.INDEX_LOG4J_MARKER_COL_NAME) {
//property keys are set as all uppercase
setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.PROP_FIELD + ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE.toUpperCase()), (StyledDocument) textPane.getDocument());
} else {
setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.MSG_FIELD), (StyledDocument) textPane.getDocument());
}
textPaneContainer.removeAll();
if (delta > 0 && logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
JPanel newPanel = new JPanel();
newPanel.setOpaque(true);
newPanel.setBackground(applicationPreferenceModel.getDeltaColor());
newPanel.setPreferredSize(new Dimension(width, (int) delta));
textPaneContainer.add(newPanel, BorderLayout.NORTH);
}
textPaneContainer.add(textPane, BorderLayout.SOUTH);
if (delta == 0 || !logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
if (col == 0) {
textPane.setBorder(getLeftBorder(isSelected, delta));
} else if (col == table.getColumnCount() - 1) {
textPane.setBorder(getRightBorder(isSelected, delta));
} else {
textPane.setBorder(getMiddleBorder(isSelected, delta));
}
} else {
if (col == 0) {
textPane.setBorder(getLeftBorder(isSelected, 0));
} else if (col == table.getColumnCount() - 1) {
textPane.setBorder(getRightBorder(isSelected, 0));
} else {
textPane.setBorder(getMiddleBorder(isSelected, 0));
}
}
int currentMarkerHeight = loggingEventWrapper.getMarkerHeight();
int currentMsgHeight = loggingEventWrapper.getMsgHeight();
int newRowHeight = ChainsawConstants.DEFAULT_ROW_HEIGHT;
boolean setHeight = false;
if (wrap) {
/*
calculating the height -would- be the correct thing to do, but setting the size to screen size works as well and
doesn't incur massive overhead, like calculateHeight does
Map paramMap = new HashMap();
paramMap.put(TextAttribute.FONT, multiLineTextPane.getFont());
int calculatedHeight = calculateHeight(thisString, width, paramMap);
*/
//instead, set size to max height
textPane.setSize(new Dimension(width, maxHeight));
int multiLinePanelPrefHeight = textPaneContainer.getPreferredSize().height;
newRowHeight = Math.max(ChainsawConstants.DEFAULT_ROW_HEIGHT, multiLinePanelPrefHeight);
}
if (!wrap && logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
textPane.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) {
loggingEventWrapper.setMarkerHeight(newRowHeight);
if (newRowHeight != currentMarkerHeight && newRowHeight >= loggingEventWrapper.getMsgHeight()) {
setHeight = true;
}
}
if (colIndex == ChainsawColumns.INDEX_MESSAGE_COL_NAME) {
loggingEventWrapper.setMsgHeight(newRowHeight);
if (newRowHeight != currentMsgHeight && newRowHeight >= loggingEventWrapper.getMarkerHeight()) {
setHeight = true;
}
}
if (setHeight) {
table.setRowHeight(row, newRowHeight);
}
component = textPaneContainer;
break;
case ChainsawColumns.INDEX_LEVEL_COL_NAME:
if (levelUseIcons) {
levelTextPane.setText("");
levelTextPane.insertIcon(iconMap.get(value.toString()));
if (!toolTipsVisible) {
levelTextPane.setToolTipText(value.toString());
}
} else {
levelTextPane.setText(value.toString());
setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.LEVEL_FIELD), (StyledDocument) levelTextPane.getDocument());
if (!toolTipsVisible) {
levelTextPane.setToolTipText(null);
}
}
if (toolTipsVisible) {
levelTextPane.setToolTipText(label.getToolTipText());
}
levelTextPane.setForeground(label.getForeground());
levelTextPane.setBackground(label.getBackground());
layoutRenderingPanel(levelPanel, levelTextPane, delta, isSelected, width, col, table);
component = levelPanel;
break;
//remaining entries are properties
default:
Set propertySet = loggingEventWrapper.getPropertyKeySet();
String headerName = tableColumn.getHeaderValue().toString().toLowerCase();
String thisProp = null;
//find the property in the property set...case-sensitive
for (Object aPropertySet : propertySet) {
String entry = aPropertySet.toString();
if (entry.equalsIgnoreCase(headerName)) {
thisProp = entry;
break;
}
}
if (thisProp != null) {
String propKey = LoggingEventFieldResolver.PROP_FIELD + thisProp.toUpperCase();
Set propKeyMatches = (Set) matches.get(propKey);
singleLineTextPane.setText(loggingEventWrapper.getLoggingEvent().getProperty(thisProp));
setHighlightAttributesInternal(propKeyMatches, (StyledDocument) singleLineTextPane.getDocument());
} else {
singleLineTextPane.setText("");
}
layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
component = generalPanel;
break;
}
Color background;
Color foreground;
Rule loggerRule = colorizer.getLoggerRule();
AbstractConfiguration configuration = SettingsManager.getInstance().getGlobalConfiguration();
//use logger colors in table instead of event colors if event passes logger rule
if (loggerRule != null && loggerRule.evaluate(loggingEventWrapper.getLoggingEvent(), null)) {
background = configuration.get(Color.class, "searchBackgroundColor", ChainsawConstants.FIND_LOGGER_BACKGROUND);
foreground = configuration.get(Color.class, "searchForegroundColor", ChainsawConstants.FIND_LOGGER_FOREGROUND);
} else {
if (colorizeSearch && !configuration.getBoolean("bypassSearchColors", false)) {
background = loggingEventWrapper.isSearchMatch() ? configuration.get(Color.class, "searchBackgroundColor", ChainsawConstants.FIND_LOGGER_BACKGROUND) : loggingEventWrapper.getBackground();
foreground = loggingEventWrapper.isSearchMatch() ? configuration.get(Color.class, "searchForegroundColor", ChainsawConstants.FIND_LOGGER_FOREGROUND) : loggingEventWrapper.getForeground();
} else {
background = loggingEventWrapper.getBackground();
foreground = loggingEventWrapper.getForeground();
}
}
/**
* Colourize background based on row striping if the event still has default foreground and background color
*/
if (background.equals(ChainsawConstants.COLOR_DEFAULT_BACKGROUND) && foreground.equals(ChainsawConstants.COLOR_DEFAULT_FOREGROUND) && (row % 2) != 0) {
background = configuration.get(Color.class, "alternatingColorBackground", ChainsawConstants.COLOR_ODD_ROW_BACKGROUND);
foreground = configuration.get(Color.class, "alternatingColorForeground", ChainsawConstants.COLOR_ODD_ROW_FOREGROUND);
}
component.setBackground(background);
component.setForeground(foreground);
//update the background & foreground of the jtextpane using styles
if (multiLineTextPane != null) {
updateColors(multiLineTextPane, background, foreground);
}
updateColors(levelTextPane, background, foreground);
updateColors(singleLineTextPane, background, foreground);
return component;
}