1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.log4j.chainsaw;
20
21 import org.apache.log4j.LogManager;
22 import org.apache.log4j.Logger;
23 import org.apache.log4j.chainsaw.color.RuleColorizer;
24 import org.apache.log4j.chainsaw.filter.FilterModel;
25 import org.apache.log4j.chainsaw.icons.ChainsawIcons;
26 import org.apache.log4j.chainsaw.icons.LineIconFactory;
27 import org.apache.log4j.rule.AbstractRule;
28 import org.apache.log4j.rule.ColorRule;
29 import org.apache.log4j.rule.ExpressionRule;
30 import org.apache.log4j.rule.Rule;
31 import org.apache.log4j.spi.LoggingEvent;
32
33 import javax.swing.*;
34 import javax.swing.event.*;
35 import javax.swing.tree.*;
36 import java.awt.*;
37 import java.awt.event.*;
38 import java.util.*;
39 import java.util.List;
40
41
42
43
44
45
46
47
48
49 final class LoggerNameTreePanel extends JPanel implements LoggerNameListener {
50
51
52 private static final int WARN_DEPTH = 4;
53
54
55
56 private LoggerNameTreeCellRenderer cellRenderer =
57 new LoggerNameTreeCellRenderer();
58 private final Action clearIgnoreListAction;
59 private final Action closeAction;
60 private final JButton closeButton = new SmallButton();
61 private final Action collapseAction;
62 private final JButton collapseButton = new SmallButton();
63 private final Action editLoggerAction;
64 private final JButton editLoggerButton = new SmallButton();
65 private final Action expandAction;
66 private final Action findAction;
67 private final Action clearFindNextAction;
68 private final Action defineColorRuleForLoggerAction;
69 private final Action setRefineFocusAction;
70 private final Action updateRefineFocusAction;
71 private final Action updateFindAction;
72 private final JButton expandButton = new SmallButton();
73 private final Action focusOnAction;
74 private final Action clearRefineFocusAction;
75 private final SmallToggleButton focusOnLoggerButton =
76 new SmallToggleButton();
77 private final Set hiddenSet = new HashSet();
78 private final Action hideAction;
79 private final Action hideSubLoggersAction;
80 private final LogPanelPreferenceModel preferenceModel;
81
82 private final JList ignoreList = new JList();
83 private final JEditorPane ignoreExpressionEntryField = new JEditorPane();
84 private final JEditorPane alwaysDisplayExpressionEntryField = new JEditorPane();
85 private final JScrollPane ignoreListScroll = new JScrollPane(ignoreList);
86 private final JDialog ignoreDialog = new JDialog();
87 private final JDialog ignoreExpressionDialog = new JDialog();
88 private final JDialog alwaysDisplayExpressionDialog = new JDialog();
89 private final JLabel ignoreSummary = new JLabel("0 hidden loggers");
90 private final JLabel ignoreExpressionSummary = new JLabel("Ignore expression");
91 private final JLabel alwaysDisplayExpressionSummary = new JLabel("Always displayed expression");
92 private final SmallToggleButton ignoreLoggerButton = new SmallToggleButton();
93 private final EventListenerList listenerList = new EventListenerList();
94 private final JTree logTree;
95 private final Logger logger = LogManager.getLogger(LoggerNameTreePanel.class);
96
97
98
99 private final LogPanelLoggerTreeModel logTreeModel;
100 private final PopupListener popupListener;
101 private final LoggerTreePopupMenu popupMenu;
102 private final VisibilityRuleDelegate visibilityRuleDelegate;
103 private Rule colorRuleDelegate;
104 private final JScrollPane scrollTree;
105 private final JToolBar toolbar = new JToolBar();
106 private final LogPanel logPanel;
107 private final RuleColorizer colorizer;
108 private Rule ignoreExpressionRule;
109 private Rule alwaysDisplayExpressionRule;
110 private boolean expandRootLatch = false;
111 private String currentlySelectedLoggerName;
112
113
114
115
116
117
118
119
120 LoggerNameTreePanel(LogPanelLoggerTreeModel logTreeModel, LogPanelPreferenceModel preferenceModel, LogPanel logPanel, RuleColorizer colorizer, FilterModel filterModel) {
121 super();
122 this.logTreeModel = logTreeModel;
123 this.preferenceModel = preferenceModel;
124 this.logPanel = logPanel;
125 this.colorizer = colorizer;
126
127 setLayout(new BorderLayout());
128 ignoreExpressionEntryField.setPreferredSize(new Dimension(300, 150));
129 alwaysDisplayExpressionEntryField.setPreferredSize(new Dimension(300, 150));
130 alwaysDisplayExpressionSummary.setMinimumSize(new Dimension(10, alwaysDisplayExpressionSummary.getHeight()));
131 ignoreExpressionSummary.setMinimumSize(new Dimension(10, ignoreExpressionSummary.getHeight()));
132 ignoreSummary.setMinimumSize(new Dimension(10, ignoreSummary.getHeight()));
133
134 JTextComponentFormatter.applySystemFontAndSize(ignoreExpressionEntryField);
135 JTextComponentFormatter.applySystemFontAndSize(alwaysDisplayExpressionEntryField);
136
137 visibilityRuleDelegate = new VisibilityRuleDelegate();
138 colorRuleDelegate =
139 new AbstractRule() {
140 public boolean evaluate(LoggingEvent e, Map matches) {
141 boolean hiddenLogger = e.getLoggerName() != null && isHiddenLogger(e.getLoggerName());
142 boolean hiddenExpression = (ignoreExpressionRule != null && ignoreExpressionRule.evaluate(e, null));
143 boolean alwaysDisplayExpression = (alwaysDisplayExpressionRule != null && alwaysDisplayExpressionRule.evaluate(e, null));
144 boolean hidden = (!alwaysDisplayExpression) && (hiddenLogger || hiddenExpression);
145 String currentlySelectedLoggerName = getCurrentlySelectedLoggerName();
146
147 return !isFocusOnSelected() && !hidden && currentlySelectedLoggerName != null && !"".equals(currentlySelectedLoggerName) && (e.getLoggerName().startsWith(currentlySelectedLoggerName + ".") || e.getLoggerName().endsWith(currentlySelectedLoggerName));
148 }
149 };
150
151 logTree =
152 new JTree(logTreeModel) {
153 public String getToolTipText(MouseEvent ev) {
154 if (ev == null) {
155 return null;
156 }
157
158 TreePath path = logTree.getPathForLocation(ev.getX(), ev.getY());
159
160 String loggerName = getLoggerName(path);
161
162 if (hiddenSet.contains(loggerName)) {
163 loggerName += " (you are ignoring this logger)";
164 }
165
166 return loggerName;
167 }
168 };
169
170 ToolTipManager.sharedInstance().registerComponent(logTree);
171 logTree.setCellRenderer(cellRenderer);
172
173
174 logTreeModel.addTreeModelListener(new TreeModelListener() {
175 public void treeNodesChanged(TreeModelEvent e) {
176 }
177
178 public void treeNodesInserted(TreeModelEvent e) {
179 if (!expandRootLatch) {
180 ensureRootExpanded();
181 expandRootLatch = true;
182 }
183 }
184
185 public void treeNodesRemoved(TreeModelEvent e) {
186 }
187
188 public void treeStructureChanged(TreeModelEvent e) {
189 }
190 });
191
192 logTree.setEditable(false);
193
194
195 TreeSelectionModel selectionModel = new DefaultTreeSelectionModel();
196 selectionModel.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
197 logTree.setSelectionModel(selectionModel);
198
199 logTree.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
200 scrollTree = new JScrollPane(logTree);
201 toolbar.setLayout(new BoxLayout(toolbar, BoxLayout.X_AXIS));
202
203 expandAction = createExpandAction();
204 findAction = createFindNextAction();
205 clearFindNextAction = createClearFindNextAction();
206 defineColorRuleForLoggerAction = createDefineColorRuleForLoggerAction();
207 clearRefineFocusAction = createClearRefineFocusAction();
208 setRefineFocusAction = createSetRefineFocusAction();
209 updateRefineFocusAction = createUpdateRefineFocusAction();
210 updateFindAction = createUpdateFindAction();
211 editLoggerAction = createEditLoggerAction();
212 closeAction = createCloseAction();
213 collapseAction = createCollapseAction();
214 focusOnAction = createFocusOnAction();
215 hideAction = createIgnoreAction();
216 hideSubLoggersAction = createIgnoreAllAction();
217 clearIgnoreListAction = createClearIgnoreListAction();
218
219 popupMenu = new LoggerTreePopupMenu();
220 popupListener = new PopupListener(popupMenu);
221
222 setupListeners();
223 configureToolbarPanel();
224
225 add(toolbar, BorderLayout.NORTH);
226 add(scrollTree, BorderLayout.CENTER);
227
228 ignoreDialog.setTitle("Hidden/Ignored Loggers");
229 ignoreDialog.setModal(true);
230
231 ignoreExpressionDialog.setTitle("Hidden/Ignored Expression");
232 ignoreExpressionDialog.setModal(true);
233
234 alwaysDisplayExpressionDialog.setTitle("Always displayed Expression");
235 alwaysDisplayExpressionDialog.setModal(true);
236
237 JPanel ignorePanel = new JPanel();
238 ignorePanel.setLayout(new BoxLayout(ignorePanel, BoxLayout.Y_AXIS));
239 JPanel ignoreSummaryPanel = new JPanel();
240 ignoreSummaryPanel.setLayout(new BoxLayout(ignoreSummaryPanel, BoxLayout.X_AXIS));
241 ignoreSummaryPanel.add(ignoreSummary);
242
243 Action showIgnoreDialogAction = new AbstractAction("...") {
244 public void actionPerformed(ActionEvent e) {
245 LogPanel.centerAndSetVisible(ignoreDialog);
246 }
247 };
248
249 Action showIgnoreExpressionDialogAction = new AbstractAction("...") {
250 public void actionPerformed(ActionEvent e) {
251 LogPanel.centerAndSetVisible(ignoreExpressionDialog);
252 }
253 };
254
255
256 Action showAlwaysDisplayExpressionDialogAction = new AbstractAction("...") {
257 public void actionPerformed(ActionEvent e) {
258 LogPanel.centerAndSetVisible(alwaysDisplayExpressionDialog);
259 }
260 };
261
262 showIgnoreDialogAction.putValue(Action.SHORT_DESCRIPTION, "Click to view and manage your hidden/ignored loggers");
263 JButton btnShowIgnoreDialog = new SmallButton(showIgnoreDialogAction);
264
265 ignoreSummaryPanel.add(btnShowIgnoreDialog);
266 ignorePanel.add(ignoreSummaryPanel);
267
268 JPanel ignoreExpressionPanel = new JPanel();
269 ignoreExpressionPanel.setLayout(new BoxLayout(ignoreExpressionPanel, BoxLayout.X_AXIS));
270 ignoreExpressionPanel.add(ignoreExpressionSummary);
271 showIgnoreExpressionDialogAction.putValue(Action.SHORT_DESCRIPTION, "Click to view and manage your hidden/ignored expression");
272 JButton btnShowIgnoreExpressionDialog = new SmallButton(showIgnoreExpressionDialogAction);
273 ignoreExpressionPanel.add(btnShowIgnoreExpressionDialog);
274
275 ignorePanel.add(ignoreExpressionPanel);
276
277 JPanel alwaysDisplayExpressionPanel = new JPanel();
278 alwaysDisplayExpressionPanel.setLayout(new BoxLayout(alwaysDisplayExpressionPanel, BoxLayout.X_AXIS));
279 alwaysDisplayExpressionPanel.add(alwaysDisplayExpressionSummary);
280 showAlwaysDisplayExpressionDialogAction.putValue(Action.SHORT_DESCRIPTION, "Click to view and manage your always-displayed expression");
281 JButton btnShowAlwaysDisplayExpressionDialog = new SmallButton(showAlwaysDisplayExpressionDialogAction);
282 alwaysDisplayExpressionPanel.add(btnShowAlwaysDisplayExpressionDialog);
283
284 ignorePanel.add(alwaysDisplayExpressionPanel);
285
286 add(ignorePanel, BorderLayout.SOUTH);
287
288 ignoreList.setModel(new DefaultListModel());
289 ignoreList.addMouseListener(new MouseAdapter() {
290 public void mouseClicked(MouseEvent e) {
291 if (
292 (e.getClickCount() > 1)
293 && ((e.getModifiers() & InputEvent.BUTTON1_MASK) > 0)) {
294 int index = ignoreList.locationToIndex(e.getPoint());
295
296 if (index >= 0) {
297 String string =
298 ignoreList.getModel().getElementAt(index).toString();
299 toggleHiddenLogger(string);
300 fireChangeEvent();
301
302
303
304
305 LoggerNameTreePanel.this.logTreeModel.nodeStructureChanged(
306 (TreeNode) LoggerNameTreePanel.this.logTreeModel.getRoot());
307 }
308 }
309 }
310 });
311
312 JPanel ignoreListPanel = new JPanel(new BorderLayout());
313 ignoreListScroll.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Double click an entry to unhide it"));
314 ignoreListPanel.add(ignoreListScroll, BorderLayout.CENTER);
315
316 JPanel ignoreExpressionDialogPanel = new JPanel(new BorderLayout());
317 ignoreExpressionEntryField.addKeyListener(new ExpressionRuleContext(filterModel, ignoreExpressionEntryField));
318
319 ignoreExpressionDialogPanel.add(new JScrollPane(ignoreExpressionEntryField), BorderLayout.CENTER);
320 JButton ignoreExpressionCloseButton = new JButton(new AbstractAction(" Close ") {
321 public void actionPerformed(ActionEvent e) {
322 String ignoreText = ignoreExpressionEntryField.getText();
323
324 if (updateIgnoreExpression(ignoreText)) {
325 ignoreExpressionDialog.setVisible(false);
326 }
327 }
328 });
329
330
331 JPanel alwaysDisplayExpressionDialogPanel = new JPanel(new BorderLayout());
332 alwaysDisplayExpressionEntryField.addKeyListener(new ExpressionRuleContext(filterModel, alwaysDisplayExpressionEntryField));
333
334 alwaysDisplayExpressionDialogPanel.add(new JScrollPane(alwaysDisplayExpressionEntryField), BorderLayout.CENTER);
335 JButton alwaysDisplayExpressionCloseButton = new JButton(new AbstractAction(" Close ") {
336 public void actionPerformed(ActionEvent e) {
337 String alwaysDisplayText = alwaysDisplayExpressionEntryField.getText();
338
339 if (updateAlwaysDisplayExpression(alwaysDisplayText)) {
340 alwaysDisplayExpressionDialog.setVisible(false);
341 }
342 }
343 });
344
345 JPanel closeAlwaysDisplayExpressionPanel = new JPanel();
346 closeAlwaysDisplayExpressionPanel.add(alwaysDisplayExpressionCloseButton);
347 alwaysDisplayExpressionDialogPanel.add(closeAlwaysDisplayExpressionPanel, BorderLayout.SOUTH);
348
349 JPanel closeIgnoreExpressionPanel = new JPanel();
350 closeIgnoreExpressionPanel.add(ignoreExpressionCloseButton);
351 ignoreExpressionDialogPanel.add(closeIgnoreExpressionPanel, BorderLayout.SOUTH);
352
353 Box ignoreListButtonPanel = Box.createHorizontalBox();
354
355 JButton unhideAll = new JButton(new AbstractAction(" Unhide All ") {
356
357 public void actionPerformed(final ActionEvent e) {
358 SwingUtilities.invokeLater(() -> clearIgnoreListAction.actionPerformed(e));
359
360 }
361 });
362 ignoreListButtonPanel.add(unhideAll);
363
364 ignoreListButtonPanel.add(Box.createHorizontalGlue());
365 JButton ignoreCloseButton = new JButton(new AbstractAction(" Close ") {
366
367 public void actionPerformed(ActionEvent e) {
368 ignoreDialog.setVisible(false);
369
370 }
371 });
372 ignoreListButtonPanel.add(ignoreCloseButton);
373
374
375 ignoreListPanel.add(ignoreListButtonPanel, BorderLayout.SOUTH);
376
377
378 ignoreDialog.getContentPane().add(ignoreListPanel);
379 ignoreDialog.pack();
380
381 ignoreExpressionDialog.getContentPane().add(ignoreExpressionDialogPanel);
382 ignoreExpressionDialog.pack();
383
384 alwaysDisplayExpressionDialog.getContentPane().add(alwaysDisplayExpressionDialogPanel);
385 alwaysDisplayExpressionDialog.pack();
386 }
387
388 private boolean updateIgnoreExpression(String ignoreText) {
389 try {
390 if (ignoreText != null && !ignoreText.trim().equals("")) {
391 ignoreExpressionRule = ExpressionRule.getRule(ignoreText);
392 } else {
393 ignoreExpressionRule = null;
394 }
395 visibilityRuleDelegate.firePropertyChange("hiddenSet", null, null);
396
397 updateDisplay();
398 ignoreExpressionEntryField.setBackground(UIManager.getColor("TextField.background"));
399 return true;
400 } catch (IllegalArgumentException iae) {
401 ignoreExpressionEntryField.setToolTipText(iae.getMessage());
402 ignoreExpressionEntryField.setBackground(ChainsawConstants.INVALID_EXPRESSION_BACKGROUND);
403 return false;
404 }
405 }
406
407 private boolean updateAlwaysDisplayExpression(String alwaysDisplayText) {
408 try {
409 if (alwaysDisplayText != null && !alwaysDisplayText.trim().equals("")) {
410 alwaysDisplayExpressionRule = ExpressionRule.getRule(alwaysDisplayText);
411 } else {
412 alwaysDisplayExpressionRule = null;
413 }
414 visibilityRuleDelegate.firePropertyChange("alwaysDisplayedSet", null, null);
415
416 updateDisplay();
417 alwaysDisplayExpressionEntryField.setBackground(UIManager.getColor("TextField.background"));
418 return true;
419 } catch (IllegalArgumentException iae) {
420 alwaysDisplayExpressionEntryField.setToolTipText(iae.getMessage());
421 alwaysDisplayExpressionEntryField.setBackground(ChainsawConstants.INVALID_EXPRESSION_BACKGROUND);
422 return false;
423 }
424 }
425
426
427
428
429
430
431
432
433
434 public void addChangeListener(ChangeListener l) {
435 listenerList.add(ChangeListener.class, l);
436 }
437
438 public Rule getLoggerColorRule() {
439 return colorRuleDelegate;
440 }
441
442 public Rule getLoggerVisibilityRule() {
443 return visibilityRuleDelegate;
444 }
445
446
447
448
449
450
451 public void removeChangeListener(ChangeListener l) {
452 listenerList.remove(ChangeListener.class, l);
453 }
454
455
456
457
458
459
460 public void setFocusOn(String newLogger) {
461 DefaultMutableTreeNode node = logTreeModel.lookupLogger(newLogger);
462
463 if (node != null) {
464 TreeNode[] nodes = node.getPath();
465 TreePath treePath = new TreePath(nodes);
466 logTree.setSelectionPath(treePath);
467
468 if (!focusOnLoggerButton.isSelected()) {
469 focusOnLoggerButton.doClick();
470 }
471 } else {
472 logger.error("failed to lookup logger " + newLogger);
473 }
474 }
475
476 private boolean isHiddenLogger(String loggerName) {
477 for (Object aHiddenSet : hiddenSet) {
478 String hiddenLoggerEntry = aHiddenSet.toString();
479 if (loggerName.startsWith(hiddenLoggerEntry + ".") || loggerName.endsWith(hiddenLoggerEntry)) {
480 return true;
481 }
482 }
483 return false;
484 }
485
486
487
488
489
490
491
492 protected void toggleHiddenLogger(String logger) {
493 if (!hiddenSet.contains(logger)) {
494 hiddenSet.add(logger);
495 } else {
496 hiddenSet.remove(logger);
497 }
498
499 visibilityRuleDelegate.firePropertyChange("hiddenSet", null, null);
500 }
501
502
503
504
505
506
507
508
509
510
511
512 String getCurrentlySelectedLoggerName() {
513 TreePath[] paths = logTree.getSelectionPaths();
514
515 if ((paths == null) || (paths.length == 0)) {
516 return null;
517 }
518
519 TreePath firstPath = paths[0];
520
521 return getLoggerName(firstPath);
522 }
523
524
525
526
527
528
529
530 String getLoggerName(TreePath path) {
531 if (path != null) {
532 Object[] objects = path.getPath();
533 StringBuilder buf = new StringBuilder();
534
535 for (int i = 1; i < objects.length; i++) {
536 buf.append(objects[i].toString());
537
538 if (i < (objects.length - 1)) {
539 buf.append(".");
540 }
541 }
542
543 return buf.toString();
544 }
545
546 return null;
547 }
548
549
550
551
552
553
554
555
556 void ignore(Collection fqnLoggersToIgnore) {
557 hiddenSet.addAll(fqnLoggersToIgnore);
558 visibilityRuleDelegate.firePropertyChange("hiddenSet", null, null);
559 fireChangeEvent();
560 }
561
562
563
564
565
566
567 boolean isFocusOnSelected() {
568 return focusOnAction.getValue("checked") != null;
569 }
570
571 void setFocusOnSelected(boolean selected) {
572 if (selected) {
573 focusOnAction.putValue("checked", Boolean.TRUE);
574 } else {
575 focusOnAction.putValue("checked", null);
576 }
577 }
578
579
580
581
582
583 private void collapseCurrentlySelectedNode() {
584 TreePath[] paths = logTree.getSelectionPaths();
585
586 if (paths == null) {
587 return;
588 }
589
590 logger.debug("Collapsing all children of selected node");
591
592 for (TreePath path : paths) {
593 DefaultMutableTreeNode node =
594 (DefaultMutableTreeNode) path.getLastPathComponent();
595 Enumeration enumeration = node.depthFirstEnumeration();
596
597 while (enumeration.hasMoreElements()) {
598 DefaultMutableTreeNode child =
599 (DefaultMutableTreeNode) enumeration.nextElement();
600
601 if ((child.getParent() != null) && (child != node)) {
602 TreeNode[] nodes =
603 ((DefaultMutableTreeNode) child.getParent()).getPath();
604
605 TreePath treePath = new TreePath(nodes);
606 logTree.collapsePath(treePath);
607 }
608 }
609 }
610
611 ensureRootExpanded();
612 }
613
614
615
616
617
618 private void configureToolbarPanel() {
619 toolbar.setFloatable(false);
620
621 expandButton.setAction(expandAction);
622 expandButton.setText(null);
623 collapseButton.setAction(collapseAction);
624 collapseButton.setText(null);
625 focusOnLoggerButton.setAction(focusOnAction);
626 focusOnLoggerButton.setText(null);
627 ignoreLoggerButton.setAction(hideAction);
628 ignoreLoggerButton.setText(null);
629
630 expandButton.setFont(expandButton.getFont().deriveFont(Font.BOLD));
631 collapseButton.setFont(collapseButton.getFont().deriveFont(Font.BOLD));
632
633 editLoggerButton.setAction(editLoggerAction);
634 editLoggerButton.setText(null);
635 closeButton.setAction(closeAction);
636 closeButton.setText(null);
637
638 toolbar.add(expandButton);
639 toolbar.add(collapseButton);
640 toolbar.addSeparator();
641 toolbar.add(focusOnLoggerButton);
642 toolbar.add(ignoreLoggerButton);
643
644
645 toolbar.addSeparator();
646
647 toolbar.add(Box.createHorizontalGlue());
648 toolbar.add(closeButton);
649 toolbar.add(Box.createHorizontalStrut(5));
650 }
651
652
653
654
655
656
657 private Action createClearIgnoreListAction() {
658 Action action = new AbstractAction("Clear Ignore list", null) {
659 public void actionPerformed(ActionEvent e) {
660 ignoreLoggerButton.setSelected(false);
661 logTreeModel.reload();
662 hiddenSet.clear();
663 fireChangeEvent();
664 }
665 };
666
667 action.putValue(
668 Action.SHORT_DESCRIPTION,
669 "Removes all entries from the Ignore list so you can see their events in the view");
670
671 return action;
672 }
673
674
675
676
677
678
679 private Action createCloseAction() {
680 Action action = new AbstractAction() {
681 public void actionPerformed(ActionEvent e) {
682 preferenceModel.setLogTreePanelVisible(false);
683 }
684 };
685
686 action.putValue(Action.NAME, "Close");
687 action.putValue(Action.SHORT_DESCRIPTION, "Closes the Logger panel");
688 action.putValue(Action.SMALL_ICON, LineIconFactory.createCloseIcon());
689
690 return action;
691 }
692
693
694
695
696
697
698 private Action createCollapseAction() {
699 Action action = new AbstractAction() {
700 public void actionPerformed(ActionEvent e) {
701 collapseCurrentlySelectedNode();
702 }
703 };
704
705 action.putValue(Action.SMALL_ICON, LineIconFactory.createCollapseIcon());
706 action.putValue(Action.NAME, "Collapse Branch");
707 action.putValue(
708 Action.SHORT_DESCRIPTION,
709 "Collapses all the children of the currently selected node");
710 action.setEnabled(false);
711
712 return action;
713 }
714
715 private Action createEditLoggerAction() {
716 Action action = new AbstractAction() {
717 public void actionPerformed(ActionEvent e) {
718
719 }
720 };
721
722
723 action.putValue("enabled", Boolean.FALSE);
724
725 action.putValue(Action.NAME, "Edit filters/colors");
726 action.putValue(
727 Action.SHORT_DESCRIPTION,
728 "Allows you to specify filters and coloring for this Logger");
729 action.putValue(
730 Action.SMALL_ICON, new ImageIcon(ChainsawIcons.ICON_EDIT_RECEIVER));
731 action.setEnabled(false);
732
733 return action;
734 }
735
736
737
738
739
740
741
742 private Action createExpandAction() {
743 Action action = new AbstractAction() {
744 public void actionPerformed(ActionEvent e) {
745 expandCurrentlySelectedNode();
746 }
747 };
748
749 action.putValue(Action.SMALL_ICON, LineIconFactory.createExpandIcon());
750 action.putValue(Action.NAME, "Expand branch");
751 action.putValue(
752 Action.SHORT_DESCRIPTION,
753 "Expands all the child nodes of the currently selected node, recursively");
754 action.setEnabled(false);
755
756 return action;
757 }
758
759
760
761
762
763
764
765 private Action createFindNextAction() {
766 Action action = new AbstractAction() {
767 public void actionPerformed(ActionEvent e) {
768 findNextUsingCurrentlySelectedNode();
769 }
770 };
771
772 action.putValue(Action.NAME, "Find next");
773 action.putValue(
774 Action.SHORT_DESCRIPTION,
775 "Find using the selected node");
776 action.setEnabled(false);
777
778 return action;
779 }
780
781 private Action createSetRefineFocusAction() {
782 Action action = new AbstractAction() {
783 public void actionPerformed(ActionEvent e) {
784 setRefineFocusUsingCurrentlySelectedNode();
785 }
786 };
787
788 action.putValue(Action.NAME, "Set 'refine focus' to selected logger");
789 action.putValue(
790 Action.SHORT_DESCRIPTION,
791 "Refine focus on the selected node");
792 action.setEnabled(false);
793
794 return action;
795 }
796
797 private Action createUpdateRefineFocusAction() {
798 Action action = new AbstractAction() {
799 public void actionPerformed(ActionEvent e) {
800 updateRefineFocusUsingCurrentlySelectedNode();
801 }
802 };
803
804 action.putValue(Action.NAME, "Update 'refine focus' to include selected logger");
805 action.putValue(
806 Action.SHORT_DESCRIPTION,
807 "Add selected node to 'refine focus' field");
808 action.setEnabled(false);
809
810 return action;
811 }
812
813 private Action createUpdateFindAction() {
814 Action action = new AbstractAction() {
815 public void actionPerformed(ActionEvent e) {
816 updateFindUsingCurrentlySelectedNode();
817 }
818 };
819
820 action.putValue(Action.NAME, "Update 'find' to include selected logger");
821 action.putValue(
822 Action.SHORT_DESCRIPTION,
823 "Add selected node to 'find' field");
824 action.setEnabled(false);
825
826 return action;
827 }
828
829 private void updateFindUsingCurrentlySelectedNode() {
830 String selectedLogger = getCurrentlySelectedLoggerName();
831 TreePath[] paths = logTree.getSelectionPaths();
832
833 if (paths == null) {
834 return;
835 }
836 String currentFindText = logPanel.getFindText();
837 logPanel.setFindText(currentFindText + " || logger ~= " + selectedLogger);
838 }
839
840 private void updateRefineFocusUsingCurrentlySelectedNode() {
841 String selectedLogger = getCurrentlySelectedLoggerName();
842 TreePath[] paths = logTree.getSelectionPaths();
843
844 if (paths == null) {
845 return;
846 }
847 String currentFilterText = logPanel.getRefineFocusText();
848 logPanel.setRefineFocusText(currentFilterText + " || logger ~= " + selectedLogger);
849 }
850
851 private void setRefineFocusUsingCurrentlySelectedNode() {
852 String selectedLogger = getCurrentlySelectedLoggerName();
853 TreePath[] paths = logTree.getSelectionPaths();
854
855 if (paths == null) {
856 return;
857 }
858 logPanel.setRefineFocusText("logger ~= " + selectedLogger);
859 }
860
861 private Action createDefineColorRuleForLoggerAction() {
862 Action action = new AbstractAction() {
863 public void actionPerformed(ActionEvent e) {
864 String selectedLogger = getCurrentlySelectedLoggerName();
865 TreePath[] paths = logTree.getSelectionPaths();
866
867 if (paths == null) {
868 return;
869 }
870 Color c = JColorChooser.showDialog(getRootPane(), "Choose a color", Color.red);
871 if (c != null) {
872 String expression = "logger like '^" + selectedLogger + ".*'";
873 colorizer.addRule(ChainsawConstants.DEFAULT_COLOR_RULE_NAME, new ColorRule(expression,
874 ExpressionRule.getRule(expression), c, ChainsawConstants.COLOR_DEFAULT_FOREGROUND));
875 }
876 }
877 };
878
879 action.putValue(Action.NAME, "Define color rule for selected logger");
880 action.putValue(
881 Action.SHORT_DESCRIPTION,
882 "Define color rule for logger");
883 action.setEnabled(false);
884 return action;
885 }
886
887
888
889
890
891
892
893 private Action createClearFindNextAction() {
894 Action action = new AbstractAction() {
895 public void actionPerformed(ActionEvent e) {
896 clearFindNext();
897 }
898 };
899
900 action.putValue(Action.NAME, "Clear find field");
901 action.putValue(
902 Action.SHORT_DESCRIPTION,
903 "Clear the find field");
904 action.setEnabled(false);
905
906 return action;
907 }
908
909 private Action createClearRefineFocusAction() {
910 Action action = new AbstractAction() {
911 public void actionPerformed(ActionEvent e) {
912 clearRefineFocus();
913 }
914 };
915
916 action.putValue(Action.NAME, "Clear 'refine focus' field");
917 action.putValue(
918 Action.SHORT_DESCRIPTION,
919 "Clear the refine focus field");
920 action.setEnabled(false);
921
922 return action;
923 }
924
925
926
927
928
929
930 private Action createFocusOnAction() {
931 final Action action = new AbstractAction() {
932 public void actionPerformed(ActionEvent e) {
933 toggleFocusOnState();
934 }
935 };
936
937 action.putValue(Action.NAME, "Focus");
938 action.putValue(
939 Action.SHORT_DESCRIPTION,
940 "Allows you to Focus on the selected logger by setting a filter that discards all but this Logger");
941 action.putValue(
942 Action.SMALL_ICON, new ImageIcon(ChainsawIcons.WINDOW_ICON));
943
944 action.setEnabled(false);
945
946 return action;
947 }
948
949
950
951
952
953
954 private Action createIgnoreAllAction() {
955 Action action =
956 new AbstractAction(
957 "Ignore loggers below selection") {
958 public void actionPerformed(ActionEvent e) {
959
960 TreePath[] paths = logTree.getSelectionPaths();
961
962 StringBuilder parentPathString = new StringBuilder();
963 DefaultMutableTreeNode root;
964 if ((paths == null) || (paths.length == 0)) {
965 root = (DefaultMutableTreeNode) logTreeModel.getRoot();
966 } else {
967 root = (DefaultMutableTreeNode) logTree.getSelectionPath().getLastPathComponent();
968 TreeNode[] path = root.getPath();
969
970 for (int i = 1; i < path.length; i++) {
971 if (i > 1) {
972 parentPathString.append(".");
973 }
974 parentPathString.append(path[i].toString());
975 }
976 if (!(parentPathString.toString().equals(""))) {
977 parentPathString.append(".");
978 }
979 }
980 Enumeration topLevelLoggersEnumeration = root.children();
981 Set topLevelLoggersSet = new HashSet();
982 while (topLevelLoggersEnumeration.hasMoreElements()) {
983 String thisLogger = topLevelLoggersEnumeration.nextElement().toString();
984 topLevelLoggersSet.add(parentPathString + thisLogger);
985 }
986 if (topLevelLoggersSet.size() > 0) {
987 ignore(topLevelLoggersSet);
988 }
989
990 logTreeModel.nodeChanged(root);
991 ignoreLoggerButton.setSelected(false);
992 focusOnAction.setEnabled(false);
993 popupMenu.hideCheck.setSelected(false);
994 fireChangeEvent();
995 }
996 };
997
998 action.putValue(
999 Action.SHORT_DESCRIPTION,
1000 "Adds all loggers to your Ignore list (unhide loggers you want to see in the view)");
1001
1002 return action;
1003 }
1004
1005
1006
1007
1008
1009
1010 private Action createIgnoreAction() {
1011 Action action =
1012 new AbstractAction(
1013 "Ignore this Logger", new ImageIcon(ChainsawIcons.ICON_COLLAPSE)) {
1014 public void actionPerformed(ActionEvent e) {
1015 String logger = getCurrentlySelectedLoggerName();
1016
1017 if (logger != null) {
1018 toggleHiddenLogger(logger);
1019 logTreeModel.nodeChanged(
1020 (TreeNode) logTree.getSelectionPath().getLastPathComponent());
1021 ignoreLoggerButton.setSelected(hiddenSet.contains(logger));
1022 focusOnAction.setEnabled(!hiddenSet.contains(logger));
1023 popupMenu.hideCheck.setSelected(hiddenSet.contains(logger));
1024 }
1025
1026 fireChangeEvent();
1027 }
1028 };
1029
1030 action.putValue(
1031 Action.SHORT_DESCRIPTION,
1032 "Adds the selected Logger to your Ignore list, filtering those events from view");
1033
1034 return action;
1035 }
1036
1037 private void ensureRootExpanded() {
1038 logger.debug("Ensuring Root node is expanded.");
1039
1040 final DefaultMutableTreeNode root =
1041 (DefaultMutableTreeNode) logTreeModel.getRoot();
1042 SwingUtilities.invokeLater(() -> logTree.expandPath(new TreePath(root)));
1043 }
1044
1045 private void findNextUsingCurrentlySelectedNode() {
1046 String selectedLogger = getCurrentlySelectedLoggerName();
1047 TreePath[] paths = logTree.getSelectionPaths();
1048
1049 if (paths == null) {
1050 return;
1051 }
1052 logPanel.setFindText("logger like '^" + selectedLogger + ".*'");
1053 }
1054
1055 private void clearFindNext() {
1056 logPanel.setFindText("");
1057 }
1058
1059 private void clearRefineFocus() {
1060 logPanel.setRefineFocusText("");
1061 }
1062
1063
1064
1065
1066
1067 private void expandCurrentlySelectedNode() {
1068 TreePath[] paths = logTree.getSelectionPaths();
1069
1070 if (paths == null) {
1071 return;
1072 }
1073
1074 logger.debug("Expanding all children of selected node");
1075
1076 for (TreePath path : paths) {
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091 DefaultMutableTreeNode treeNode =
1092 (DefaultMutableTreeNode) path.getLastPathComponent();
1093
1094 Enumeration depthEnum = treeNode.depthFirstEnumeration();
1095
1096 if (!depthEnum.hasMoreElements()) {
1097 break;
1098 }
1099
1100 List<Integer> depths = new ArrayList<>();
1101
1102 while (depthEnum.hasMoreElements()) {
1103 depths.add(
1104 ((DefaultMutableTreeNode) depthEnum.nextElement()).getDepth());
1105 }
1106
1107 Collections.sort(depths);
1108 Collections.reverse(depths);
1109
1110 int maxDepth = depths.get(0);
1111
1112 if (maxDepth > WARN_DEPTH) {
1113 logger.warn("Should warn user, depth=" + maxDepth);
1114 }
1115
1116 depthEnum = treeNode.depthFirstEnumeration();
1117
1118 while (depthEnum.hasMoreElements()) {
1119 DefaultMutableTreeNode node =
1120 (DefaultMutableTreeNode) depthEnum.nextElement();
1121
1122 if (node.isLeaf() && node.getParent() != null) {
1123 TreeNode[] nodes =
1124 ((DefaultMutableTreeNode) node.getParent()).getPath();
1125 TreePath treePath = new TreePath(nodes);
1126
1127 logger.debug("Expanding path:" + treePath);
1128
1129 logTree.expandPath(treePath);
1130 }
1131 }
1132 }
1133 }
1134
1135 private void fireChangeEvent() {
1136 ChangeListener[] listeners =
1137 listenerList.getListeners(ChangeListener.class);
1138 ChangeEvent e = null;
1139
1140 for (ChangeListener listener : listeners) {
1141 if (e == null) {
1142 e = new ChangeEvent(this);
1143 }
1144
1145 listener.stateChanged(e);
1146 }
1147 }
1148
1149 private void reconfigureMenuText() {
1150 String logger = getCurrentlySelectedLoggerName();
1151
1152 if ((logger == null) || (logger.length() == 0)) {
1153 focusOnAction.putValue(Action.NAME, "Focus On...");
1154 hideAction.putValue(Action.NAME, "Ignore...");
1155 findAction.putValue(Action.NAME, "Find...");
1156 setRefineFocusAction.putValue(Action.NAME, "Set refine focus field");
1157 updateRefineFocusAction.putValue(Action.NAME, "Add to refine focus field");
1158 updateFindAction.putValue(Action.NAME, "Add to find field");
1159 defineColorRuleForLoggerAction.putValue(Action.NAME, "Define color rule");
1160 } else {
1161 focusOnAction.putValue(Action.NAME, "Focus On '" + logger + "'");
1162 hideAction.putValue(Action.NAME, "Ignore '" + logger + "'");
1163 findAction.putValue(Action.NAME, "Find '" + logger + "'");
1164 setRefineFocusAction.putValue(Action.NAME, "Set refine focus field to '" + logger + "'");
1165 updateRefineFocusAction.putValue(Action.NAME, "Add '" + logger + "' to 'refine focus' field");
1166 updateFindAction.putValue(Action.NAME, "Add '" + logger + "' to 'find' field");
1167 defineColorRuleForLoggerAction.putValue(Action.NAME, "Define color rule for '" + logger + "'");
1168 }
1169
1170
1171 hideSubLoggersAction.putValue(Action.NAME, "Ignore loggers below selection");
1172 focusOnLoggerButton.setText(null);
1173 ignoreLoggerButton.setText(null);
1174 }
1175
1176
1177
1178
1179
1180 private void setupListeners() {
1181 logTree.addMouseMotionListener(new MouseKeyIconListener());
1182
1183
1184
1185
1186 logTree.addTreeSelectionListener(e -> {
1187 TreePath path = e.getNewLeadSelectionPath();
1188 TreeNode node = null;
1189
1190 if (path != null) {
1191 node = (TreeNode) path.getLastPathComponent();
1192 }
1193 boolean focusOnSelected = isFocusOnSelected();
1194
1195 currentlySelectedLoggerName = getCurrentlySelectedLoggerName();
1196 focusOnAction.setEnabled(
1197 (path != null) && (node != null) && (node.getParent() != null)
1198 && !hiddenSet.contains(currentlySelectedLoggerName));
1199 hideAction.setEnabled(
1200 (path != null) && (node != null) && (node.getParent() != null));
1201 if (!focusOnAction.isEnabled()) {
1202 setFocusOnSelected(false);
1203 } else {
1204 }
1205
1206 expandAction.setEnabled(path != null);
1207 findAction.setEnabled(path != null);
1208 clearFindNextAction.setEnabled(true);
1209 defineColorRuleForLoggerAction.setEnabled(path != null);
1210 setRefineFocusAction.setEnabled(path != null);
1211 updateRefineFocusAction.setEnabled(path != null);
1212 updateFindAction.setEnabled(path != null);
1213 clearRefineFocusAction.setEnabled(true);
1214
1215 if (currentlySelectedLoggerName != null) {
1216 boolean isHidden = hiddenSet.contains(currentlySelectedLoggerName);
1217 popupMenu.hideCheck.setSelected(isHidden);
1218 ignoreLoggerButton.setSelected(isHidden);
1219 }
1220
1221 collapseAction.setEnabled(path != null);
1222
1223 reconfigureMenuText();
1224 if (isFocusOnSelected()) {
1225 fireChangeEvent();
1226 }
1227
1228 if (focusOnSelected && !isFocusOnSelected()) {
1229 fireChangeEvent();
1230 }
1231
1232 logPanel.repaint();
1233 });
1234
1235 logTree.addMouseListener(popupListener);
1236
1237
1238
1239
1240
1241
1242 focusOnAction.addPropertyChangeListener(evt -> {
1243 popupMenu.focusOnCheck.setSelected(isFocusOnSelected());
1244 focusOnLoggerButton.setSelected(isFocusOnSelected());
1245
1246 if (logTree.getSelectionPath() != null) {
1247 logTreeModel.nodeChanged(
1248 (TreeNode) logTree.getSelectionPath().getLastPathComponent());
1249 }
1250 });
1251
1252 hideAction.addPropertyChangeListener(evt -> {
1253 if (logTree.getSelectionPath() != null) {
1254 logTreeModel.nodeChanged(
1255 (TreeNode) logTree.getSelectionPath().getLastPathComponent());
1256 }
1257 });
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279 logTree.addMouseListener(new MouseFocusOnListener());
1280
1281
1282
1283
1284
1285 addChangeListener(evt -> {
1286 visibilityRuleDelegate.firePropertyChange("rule", null, null);
1287 updateDisplay();
1288 });
1289
1290 visibilityRuleDelegate.addPropertyChangeListener(event -> {
1291 if (event.getPropertyName().equals("hiddenSet")) {
1292 updateDisplay();
1293 }
1294 });
1295 }
1296
1297 private void updateDisplay() {
1298 updateHiddenSetModels();
1299 updateIgnoreSummary();
1300 updateIgnoreExpressionSummary();
1301 updateAlwaysDisplayExpressionSummary();
1302 }
1303
1304 private void updateHiddenSetModels() {
1305 DefaultListModel model = (DefaultListModel) ignoreList.getModel();
1306 model.clear();
1307 List sortedIgnoreList = new ArrayList(hiddenSet);
1308 Collections.sort(sortedIgnoreList);
1309
1310 for (Object aSortedIgnoreList : sortedIgnoreList) {
1311 String string = (String) aSortedIgnoreList;
1312 model.addElement(string);
1313 }
1314
1315
1316
1317 }
1318
1319 private void updateIgnoreSummary() {
1320 ignoreSummary.setText(ignoreList.getModel().getSize() + " hidden loggers");
1321 }
1322
1323 private void updateIgnoreExpressionSummary() {
1324 ignoreExpressionSummary.setText(ignoreExpressionRule != null ? "Ignore (set)" : "Ignore (unset)");
1325 }
1326
1327 private void updateAlwaysDisplayExpressionSummary() {
1328 alwaysDisplayExpressionSummary.setText(alwaysDisplayExpressionRule != null ? "Always displayed (set)" : "Always displayed (unset)");
1329 }
1330
1331 private void toggleFocusOnState() {
1332 setFocusOnSelected(!isFocusOnSelected());
1333 fireChangeEvent();
1334 }
1335
1336 public Collection getHiddenSet() {
1337 return Collections.unmodifiableSet(hiddenSet);
1338 }
1339
1340 public String getHiddenExpression() {
1341 String text = ignoreExpressionEntryField.getText();
1342 if (text == null || text.trim().equals("")) {
1343 return null;
1344 }
1345 return text.trim();
1346 }
1347
1348 public void setHiddenExpression(String hiddenExpression) {
1349 ignoreExpressionEntryField.setText(hiddenExpression);
1350 updateIgnoreExpression(hiddenExpression);
1351 }
1352
1353 public String getAlwaysDisplayExpression() {
1354 String text = alwaysDisplayExpressionEntryField.getText();
1355 if (text == null || text.trim().equals("")) {
1356 return null;
1357 }
1358 return text.trim();
1359 }
1360
1361 public void setAlwaysDisplayExpression(String alwaysDisplayExpression) {
1362 alwaysDisplayExpressionEntryField.setText(alwaysDisplayExpression);
1363 updateAlwaysDisplayExpression(alwaysDisplayExpression);
1364 }
1365
1366 public void loggerNameAdded(String loggerName) {
1367
1368 }
1369
1370 public void reset() {
1371 expandRootLatch = false;
1372
1373 final String logger = currentlySelectedLoggerName;
1374 final boolean focusOnSelected = isFocusOnSelected();
1375 if (logger == null || !focusOnSelected) {
1376 return;
1377 }
1378
1379
1380 logTreeModel.loggerNameAdded(logger);
1381 EventQueue.invokeLater(() -> setFocusOn(logger));
1382 }
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393 private class LoggerNameTreeCellRenderer extends DefaultTreeCellRenderer {
1394
1395
1396
1397 private LoggerNameTreeCellRenderer() {
1398 super();
1399
1400
1401
1402 setLeafIcon(null);
1403 setOpaque(false);
1404 }
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424 public Component getTreeCellRendererComponent(
1425 JTree tree, Object value, boolean sel, boolean expanded, boolean leaf,
1426 int row, boolean focus) {
1427 JLabel component =
1428 (JLabel) super.getTreeCellRendererComponent(
1429 tree, value, sel, expanded, leaf, row, focus);
1430
1431 Font originalFont = new Font(component.getFont().getName(), component.getFont().getStyle(), component.getFont().getSize());
1432
1433 int style = Font.PLAIN;
1434
1435 if (sel && focusOnLoggerButton.isSelected()) {
1436 style = style | Font.BOLD;
1437 }
1438
1439 String logger =
1440 getLoggerName(
1441 new TreePath(((DefaultMutableTreeNode) value).getPath()));
1442
1443 if (hiddenSet.contains(logger)) {
1444
1445
1446 style = style | Font.ITALIC;
1447
1448
1449 } else {
1450
1451
1452 }
1453
1454 if (originalFont != null) {
1455 Font font2 = originalFont.deriveFont(style);
1456
1457 if (font2 != null) {
1458 component.setFont(font2);
1459 }
1460 }
1461
1462 return component;
1463 }
1464 }
1465
1466 private class LoggerTreePopupMenu extends JPopupMenu {
1467
1468
1469 JCheckBoxMenuItem focusOnCheck = new JCheckBoxMenuItem();
1470 JCheckBoxMenuItem hideCheck = new JCheckBoxMenuItem();
1471
1472
1473
1474 private LoggerTreePopupMenu() {
1475 initMenu();
1476 }
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491 public void show(Component invoker, int x, int y) {
1492 DefaultMutableTreeNode node =
1493 (DefaultMutableTreeNode) logTree.getLastSelectedPathComponent();
1494
1495 if (node == null) {
1496 return;
1497 }
1498
1499 super.show(invoker, x, y);
1500 }
1501
1502
1503
1504
1505 private void initMenu() {
1506 focusOnCheck.setAction(focusOnAction);
1507 hideCheck.setAction(hideAction);
1508 add(expandAction);
1509 add(collapseAction);
1510 addSeparator();
1511 add(focusOnCheck);
1512 add(hideCheck);
1513 addSeparator();
1514 add(setRefineFocusAction);
1515 add(updateRefineFocusAction);
1516 add(clearRefineFocusAction);
1517 addSeparator();
1518 add(findAction);
1519 add(updateFindAction);
1520 add(clearFindNextAction);
1521
1522 addSeparator();
1523 add(defineColorRuleForLoggerAction);
1524 addSeparator();
1525
1526 add(hideSubLoggersAction);
1527 add(clearIgnoreListAction);
1528 }
1529 }
1530
1531 private final class MouseFocusOnListener extends MouseAdapter {
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543 public void mouseClicked(MouseEvent e) {
1544 if (
1545 (e.getClickCount() > 1)
1546 && ((e.getModifiers() & InputEvent.CTRL_MASK) > 0)
1547 && ((e.getModifiers() & InputEvent.SHIFT_MASK) > 0)) {
1548 ignoreLoggerAtPoint(e.getPoint());
1549 e.consume();
1550 fireChangeEvent();
1551 } else if (
1552 (e.getClickCount() > 1)
1553 && ((e.getModifiers() & InputEvent.CTRL_MASK) > 0)) {
1554 focusAnLoggerAtPoint(e.getPoint());
1555 e.consume();
1556 fireChangeEvent();
1557 }
1558 }
1559
1560
1561
1562
1563
1564
1565 private void focusAnLoggerAtPoint(Point point) {
1566 String logger = getLoggerAtPoint(point);
1567
1568 if (logger != null) {
1569 toggleFocusOnState();
1570 }
1571 }
1572
1573
1574
1575
1576
1577
1578
1579 private String getLoggerAtPoint(Point point) {
1580 TreePath path = logTree.getPathForLocation(point.x, point.y);
1581
1582 if (path != null) {
1583 return getLoggerName(path);
1584 }
1585
1586 return null;
1587 }
1588
1589
1590
1591
1592
1593
1594 private void ignoreLoggerAtPoint(Point point) {
1595 String logger = getLoggerAtPoint(point);
1596
1597 if (logger != null) {
1598 toggleHiddenLogger(logger);
1599 fireChangeEvent();
1600 }
1601 }
1602 }
1603
1604 private final class MouseKeyIconListener extends MouseMotionAdapter
1605 implements MouseMotionListener {
1606
1607
1608 Cursor focusOnCursor =
1609 Toolkit.getDefaultToolkit().createCustomCursor(
1610 ChainsawIcons.FOCUS_ON_ICON.getImage(), new Point(10, 10), "");
1611 Cursor ignoreCursor =
1612 Toolkit.getDefaultToolkit().createCustomCursor(
1613 ChainsawIcons.IGNORE_ICON.getImage(), new Point(10, 10), "");
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626 public void mouseMoved(MouseEvent e) {
1627
1628 if (
1629 ((e.getModifiers() & InputEvent.CTRL_MASK) > 0)
1630 && ((e.getModifiers() & InputEvent.SHIFT_MASK) > 0)) {
1631 logTree.setCursor(ignoreCursor);
1632 } else if ((e.getModifiers() & InputEvent.CTRL_MASK) > 0) {
1633 logTree.setCursor(focusOnCursor);
1634 } else {
1635 logTree.setCursor(Cursor.getDefaultCursor());
1636 }
1637 }
1638 }
1639
1640 class VisibilityRuleDelegate extends AbstractRule {
1641 public boolean evaluate(LoggingEvent e, Map matches) {
1642 String currentlySelectedLoggerName = getCurrentlySelectedLoggerName();
1643 boolean hiddenLogger = e.getLoggerName() != null && isHiddenLogger(e.getLoggerName());
1644 boolean hiddenExpression = (ignoreExpressionRule != null && ignoreExpressionRule.evaluate(e, null));
1645 boolean alwaysDisplayExpression = (alwaysDisplayExpressionRule != null && alwaysDisplayExpressionRule.evaluate(e, null));
1646 boolean hidden = (!alwaysDisplayExpression) && (hiddenLogger || hiddenExpression);
1647 if (currentlySelectedLoggerName == null) {
1648
1649 return !hidden;
1650 }
1651 boolean result = (e.getLoggerName() != null) && !hidden;
1652
1653 if (result && isFocusOnSelected()) {
1654 result = (e.getLoggerName() != null && (e.getLoggerName().startsWith(currentlySelectedLoggerName + ".") || e.getLoggerName().endsWith(currentlySelectedLoggerName)));
1655 }
1656
1657 return result;
1658 }
1659
1660 public void firePropertyChange(String propertyName, Object oldVal, Object newVal) {
1661 super.firePropertyChange(propertyName, oldVal, newVal);
1662 }
1663 }
1664
1665 }