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