1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.log4j.chainsaw;
19
20 import org.apache.log4j.chainsaw.color.RuleColorizer;
21 import org.apache.log4j.chainsaw.icons.LevelIconFactory;
22 import org.apache.log4j.helpers.Constants;
23 import org.apache.log4j.rule.Rule;
24 import org.apache.log4j.spi.LoggingEventFieldResolver;
25
26 import javax.swing.*;
27 import javax.swing.border.Border;
28 import javax.swing.table.DefaultTableCellRenderer;
29 import javax.swing.table.TableColumn;
30 import javax.swing.text.*;
31 import java.awt.*;
32 import java.text.DateFormat;
33 import java.text.SimpleDateFormat;
34 import java.util.Date;
35 import java.util.HashMap;
36 import java.util.Map;
37 import java.util.Set;
38 import java.util.TimeZone;
39
40
41
42
43
44
45
46
47
48
49 public class TableColorizingRenderer extends DefaultTableCellRenderer {
50 private static final DateFormat DATE_FORMATTER = new SimpleDateFormat(Constants.SIMPLE_TIME_PATTERN);
51 private final Map<String, Icon> iconMap;
52 private RuleColorizer colorizer;
53 private boolean levelUseIcons = false;
54 private boolean wrap = false;
55 private boolean highlightSearchMatchText;
56 private DateFormat dateFormatInUse = DATE_FORMATTER;
57 private int loggerPrecision = 0;
58 private boolean toolTipsVisible;
59 private String dateFormatTZ;
60 private boolean useRelativeTimesToFixedTime = false;
61 private long relativeTimestampBase;
62
63 private static int borderWidth = ChainsawConstants.TABLE_BORDER_WIDTH;
64
65 private final Color borderColor;
66
67 private final JTextPane levelTextPane = new JTextPane();
68 private JTextPane singleLineTextPane = new JTextPane();
69
70 private final JPanel multiLinePanel = new JPanel(new BorderLayout());
71 private final JPanel generalPanel = new JPanel(new BorderLayout());
72 private final JPanel levelPanel = new JPanel(new BorderLayout());
73 private ApplicationPreferenceModel applicationPreferenceModel;
74 private JTextPane multiLineTextPane;
75 private MutableAttributeSet boldAttributeSet;
76 private TabSet tabs;
77 private int maxHeight;
78 private boolean useRelativeTimesToPrevious;
79 private EventContainer eventContainer;
80 private LogPanelPreferenceModel logPanelPreferenceModel;
81 private SimpleAttributeSet insetAttributeSet;
82 private boolean colorizeSearch;
83
84
85
86
87 public TableColorizingRenderer(RuleColorizer colorizer, ApplicationPreferenceModel applicationPreferenceModel,
88 EventContainer eventContainer, LogPanelPreferenceModel logPanelPreferenceModel,
89 boolean colorizeSearch) {
90 this.applicationPreferenceModel = applicationPreferenceModel;
91 this.logPanelPreferenceModel = logPanelPreferenceModel;
92 this.eventContainer = eventContainer;
93 this.colorizeSearch = colorizeSearch;
94 multiLinePanel.setLayout(new BoxLayout(multiLinePanel, BoxLayout.Y_AXIS));
95 generalPanel.setLayout(new BoxLayout(generalPanel, BoxLayout.Y_AXIS));
96 levelPanel.setLayout(new BoxLayout(levelPanel, BoxLayout.Y_AXIS));
97 maxHeight = Toolkit.getDefaultToolkit().getScreenSize().height;
98
99 iconMap = new HashMap<>();
100 try {
101 iconMap.putAll(LevelIconFactory.getInstance().getLevelToIconMap());
102 } catch (IllegalStateException ise) {
103
104 }
105
106 if (UIManager.get("Table.selectionBackground") != null) {
107 borderColor = (Color) UIManager.get("Table.selectionBackground");
108 } else {
109 borderColor = Color.BLUE;
110 }
111
112 boldAttributeSet = new SimpleAttributeSet();
113 StyleConstants.setBold(boldAttributeSet, true);
114
115 insetAttributeSet = new SimpleAttributeSet();
116 StyleConstants.setLeftIndent(insetAttributeSet, 6);
117
118 int pos = 0;
119 int align = TabStop.ALIGN_LEFT;
120 int leader = TabStop.LEAD_NONE;
121 TabStop tabStop = new TabStop(pos, align, leader);
122 tabs = new TabSet(new TabStop[]{tabStop});
123
124 levelTextPane.setOpaque(true);
125 levelTextPane.setText("");
126
127 levelPanel.add(levelTextPane);
128
129 this.colorizer = colorizer;
130 multiLineTextPane = new JTextPane();
131 multiLineTextPane.setEditorKit(new StyledEditorKit());
132
133 singleLineTextPane.setEditorKit(new OneLineEditorKit());
134 levelTextPane.setEditorKit(new OneLineEditorKit());
135
136 multiLineTextPane.setEditable(false);
137 multiLineTextPane.setFont(levelTextPane.getFont());
138
139 multiLineTextPane.setParagraphAttributes(insetAttributeSet, false);
140 singleLineTextPane.setParagraphAttributes(insetAttributeSet, false);
141 levelTextPane.setParagraphAttributes(insetAttributeSet, false);
142 }
143
144 public void setToolTipsVisible(boolean toolTipsVisible) {
145 this.toolTipsVisible = toolTipsVisible;
146 }
147
148 public Component getTableCellRendererComponent(
149 final JTable table, Object value, boolean isSelected, boolean hasFocus,
150 int row, int col) {
151 EventContainer container = (EventContainer) table.getModel();
152 LoggingEventWrapper loggingEventWrapper = container.getRow(row);
153 value = formatField(value, loggingEventWrapper);
154 TableColumn tableColumn = table.getColumnModel().getColumn(col);
155 int width = tableColumn.getWidth();
156 JLabel label = (JLabel) super.getTableCellRendererComponent(table, value,
157 isSelected, hasFocus, row, col);
158
159 int colIndex = tableColumn.getModelIndex() + 1;
160
161
162 if (loggingEventWrapper == null) {
163 return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
164 }
165 long delta = 0;
166 if (row > 0) {
167 LoggingEventWrapper previous = eventContainer.getRow(row - 1);
168 delta = Math.min(ChainsawConstants.MILLIS_DELTA_RENDERING_HEIGHT_MAX, Math.max(0, (long) ((loggingEventWrapper.getLoggingEvent().getTimeStamp() - previous.getLoggingEvent().getTimeStamp()) * ChainsawConstants.MILLIS_DELTA_RENDERING_FACTOR)));
169 }
170
171 Map matches = loggingEventWrapper.getSearchMatches();
172
173 JComponent component;
174 switch (colIndex) {
175 case ChainsawColumns.INDEX_THROWABLE_COL_NAME:
176 if (value instanceof String[] && ((String[]) value).length > 0) {
177 Style tabStyle = singleLineTextPane.getLogicalStyle();
178 StyleConstants.setTabSet(tabStyle, tabs);
179
180 singleLineTextPane.setLogicalStyle(tabStyle);
181
182 Set exceptionMatches = (Set) matches.get(LoggingEventFieldResolver.EXCEPTION_FIELD);
183 if (exceptionMatches != null && exceptionMatches.size() > 0) {
184 singleLineTextPane.setText(((String[]) value)[0]);
185 boldAll((StyledDocument) singleLineTextPane.getDocument());
186 } else {
187 singleLineTextPane.setText(((String[]) value)[0]);
188 }
189 } else {
190 singleLineTextPane.setText("");
191 }
192 layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
193 component = generalPanel;
194 break;
195 case ChainsawColumns.INDEX_LOGGER_COL_NAME:
196 String logger = value.toString();
197 int startPos = -1;
198
199 for (int i = 0; i < loggerPrecision; i++) {
200 startPos = logger.indexOf(".", startPos + 1);
201 if (startPos < 0) {
202 break;
203 }
204 }
205 singleLineTextPane.setText(logger.substring(startPos + 1));
206 setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.LOGGER_FIELD), (StyledDocument) singleLineTextPane.getDocument());
207 layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
208 component = generalPanel;
209 break;
210 case ChainsawColumns.INDEX_ID_COL_NAME:
211 singleLineTextPane.setText(value.toString());
212 setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.PROP_FIELD + "LOG4JID"), (StyledDocument) singleLineTextPane.getDocument());
213 layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
214 component = generalPanel;
215 break;
216 case ChainsawColumns.INDEX_CLASS_COL_NAME:
217 singleLineTextPane.setText(value.toString());
218 setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.CLASS_FIELD), (StyledDocument) singleLineTextPane.getDocument());
219 layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
220 component = generalPanel;
221 break;
222 case ChainsawColumns.INDEX_FILE_COL_NAME:
223 singleLineTextPane.setText(value.toString());
224 setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.FILE_FIELD), (StyledDocument) singleLineTextPane.getDocument());
225 layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
226 component = generalPanel;
227 break;
228 case ChainsawColumns.INDEX_LINE_COL_NAME:
229 singleLineTextPane.setText(value.toString());
230 setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.LINE_FIELD), (StyledDocument) singleLineTextPane.getDocument());
231 layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
232 component = generalPanel;
233 break;
234 case ChainsawColumns.INDEX_NDC_COL_NAME:
235 singleLineTextPane.setText(value.toString());
236 setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.NDC_FIELD), (StyledDocument) singleLineTextPane.getDocument());
237 layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
238 component = generalPanel;
239 break;
240 case ChainsawColumns.INDEX_THREAD_COL_NAME:
241 singleLineTextPane.setText(value.toString());
242 setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.THREAD_FIELD), (StyledDocument) singleLineTextPane.getDocument());
243 layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
244 component = generalPanel;
245 break;
246 case ChainsawColumns.INDEX_TIMESTAMP_COL_NAME:
247
248 Set timestampMatches = (Set) matches.get(LoggingEventFieldResolver.TIMESTAMP_FIELD);
249 if (timestampMatches != null && timestampMatches.size() > 0) {
250 singleLineTextPane.setText(value.toString());
251 boldAll((StyledDocument) singleLineTextPane.getDocument());
252 } else {
253 singleLineTextPane.setText(value.toString());
254 }
255 layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
256 component = generalPanel;
257 break;
258 case ChainsawColumns.INDEX_METHOD_COL_NAME:
259 singleLineTextPane.setText(value.toString());
260 setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.METHOD_FIELD), (StyledDocument) singleLineTextPane.getDocument());
261 layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
262 component = generalPanel;
263 break;
264 case ChainsawColumns.INDEX_LOG4J_MARKER_COL_NAME:
265 case ChainsawColumns.INDEX_MESSAGE_COL_NAME:
266 String thisString = value.toString().trim();
267 JTextPane textPane = wrap ? multiLineTextPane : singleLineTextPane;
268 JComponent textPaneContainer = wrap ? multiLinePanel : generalPanel;
269 textPane.setText(thisString);
270
271 if (colIndex == ChainsawColumns.INDEX_LOG4J_MARKER_COL_NAME) {
272
273 setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.PROP_FIELD + ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE.toUpperCase()), (StyledDocument) textPane.getDocument());
274 } else {
275 setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.MSG_FIELD), (StyledDocument) textPane.getDocument());
276 }
277 textPaneContainer.removeAll();
278 if (delta > 0 && logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
279 JPanel newPanel = new JPanel();
280 newPanel.setOpaque(true);
281 newPanel.setBackground(applicationPreferenceModel.getDeltaColor());
282 newPanel.setPreferredSize(new Dimension(width, (int) delta));
283 textPaneContainer.add(newPanel, BorderLayout.NORTH);
284 }
285 textPaneContainer.add(textPane, BorderLayout.SOUTH);
286
287 if (delta == 0 || !logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
288 if (col == 0) {
289 textPane.setBorder(getLeftBorder(isSelected, delta));
290 } else if (col == table.getColumnCount() - 1) {
291 textPane.setBorder(getRightBorder(isSelected, delta));
292 } else {
293 textPane.setBorder(getMiddleBorder(isSelected, delta));
294 }
295 } else {
296 if (col == 0) {
297 textPane.setBorder(getLeftBorder(isSelected, 0));
298 } else if (col == table.getColumnCount() - 1) {
299 textPane.setBorder(getRightBorder(isSelected, 0));
300 } else {
301 textPane.setBorder(getMiddleBorder(isSelected, 0));
302 }
303 }
304 int currentMarkerHeight = loggingEventWrapper.getMarkerHeight();
305 int currentMsgHeight = loggingEventWrapper.getMsgHeight();
306 int newRowHeight = ChainsawConstants.DEFAULT_ROW_HEIGHT;
307 boolean setHeight = false;
308
309 if (wrap) {
310
311
312
313
314
315
316
317
318
319 textPane.setSize(new Dimension(width, maxHeight));
320 int multiLinePanelPrefHeight = textPaneContainer.getPreferredSize().height;
321 newRowHeight = Math.max(ChainsawConstants.DEFAULT_ROW_HEIGHT, multiLinePanelPrefHeight);
322
323 }
324 if (!wrap && logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
325 textPane.setSize(new Dimension(Integer.MAX_VALUE, ChainsawConstants.DEFAULT_ROW_HEIGHT));
326 newRowHeight = (int) (ChainsawConstants.DEFAULT_ROW_HEIGHT + delta);
327 }
328
329 if (colIndex == ChainsawColumns.INDEX_LOG4J_MARKER_COL_NAME) {
330 loggingEventWrapper.setMarkerHeight(newRowHeight);
331 if (newRowHeight != currentMarkerHeight && newRowHeight >= loggingEventWrapper.getMsgHeight()) {
332 setHeight = true;
333 }
334 }
335
336 if (colIndex == ChainsawColumns.INDEX_MESSAGE_COL_NAME) {
337 loggingEventWrapper.setMsgHeight(newRowHeight);
338 if (newRowHeight != currentMsgHeight && newRowHeight >= loggingEventWrapper.getMarkerHeight()) {
339 setHeight = true;
340 }
341 }
342 if (setHeight) {
343 table.setRowHeight(row, newRowHeight);
344 }
345
346 component = textPaneContainer;
347 break;
348 case ChainsawColumns.INDEX_LEVEL_COL_NAME:
349 if (levelUseIcons) {
350 levelTextPane.setText("");
351 levelTextPane.insertIcon(iconMap.get(value.toString()));
352 if (!toolTipsVisible) {
353 levelTextPane.setToolTipText(value.toString());
354 }
355 } else {
356 levelTextPane.setText(value.toString());
357 setHighlightAttributesInternal(matches.get(LoggingEventFieldResolver.LEVEL_FIELD), (StyledDocument) levelTextPane.getDocument());
358 if (!toolTipsVisible) {
359 levelTextPane.setToolTipText(null);
360 }
361 }
362 if (toolTipsVisible) {
363 levelTextPane.setToolTipText(label.getToolTipText());
364 }
365 levelTextPane.setForeground(label.getForeground());
366 levelTextPane.setBackground(label.getBackground());
367 layoutRenderingPanel(levelPanel, levelTextPane, delta, isSelected, width, col, table);
368 component = levelPanel;
369 break;
370
371
372 default:
373 Set propertySet = loggingEventWrapper.getPropertyKeySet();
374 String headerName = tableColumn.getHeaderValue().toString().toLowerCase();
375 String thisProp = null;
376
377 for (Object aPropertySet : propertySet) {
378 String entry = aPropertySet.toString();
379 if (entry.equalsIgnoreCase(headerName)) {
380 thisProp = entry;
381 break;
382 }
383 }
384 if (thisProp != null) {
385 String propKey = LoggingEventFieldResolver.PROP_FIELD + thisProp.toUpperCase();
386 Set propKeyMatches = (Set) matches.get(propKey);
387 singleLineTextPane.setText(loggingEventWrapper.getLoggingEvent().getProperty(thisProp));
388 setHighlightAttributesInternal(propKeyMatches, (StyledDocument) singleLineTextPane.getDocument());
389 } else {
390 singleLineTextPane.setText("");
391 }
392 layoutRenderingPanel(generalPanel, singleLineTextPane, delta, isSelected, width, col, table);
393 component = generalPanel;
394 break;
395 }
396
397 Color background;
398 Color foreground;
399 Rule loggerRule = colorizer.getLoggerRule();
400
401 if (loggerRule != null && loggerRule.evaluate(loggingEventWrapper.getLoggingEvent(), null)) {
402 background = applicationPreferenceModel.getSearchBackgroundColor();
403 foreground = applicationPreferenceModel.getSearchForegroundColor();
404 } else {
405 if (colorizeSearch && !applicationPreferenceModel.isBypassSearchColors()) {
406 background = loggingEventWrapper.isSearchMatch() ? applicationPreferenceModel.getSearchBackgroundColor() : loggingEventWrapper.getBackground();
407 foreground = loggingEventWrapper.isSearchMatch() ? applicationPreferenceModel.getSearchForegroundColor() : loggingEventWrapper.getForeground();
408 } else {
409 background = loggingEventWrapper.getBackground();
410 foreground = loggingEventWrapper.getForeground();
411 }
412 }
413
414
415
416
417 if (background.equals(ChainsawConstants.COLOR_DEFAULT_BACKGROUND) && foreground.equals(ChainsawConstants.COLOR_DEFAULT_FOREGROUND) && (row % 2) != 0) {
418 background = applicationPreferenceModel.getAlternatingColorBackgroundColor();
419 foreground = applicationPreferenceModel.getAlternatingColorForegroundColor();
420 }
421
422 component.setBackground(background);
423 component.setForeground(foreground);
424
425
426 if (multiLineTextPane != null) {
427 updateColors(multiLineTextPane, background, foreground);
428 }
429 updateColors(levelTextPane, background, foreground);
430 updateColors(singleLineTextPane, background, foreground);
431
432 return component;
433 }
434
435 private void layoutRenderingPanel(JComponent container, JComponent bottomComponent, long delta, boolean isSelected,
436 int width, int col, JTable table) {
437 container.removeAll();
438 if (delta == 0 || !logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
439 if (col == 0) {
440 bottomComponent.setBorder(getLeftBorder(isSelected, delta));
441 } else if (col == table.getColumnCount() - 1) {
442 bottomComponent.setBorder(getRightBorder(isSelected, delta));
443 } else {
444 bottomComponent.setBorder(getMiddleBorder(isSelected, delta));
445 }
446 } else {
447 JPanel newPanel = new JPanel();
448 newPanel.setOpaque(true);
449 newPanel.setBackground(applicationPreferenceModel.getDeltaColor());
450 newPanel.setPreferredSize(new Dimension(width, (int) delta));
451 container.add(newPanel, BorderLayout.NORTH);
452 if (col == 0) {
453 bottomComponent.setBorder(getLeftBorder(isSelected, 0));
454 } else if (col == table.getColumnCount() - 1) {
455 bottomComponent.setBorder(getRightBorder(isSelected, 0));
456 } else {
457 bottomComponent.setBorder(getMiddleBorder(isSelected, 0));
458 }
459 }
460
461 container.add(bottomComponent, BorderLayout.SOUTH);
462 }
463
464 private Border getLeftBorder(boolean isSelected, long delta) {
465 Border LEFT_BORDER = BorderFactory.createMatteBorder(borderWidth, borderWidth, borderWidth, 0, borderColor);
466 Border LEFT_EMPTY_BORDER = BorderFactory.createEmptyBorder(borderWidth, borderWidth, borderWidth, 0);
467
468 Border innerBorder = isSelected ? LEFT_BORDER : LEFT_EMPTY_BORDER;
469 if (delta == 0 || !wrap || !logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
470 return innerBorder;
471 } else {
472 Border outerBorder = BorderFactory.createMatteBorder((int) Math.max(borderWidth, delta), 0, 0, 0, applicationPreferenceModel.getDeltaColor());
473 return BorderFactory.createCompoundBorder(outerBorder, innerBorder);
474 }
475 }
476
477 private Border getRightBorder(boolean isSelected, long delta) {
478 Border RIGHT_BORDER = BorderFactory.createMatteBorder(borderWidth, 0, borderWidth, borderWidth, borderColor);
479 Border RIGHT_EMPTY_BORDER = BorderFactory.createEmptyBorder(borderWidth, 0, borderWidth, borderWidth);
480 Border innerBorder = isSelected ? RIGHT_BORDER : RIGHT_EMPTY_BORDER;
481 if (delta == 0 || !wrap || !logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
482 return innerBorder;
483 } else {
484 Border outerBorder = BorderFactory.createMatteBorder((int) Math.max(borderWidth, delta), 0, 0, 0, applicationPreferenceModel.getDeltaColor());
485 return BorderFactory.createCompoundBorder(outerBorder, innerBorder);
486 }
487 }
488
489 private Border getMiddleBorder(boolean isSelected, long delta) {
490 Border MIDDLE_BORDER = BorderFactory.createMatteBorder(borderWidth, 0, borderWidth, 0, borderColor);
491 Border MIDDLE_EMPTY_BORDER = BorderFactory.createEmptyBorder(borderWidth, 0, borderWidth, 0);
492 Border innerBorder = isSelected ? MIDDLE_BORDER : MIDDLE_EMPTY_BORDER;
493 if (delta == 0 || !wrap || !logPanelPreferenceModel.isShowMillisDeltaAsGap()) {
494 return innerBorder;
495 } else {
496 Border outerBorder = BorderFactory.createMatteBorder((int) Math.max(borderWidth, delta), 0, 0, 0, applicationPreferenceModel.getDeltaColor());
497 return BorderFactory.createCompoundBorder(outerBorder, innerBorder);
498 }
499 }
500
501 private void updateColors(JTextPane textPane, Color background, Color foreground) {
502 StyledDocument styledDocument = textPane.getStyledDocument();
503 MutableAttributeSet attributes = textPane.getInputAttributes();
504 StyleConstants.setForeground(attributes, foreground);
505 styledDocument.setCharacterAttributes(0, styledDocument.getLength() + 1, attributes, false);
506 textPane.setBackground(background);
507 }
508
509
510
511
512
513
514 void setDateFormatter(DateFormat formatter) {
515 this.dateFormatInUse = formatter;
516 if (dateFormatInUse != null && dateFormatTZ != null && !("".equals(dateFormatTZ))) {
517 dateFormatInUse.setTimeZone(TimeZone.getTimeZone(dateFormatTZ));
518 } else {
519 dateFormatInUse.setTimeZone(TimeZone.getDefault());
520 }
521 }
522
523
524
525
526
527
528 void setLoggerPrecision(String loggerPrecisionText) {
529 try {
530 loggerPrecision = Integer.parseInt(loggerPrecisionText);
531 } catch (NumberFormatException nfe) {
532 loggerPrecision = 0;
533 }
534 }
535
536
537
538
539
540
541
542 private Object formatField(Object field, LoggingEventWrapper loggingEventWrapper) {
543 if (!(field instanceof Date)) {
544 return (field == null ? "" : field);
545 }
546
547
548 if (useRelativeTimesToFixedTime) {
549 return "" + (((Date) field).getTime() - relativeTimestampBase);
550 }
551 if (useRelativeTimesToPrevious) {
552 return loggingEventWrapper.getLoggingEvent().getProperty(ChainsawConstants.MILLIS_DELTA_COL_NAME_LOWERCASE);
553 }
554
555 return dateFormatInUse.format((Date) field);
556 }
557
558
559
560
561
562
563 public void setWrapMessage(boolean wrapMsg) {
564 this.wrap = wrapMsg;
565 }
566
567
568
569
570
571
572
573 public void setLevelUseIcons(boolean levelUseIcons) {
574 this.levelUseIcons = levelUseIcons;
575 }
576
577 public void setTimeZone(String dateFormatTZ) {
578 this.dateFormatTZ = dateFormatTZ;
579
580 if (dateFormatInUse != null && dateFormatTZ != null && !("".equals(dateFormatTZ))) {
581 dateFormatInUse.setTimeZone(TimeZone.getTimeZone(dateFormatTZ));
582 } else {
583 dateFormatInUse.setTimeZone(TimeZone.getDefault());
584 }
585 }
586
587 public void setUseRelativeTimes(long timeStamp) {
588 useRelativeTimesToFixedTime = true;
589 useRelativeTimesToPrevious = false;
590 relativeTimestampBase = timeStamp;
591 }
592
593 public void setUseRelativeTimesToPreviousRow() {
594 useRelativeTimesToFixedTime = false;
595 useRelativeTimesToPrevious = true;
596 }
597
598 public void setUseNormalTimes() {
599 useRelativeTimesToFixedTime = false;
600 useRelativeTimesToPrevious = false;
601 }
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622 private void setHighlightAttributesInternal(Object matchSet, StyledDocument styledDocument) {
623 if (!highlightSearchMatchText) {
624 return;
625 }
626 setHighlightAttributes(matchSet, styledDocument);
627 }
628
629 public void setHighlightAttributes(Object matchSet, StyledDocument styledDocument) {
630 if (matchSet instanceof Set) {
631 Set thisSet = (Set) matchSet;
632 for (Object aThisSet : thisSet) {
633 String thisEntry = aThisSet.toString();
634 bold(thisEntry, styledDocument);
635 }
636 }
637 }
638
639 private void boldAll(StyledDocument styledDocument) {
640 if (!highlightSearchMatchText) {
641 return;
642 }
643 styledDocument.setCharacterAttributes(0, styledDocument.getLength(), boldAttributeSet, false);
644 }
645
646 private void bold(String textToBold, StyledDocument styledDocument) {
647 try {
648 String lowerInput = styledDocument.getText(0, styledDocument.getLength()).toLowerCase();
649 String lowerTextToBold = textToBold.toLowerCase();
650 int textToBoldLength = textToBold.length();
651 int firstIndex = 0;
652 int currentIndex;
653 while ((currentIndex = lowerInput.indexOf(lowerTextToBold, firstIndex)) > -1) {
654 styledDocument.setCharacterAttributes(currentIndex, textToBoldLength, boldAttributeSet, false);
655 firstIndex = currentIndex + textToBoldLength;
656 }
657 } catch (BadLocationException e) {
658
659 }
660 }
661
662 public void setHighlightSearchMatchText(boolean highlightSearchMatchText) {
663 this.highlightSearchMatchText = highlightSearchMatchText;
664 }
665
666 private class OneLineEditorKit extends StyledEditorKit {
667 private ViewFactory viewFactoryImpl = new ViewFactoryImpl();
668
669 public ViewFactory getViewFactory() {
670 return viewFactoryImpl;
671 }
672 }
673
674 private class ViewFactoryImpl implements ViewFactory {
675 public View create(Element elem) {
676 String elementName = elem.getName();
677 if (elementName != null) {
678 switch (elementName) {
679 case AbstractDocument.ParagraphElementName:
680 return new OneLineParagraphView(elem);
681 case AbstractDocument.ContentElementName:
682 return new LabelView(elem);
683 case AbstractDocument.SectionElementName:
684 return new BoxView(elem, View.Y_AXIS);
685 case StyleConstants.ComponentElementName:
686 return new ComponentView(elem);
687 case StyleConstants.IconElementName:
688 return new IconView(elem);
689 }
690 }
691 return new LabelView(elem);
692 }
693 }
694
695 private class OneLineParagraphView extends ParagraphView {
696 public OneLineParagraphView(Element elem) {
697 super(elem);
698 }
699
700
701 public int getFlowSpan(int index) {
702 return Integer.MAX_VALUE;
703 }
704 }
705 }