KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > de > qfs > apps > qflog > logview > LogFilterView


1 // {{{ copyright
2

3 /********************************************************************
4  *
5  * $Id: LogFilterView.java,v 1.16 2000/07/05 14:07:44 gs Exp $
6  *
7  * The contents of this file are subject to the Mozilla Public
8  * License Version 1.1 (the "License"); you may not use this file
9  * except in compliance with the License. You may obtain a copy of
10  * the License at http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS
13  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14  * implied. See the License for the specific language governing
15  * rights and limitations under the License.
16  *
17  * The Original Code is qfs.de code.
18  *
19  * The Initial Developer of the Original Code is Gregor Schmid.
20  * Portions created by Gregor Schmid are
21  * Copyright (C) 1999 Quality First Software, Gregor Schmid.
22  * All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  *******************************************************************/

27
28 // }}}
29

30 package de.qfs.apps.qflog.logview;
31
32 // {{{ imports
33

34 import java.awt.BorderLayout JavaDoc;
35 import java.awt.Color JavaDoc;
36 import java.awt.Component JavaDoc;
37 import java.awt.event.ActionEvent JavaDoc;
38 import java.awt.event.KeyEvent JavaDoc;
39 import java.awt.event.MouseAdapter JavaDoc;
40 import java.awt.event.MouseEvent JavaDoc;
41
42 import java.util.ResourceBundle JavaDoc;
43
44 import javax.swing.Action JavaDoc;
45 import javax.swing.AbstractAction JavaDoc;
46 import javax.swing.BorderFactory JavaDoc;
47 import javax.swing.ButtonModel JavaDoc;
48 import javax.swing.Icon JavaDoc;
49 import javax.swing.KeyStroke JavaDoc;
50 import javax.swing.JCheckBoxMenuItem JavaDoc;
51 import javax.swing.JLabel JavaDoc;
52 import javax.swing.JMenu JavaDoc;
53 import javax.swing.JMenuItem JavaDoc;
54 import javax.swing.JPanel JavaDoc;
55 import javax.swing.JPopupMenu JavaDoc;
56 import javax.swing.JScrollPane JavaDoc;
57 import javax.swing.JTree JavaDoc;
58 import javax.swing.SwingUtilities JavaDoc;
59 import javax.swing.tree.DefaultTreeCellRenderer JavaDoc;
60 import javax.swing.tree.TreePath JavaDoc;
61
62 import de.qfs.lib.gui.SwingUtil;
63 import de.qfs.lib.gui.WindowsTreeCellRenderer;
64 import de.qfs.lib.log.Log;
65 import de.qfs.lib.log.Logger;
66 import de.qfs.lib.util.MapResourceBundle;
67
68 // }}}
69

70 /**
71  * A LogFilterView is used for display and manipulation of various filters,
72  * thus modifying the display of log messages in a LogTableView. It is not
73  * very useful on its own, but usually used as part of the {@link LogView
74  * LogView} component, that integrates the LogFilterView with other logging
75  * related views. <p>
76  *
77  * The LogFilterView must be initialized by a call to {@link #init init} after
78  * creation. It uses its own resources for localization, which can be modified
79  * via {@link #setResources setResources}. <p>
80  *
81  * The LogLevelView does not have any {@link Configurable Configurable} parts
82  * except for its {@link LogFilterTreeModel LogFilterTreeModel}, which must be
83  * handled by the caller if its state should be saved, unless the
84  * LogFilterView is used as part of a LogView. <p>
85  *
86  * @author Gregor Schmid
87  * @version $Revision: 1.16 $
88  */

89 public class LogFilterView
90     extends JPanel JavaDoc
91 {
92     // {{{ variables
93

94     /**
95      * The Logger used for logging.
96      */

97     private final static Logger logger = new Logger (LogFilterView.class);
98
99     /**
100      * The model of log levels.
101      */

102     private transient LogFilterTreeModel model;
103
104     /**
105      * The tree component.
106      */

107     private transient JTree JavaDoc tree;
108
109     /**
110      * The default resources to use.
111      */

112     private static MapResourceBundle defaultResources;
113
114     /**
115      * The resources to use.
116      */

117     private transient MapResourceBundle resources;
118
119     /**
120      * Popup menu for context menu.
121      */

122     private transient JPopupMenu JavaDoc popup;
123
124     /**
125      * Mouse listener for the popup menu.
126      */

127     private transient PopupListener popupListener;
128
129     /**
130      * Whether logging is enabled (true) or disabled (false);
131      */

132     private boolean logging;
133
134     /**
135      * Button model for the toggleExtraFilter menu items.
136      */

137     private ButtonModel JavaDoc toggleButtonModel;
138
139     //----------------------------------------------------------------------
140
// The actions
141
//----------------------------------------------------------------------
142
/**
143      * Remove log levels (non recursive).
144      */

145     private Action JavaDoc removeAction;
146
147     /**
148      * Remove log levels (recursive).
149      */

150     private Action JavaDoc removeRecursiveAction;
151
152     /**
153      * Set log levels to Log.ERR
154      */

155     private Action JavaDoc setERRAction;
156
157     /**
158      * Set log levels to Log.ERRDETAIL
159      */

160     private Action JavaDoc setERRDETAILAction;
161
162     /**
163      * Set log levels to Log.WRN
164      */

165     private Action JavaDoc setWRNAction;
166
167     /**
168      * Set log levels to Log.WRNDETAIL
169      */

170     private Action JavaDoc setWRNDETAILAction;
171
172     /**
173      * Set log levels to Log.MSG
174      */

175     private Action JavaDoc setMSGAction;
176
177     /**
178      * Set log levels to Log.MSGDETAIL
179      */

180     private Action JavaDoc setMSGDETAILAction;
181
182     /**
183      * Set log levels to Log.MTD
184      */

185     private Action JavaDoc setMTDAction;
186
187     /**
188      * Set log levels to Log.MTDDETAIL
189      */

190     private Action JavaDoc setMTDDETAILAction;
191
192     /**
193      * Set log levels to Log.DBG
194      */

195     private Action JavaDoc setDBGAction;
196
197     /**
198      * Set log levels to Log.DBGDETAIL
199      */

200     private Action JavaDoc setDBGDETAILAction;
201
202     /**
203      * Toggle extra filters.
204      */

205     private Action JavaDoc toggleFilterAction;
206
207     /**
208      * Add an extra filter.
209      */

210     private Action JavaDoc addFilterAction;
211
212     /**
213      * Remove an extra filter.
214      */

215     private Action JavaDoc removeFilterAction;
216
217     /**
218      * Remove all extra filters.
219      */

220     private Action JavaDoc clearFilterAction;
221
222     /**
223      * Expand path and all descendants.
224      */

225     private Action JavaDoc expandAllAction;
226
227     /**
228      * Collapse path and all descendants.
229      */

230     private Action JavaDoc collapseAllAction;
231
232     /**
233      * Display all nodes with a non-null level.
234      */

235     private Action JavaDoc showSetLevelsAction;
236
237     // }}}
238

239     // {{{ constructor
240

241     /**
242      * Create a new LogFilterView.
243      *
244      * @param model The mode to use for the tree.
245      */

246     public LogFilterView(LogFilterTreeModel model)
247     {
248         this.model = model;
249         setupResources();
250         model.setRootName(resources.getString("logFilterView.root.name",
251                                               "default"));
252     }
253
254     // }}}
255

256     // {{{ setLoggingEnabled
257

258     /**
259      * Enable or disable logging output caused directly or indirectly by
260      * LogFilterView methods. If logging is disabled, all calls to methods
261      * that might create log messages will be protected with {@link
262      * de.qfs.lib.log.Log#excludeThread de.qfs.lib.log.Log.excludeThread}.
263      * This is necessary, if the LogFilterTreeModel is used inside the
264      * application whose logs it is supposed to filter. <p>
265      *
266      * The default value is false.
267      *
268      * @param enable True to enable logging, false to disable it.
269      */

270     public final void setLoggingEnabled(boolean enable)
271     {
272         logging = enable;
273         model.setLoggingEnabled(enable);
274     }
275
276     // }}}
277

278     //----------------------------------------------------------------------
279
// Initialization
280
//----------------------------------------------------------------------
281
// {{{ init
282

283     /**
284      * Initialize the components of the view. This method is not called by the
285      * constructor to enable further configuration like setting the resources,
286      * before the view is initialized.
287      */

288     public void init()
289     {
290         boolean excluded = !logging;
291         if (excluded) {
292             Log.excludeThread();
293         }
294         try {
295             setLayout(new BorderLayout JavaDoc ());
296             setBorder(null);
297
298             JPanel JavaDoc top = new JPanel JavaDoc ();
299             top.setLayout(new BorderLayout JavaDoc ());
300             top.setBorder(null);
301
302             String JavaDoc title = resources.getString("logFilterView.title", "Filter");
303             JLabel JavaDoc titleLabel = new JLabel JavaDoc (title);
304             titleLabel.setBorder(BorderFactory.createEtchedBorder());
305             top.add(titleLabel, BorderLayout.NORTH);
306
307             tree = new JTree JavaDoc (model) {
308                 // public boolean hasBeenExpanded(TreePath path) {
309
// return false;
310
// }
311
};
312             tree.setBorder(null);
313             tree.setCellRenderer(new Renderer JavaDoc ());
314
315             JScrollPane JavaDoc treePane = new JScrollPane JavaDoc (tree);
316             SwingUtil.constrainScroll(treePane);
317             treePane.setBorder(BorderFactory.createLoweredBevelBorder());
318             top.add(treePane, BorderLayout.CENTER);
319             add(top, BorderLayout.CENTER);
320
321             // Default selection
322
tree.setSelectionRow(0);
323
324             // setup and bind actions
325
setupActions();
326
327             tree.registerKeyboardAction
328                 (removeAction, "remove",
329                  KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0),
330                  tree.WHEN_FOCUSED);
331             tree.registerKeyboardAction
332                 (removeRecursiveAction, "removeRecursive",
333                  KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, KeyEvent.CTRL_MASK),
334                  tree.WHEN_FOCUSED);
335
336             tree.registerKeyboardAction
337                 (setERRAction, "setERR",
338                  KeyStroke.getKeyStroke(KeyEvent.VK_1, 0),
339                  tree.WHEN_FOCUSED);
340             tree.registerKeyboardAction
341                 (setERRDETAILAction, "setERRDETAIL",
342                  KeyStroke.getKeyStroke(KeyEvent.VK_2, 0),
343                  tree.WHEN_FOCUSED);
344             tree.registerKeyboardAction
345                 (setWRNAction, "setWRN",
346                  KeyStroke.getKeyStroke(KeyEvent.VK_3, 0),
347                  tree.WHEN_FOCUSED);
348             tree.registerKeyboardAction
349                 (setWRNDETAILAction, "setWRNDETAIL",
350                  KeyStroke.getKeyStroke(KeyEvent.VK_4, 0),
351                  tree.WHEN_FOCUSED);
352             tree.registerKeyboardAction
353                 (setMSGAction, "MSGERR",
354                  KeyStroke.getKeyStroke(KeyEvent.VK_5, 0),
355                  tree.WHEN_FOCUSED);
356             tree.registerKeyboardAction
357                 (setMSGDETAILAction, "setMSGDETAIL",
358                  KeyStroke.getKeyStroke(KeyEvent.VK_6, 0),
359                  tree.WHEN_FOCUSED);
360             tree.registerKeyboardAction
361                 (setMTDAction, "setMTD",
362                  KeyStroke.getKeyStroke(KeyEvent.VK_7, 0),
363                  tree.WHEN_FOCUSED);
364             tree.registerKeyboardAction
365                 (setMTDDETAILAction, "setMTDDETAIL",
366                  KeyStroke.getKeyStroke(KeyEvent.VK_8, 0),
367                  tree.WHEN_FOCUSED);
368             tree.registerKeyboardAction
369                 (setDBGAction, "setDBG",
370                  KeyStroke.getKeyStroke(KeyEvent.VK_9, 0),
371                  tree.WHEN_FOCUSED);
372             tree.registerKeyboardAction
373                 (setDBGDETAILAction, "setDBGDETAIL",
374                  KeyStroke.getKeyStroke(KeyEvent.VK_0, 0),
375                  tree.WHEN_FOCUSED);
376
377             tree.registerKeyboardAction
378                 (toggleFilterAction, "filter",
379                  KeyStroke.getKeyStroke(KeyEvent.VK_F, KeyEvent.CTRL_MASK),
380                  tree.WHEN_FOCUSED);
381
382             tree.registerKeyboardAction
383                 (addFilterAction, "addFilter",
384                  KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.CTRL_MASK),
385                  tree.WHEN_FOCUSED);
386
387             tree.registerKeyboardAction
388                 (removeFilterAction, "removeFilter",
389                  KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.CTRL_MASK),
390                  tree.WHEN_FOCUSED);
391
392             tree.registerKeyboardAction
393                 (clearFilterAction, "clearFilter",
394                  KeyStroke.getKeyStroke(KeyEvent.VK_K, KeyEvent.CTRL_MASK),
395                  tree.WHEN_FOCUSED);
396
397             tree.registerKeyboardAction
398                 (expandAllAction, "expandAll",
399                  KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.ALT_MASK),
400                  tree.WHEN_FOCUSED);
401
402             tree.registerKeyboardAction
403                 (collapseAllAction, "collapseAll",
404                  KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, KeyEvent.ALT_MASK),
405                  tree.WHEN_FOCUSED);
406
407             // popup menu
408
popup = new JPopupMenu JavaDoc ();
409             fillMenu(popup);
410             popupListener = new PopupListener ();
411             tree.addMouseListener(popupListener);
412
413             showSetLevels();
414
415         } finally {
416             if (excluded) {
417                 Log.includeThread();
418             }
419         }
420     }
421
422     // }}}
423
// {{{ cleanup
424

425     /**
426      * Try to remove everything that might prevent the LogFilterView from
427      * being garbage collected.
428      */

429     public void cleanup()
430     {
431         if (logging && logger.level >= Log.MTD) {
432             logger.log(Log.MTD, "cleanup()", "");
433         }
434
435         SwingUtil.cleanup(this);
436
437         tree.removeMouseListener(popupListener);
438         popupListener = null;
439         SwingUtil.cleanup(popup);
440         popup = null;
441
442         tree.resetKeyboardActions();
443         tree = null;
444         resources = null;
445
446         model.cleanup();
447         model = null;
448     }
449
450     // }}}
451
// {{{ finalize
452

453     /**
454      * Finalize the LogFilterView.
455      */

456     public void finalize()
457     {
458         if (logging && logger.level >= Log.MTD) {
459             logger.log(Log.MTD, "finalize()", "");
460         }
461     }
462
463     // }}}
464

465     //----------------------------------------------------------------------
466
// Access
467
//----------------------------------------------------------------------
468
// {{{ getModel
469

470     /**
471      * Get the view's associated LogFilterTreeModel.
472      *
473      * @return The model of the view.
474      */

475     public final LogFilterTreeModel getModel()
476     {
477         return model;
478     }
479
480     // }}}
481
// {{{ getTree
482

483     /**
484      * Get the JTree component of the view.
485      *
486      * @return The tree.
487      */

488     public final JTree JavaDoc getTree()
489     {
490         return tree;
491     }
492
493     // }}}
494
// {{{ fillMenu
495

496     /**
497      * Fill a JMenu with menu items for the LogFilterView.
498      *
499      * @param menu The JMenu to fill.
500      */

501     public void fillMenu(JMenu JavaDoc menu)
502     {
503         JMenuItem JavaDoc mi = menu.add(removeAction);
504         mi = menu.add(removeRecursiveAction);
505
506         menu.addSeparator();
507
508         mi = menu.add(setERRAction);
509         mi = menu.add(setERRDETAILAction);
510         mi = menu.add(setWRNAction);
511         mi = menu.add(setWRNDETAILAction);
512         mi = menu.add(setMSGAction);
513         mi = menu.add(setMSGDETAILAction);
514         mi = menu.add(setMTDAction);
515         mi = menu.add(setMTDDETAILAction);
516         mi = menu.add(setDBGAction);
517         mi = menu.add(setDBGDETAILAction);
518
519         menu.addSeparator();
520
521         mi = new JCheckBoxMenuItem JavaDoc
522             ((String JavaDoc) toggleFilterAction.getValue(Action.NAME),
523              (Icon JavaDoc) toggleFilterAction.getValue(Action.SMALL_ICON));
524         if (toggleButtonModel == null) {
525             toggleButtonModel = mi.getModel();
526             toggleButtonModel.setSelected(model.isPackageFilteringEnabled());
527         mi.addActionListener(toggleFilterAction);
528         } else {
529             mi.setModel(toggleButtonModel);
530         }
531         menu.add(mi);
532         mi = menu.add(addFilterAction);
533         mi = menu.add(removeFilterAction);
534         mi = menu.add(clearFilterAction);
535
536         menu.addSeparator();
537
538         menu.add(showSetLevelsAction);
539     }
540
541     /**
542      * Fill a JPopupMenu with menu items for the LogLevelView.
543      *
544      * @param menu The JPopupMenu to fill.
545      */

546     public void fillMenu(JPopupMenu JavaDoc menu)
547     {
548         menu.add(removeAction);
549         menu.add(removeRecursiveAction);
550
551         menu.addSeparator();
552
553         menu.add(setERRAction);
554         menu.add(setERRDETAILAction);
555         menu.add(setWRNAction);
556         menu.add(setWRNDETAILAction);
557         menu.add(setMSGAction);
558         menu.add(setMSGDETAILAction);
559         menu.add(setMTDAction);
560         menu.add(setMTDDETAILAction);
561         menu.add(setDBGAction);
562         menu.add(setDBGDETAILAction);
563
564         menu.addSeparator();
565
566         JCheckBoxMenuItem JavaDoc mi = new JCheckBoxMenuItem JavaDoc
567             ((String JavaDoc) toggleFilterAction.getValue(Action.NAME),
568              (Icon JavaDoc) toggleFilterAction.getValue(Action.SMALL_ICON));
569         if (toggleButtonModel == null) {
570             toggleButtonModel = mi.getModel();
571             toggleButtonModel.setSelected(model.isPackageFilteringEnabled());
572             mi.addActionListener(toggleFilterAction);
573         } else {
574             mi.setModel(toggleButtonModel);
575         }
576         menu.add(mi);
577         menu.add(addFilterAction);
578         menu.add(removeFilterAction);
579         menu.add(clearFilterAction);
580
581         menu.addSeparator();
582
583         menu.add(showSetLevelsAction);
584     }
585
586     // }}}
587

588     //----------------------------------------------------------------------
589
// Configuration
590
//----------------------------------------------------------------------
591
// {{{ setResources
592

593     /**
594      * Override the default resources used by the LogLevelView. If this method
595      * is not called, the LogLevelView will use its default resource settings.
596      *
597      * @param rb ResourceBundle containing the resources to use.
598      */

599     public void setResources(ResourceBundle JavaDoc rb)
600     {
601         resources.addResources(rb);
602         model.setRootName(resources.getString("logFilterView.root.name",
603                                               "default"));
604     }
605
606
607     // }}}
608
// {{{ showSetLevels
609

610     /**
611      * Expand or collapse tree nodes so that all nodes with a non-null level
612      * are displayed.
613      */

614     public void showSetLevels()
615     {
616         SwingUtilities.invokeLater(new Runnable JavaDoc () {
617             public void run() {
618                 showSetLevelsAction.actionPerformed(null);
619             }
620         });
621     }
622
623     // }}}
624

625     //----------------------------------------------------------------------
626
// Helper methods
627
//----------------------------------------------------------------------
628
// {{{ setupActions
629

630     /**
631      * Set up the actions for the LogLevelView.
632      */

633     private void setupActions()
634     {
635         // do this only once
636
if (removeAction == null) {
637             removeAction = new RemoveLevelAction (false);
638             setActionProperties(removeAction, "removeLevel");
639             removeRecursiveAction = new RemoveLevelAction (true);
640             setActionProperties(removeRecursiveAction, "removeLevelRecursive");
641
642             setERRAction = new ChangeLevelAction (Log.ERR);
643             setActionProperties(setERRAction, "setLevelERR");
644             setERRDETAILAction = new ChangeLevelAction (Log.ERRDETAIL);
645             setActionProperties(setERRDETAILAction, "setLevelERRDETAIL");
646             setWRNAction = new ChangeLevelAction (Log.WRN);
647             setActionProperties(setWRNAction, "setLevelWRN");
648             setWRNDETAILAction = new ChangeLevelAction (Log.WRNDETAIL);
649             setActionProperties(setWRNDETAILAction, "setLevelWRNDETAIL");
650             setMSGAction = new ChangeLevelAction (Log.MSG);
651             setActionProperties(setMSGAction, "setLevelMSG");
652             setMSGDETAILAction = new ChangeLevelAction (Log.MSGDETAIL);
653             setActionProperties(setMSGDETAILAction, "setLevelMSGDETAIL");
654             setMTDAction = new ChangeLevelAction (Log.MTD);
655             setActionProperties(setMTDAction, "setLevelMTD");
656             setMTDDETAILAction = new ChangeLevelAction (Log.MTDDETAIL);
657             setActionProperties(setMTDDETAILAction, "setLevelMTDDETAIL");
658             setDBGAction = new ChangeLevelAction (Log.DBG);
659             setActionProperties(setDBGAction, "setLevelDBG");
660             setDBGDETAILAction = new ChangeLevelAction (Log.DBGDETAIL);
661             setActionProperties(setDBGDETAILAction, "setLevelDBGDETAIL");
662
663             toggleFilterAction = new AbstractAction JavaDoc () {
664                 public void actionPerformed(ActionEvent JavaDoc e) {
665                     model.togglePackageFiltering();
666                     if (toggleButtonModel != null) {
667                         toggleButtonModel.setSelected
668                         (model.isPackageFilteringEnabled());
669                     }
670                 }
671             };
672             setActionProperties(toggleFilterAction, "toggleFilter");
673
674             addFilterAction = new AbstractAction JavaDoc () {
675                 public void actionPerformed(ActionEvent JavaDoc e) {
676                     TreePath JavaDoc[] paths = tree.getSelectionPaths();
677
678                     if (paths != null) {
679                         for (int i = 0; i < paths.length; i++) {
680                             FilterNode node = (FilterNode)
681                                 paths[i].getLastPathComponent();
682                             model.addFilterPackage(node);
683                         }
684                     }
685                 }
686             };
687             setActionProperties(addFilterAction, "addFilter");
688
689             removeFilterAction = new AbstractAction JavaDoc () {
690                 public void actionPerformed(ActionEvent JavaDoc e) {
691                     TreePath JavaDoc[] paths = tree.getSelectionPaths();
692
693                     if (paths != null) {
694                         for (int i = 0; i < paths.length; i++) {
695                             FilterNode node = (FilterNode)
696                                 paths[i].getLastPathComponent();
697                             model.removeFilterPackage(node);
698                         }
699                     }
700                 }
701             };
702             setActionProperties(removeFilterAction, "removeFilter");
703
704             clearFilterAction = new AbstractAction JavaDoc () {
705                 public void actionPerformed(ActionEvent JavaDoc e) {
706                     model.clearFilterPackages();
707                 }
708             };
709             setActionProperties(clearFilterAction, "clearFilter");
710
711             expandAllAction = new AbstractAction JavaDoc () {
712                 public void actionPerformed(ActionEvent JavaDoc e) {
713                     TreePath JavaDoc path = tree.getSelectionPath();
714                     if (path != null) {
715                         boolean excluded = ! logging;
716                         if (excluded) {
717                             Log.excludeThread();
718                         }
719                         try {
720                             SwingUtil.expandAll(tree, path);
721                         } finally {
722                             if (excluded) {
723                                 Log.includeThread();
724                             }
725                         }
726                     }
727                 }
728             };
729
730             collapseAllAction = new AbstractAction JavaDoc () {
731                 public void actionPerformed(ActionEvent JavaDoc e) {
732                     TreePath JavaDoc path = tree.getSelectionPath();
733                     if (path != null) {
734                         boolean excluded = ! logging;
735                         if (excluded) {
736                             Log.excludeThread();
737                         }
738                         try {
739                             SwingUtil.collapseAll(tree, path);
740                         } finally {
741                             if (excluded) {
742                                 Log.includeThread();
743                             }
744                         }
745                     }
746                 }
747             };
748
749             showSetLevelsAction = new ShowSetLevelsAction ();
750             setActionProperties(showSetLevelsAction, "showSetLevels");
751         }
752     }
753
754     // }}}
755
// {{{ setActionProperties
756

757     /**
758      * Set name and icon for an action from the LogLevelView's resources.
759      *
760      * @param action The action to prepare.
761      * @param resource Identifier for the action's resources.
762      */

763     private void setActionProperties(Action JavaDoc action, String JavaDoc resource)
764     {
765         String JavaDoc name = resources.getString
766             ("logFilterView.action." + resource + ".name", null);
767         if (name != null) {
768             action.putValue(Action.NAME, name);
769         }
770
771         String JavaDoc iconName = resources.getString
772             ("logFilterView.action." + resource + ".icon", null);
773         if (iconName != null) {
774             Icon JavaDoc icon = resources.getIcon (iconName, null);
775             if (icon != null) {
776                 action.putValue(Action.SMALL_ICON, icon);
777             }
778         }
779     }
780
781     // }}}
782
// {{{ setupResources
783

784     /**
785      * Initialize the resources from the default resources, fetching them if
786      * necessary.
787      */

788     private void setupResources()
789     {
790         if (defaultResources == null) {
791             defaultResources = new MapResourceBundle ();
792             defaultResources.fetchProperties
793                 ("/de/qfs/apps/qflog/logview/resources/properties/logfilterview",
794                  LogFilterView.class);
795         }
796         resources = defaultResources;
797     }
798
799     // }}}
800

801     //----------------------------------------------------------------------
802
// Action classes
803
//----------------------------------------------------------------------
804
// {{{ class ChangeLevelAction
805

806     // {{{ static ChangeLevelAction variables
807

808     /**
809      * The Logger used for logging ChangeLevelAction methods.
810      */

811     private final static Logger claLogger =
812         new Logger (ChangeLevelAction.class);
813
814     // }}}
815

816     /**
817      * Change the level of selected nodes in the filter tree.
818      */

819     private class ChangeLevelAction
820         extends AbstractAction JavaDoc
821     {
822         // {{{ variables
823

824         /**
825          * The level to set.
826          */

827         private int level;
828
829         // }}}
830

831         // {{{ constructor
832

833         /**
834          * Create a new ChangeLevelAction.
835          *
836          * @param level The level to set when the action is invoked.
837          */

838         public ChangeLevelAction(int level)
839         {
840             this.level = level;
841         }
842
843         // }}}
844

845         // {{{ actionPerformed
846

847         /**
848          * Set the level on the selected nodes.
849          *
850          * @param e Ignored.
851          */

852         public void actionPerformed (ActionEvent JavaDoc e)
853         {
854             if (logging && claLogger.level >= Log.MTD) {
855                 claLogger.log(Log.MTD, "actionPerformed(ActionEvent)",
856                            claLogger.level < Log.MTDDETAIL ? "" :
857                            "level: " + level);
858             }
859             TreePath JavaDoc[] paths = tree.getSelectionPaths();
860
861             if (paths != null) {
862                 for (int i = 0; i < paths.length; i++) {
863                     model.setLevel(paths[i], level);
864                 }
865             }
866         }
867
868         // }}}
869
}
870
871     // }}}
872
// {{{ class RemoveLevelAction
873

874     // {{{ static RemoveLevelAction variables
875

876     /**
877      * The Logger used for logging RemoveLevelAction methods.
878      */

879     private final static Logger rlaLogger =
880         new Logger (RemoveLevelAction.class);
881
882     // }}}
883

884     /**
885      * Remove the levels from the selected filter tree nodes.
886      */

887     private class RemoveLevelAction
888         extends AbstractAction JavaDoc
889     {
890         // {{{ variables
891

892         /**
893          * Whether to recursively remove levels.
894          */

895         private boolean recurse;
896
897         // }}}
898

899         // {{{ constructor
900

901         /**
902          * Create a new RemoveLevelAction.
903          *
904          * @param recurse Whether to recursively remove levels.
905          */

906         public RemoveLevelAction(boolean recurse)
907         {
908             this.recurse = recurse;
909         }
910
911         // }}}
912

913         // {{{ actionPerformed
914

915         /**
916          * Remove the levels from the selected filter tree nodes.
917          *
918          * @param e Ignored.
919          */

920         public void actionPerformed (ActionEvent JavaDoc e)
921         {
922             if (logging && rlaLogger.level >= Log.MTD) {
923                 rlaLogger.log(Log.MTD, "actionPerformed(ActionEvent)",
924                            rlaLogger.level < Log.MTDDETAIL ? "" :
925                            "recurse: " + recurse);
926             }
927             TreePath JavaDoc[] paths = tree.getSelectionPaths();
928
929             if (paths != null) {
930                 for (int i = 0; i < paths.length; i++) {
931                     model.removeLevel(paths[i], recurse);
932                 }
933             }
934         }
935
936         // }}}
937
}
938
939     // }}}
940
// {{{ class ShowSetLevelsAction
941

942     // {{{ static ShowSetLevelsAction variables
943

944     /**
945      * The Logger used for logging ShowSetLevelsAction methods.
946      */

947     private final static Logger sslaLogger =
948         new Logger (ShowSetLevelsAction.class);
949
950     // }}}
951
/**
952      * Expand or collapse tree nodes so that all nodes with a non-null level
953      * are displayed.
954      */

955     private class ShowSetLevelsAction
956         extends AbstractAction JavaDoc
957     {
958         // {{{ constructor
959

960         /**
961          * Create a new ShowSetLevelsAction.
962          */

963         public ShowSetLevelsAction()
964         {
965         }
966
967         // }}}
968

969         // {{{ actionPerformed
970

971         /**
972          * Expand/collapse tree nodes according to the levels.
973          *
974          * @param e Ignored.
975          */

976         public void actionPerformed (ActionEvent JavaDoc e)
977         {
978             boolean excluded = !logging;
979             if (excluded) {
980                 Log.excludeThread();
981             }
982             try {
983                 maybeExpandPath(new TreePath JavaDoc (new Object JavaDoc[] {model.getRoot()}));
984             } finally {
985                 if (excluded) {
986                     Log.includeThread();
987                 }
988             }
989         }
990
991         // }}}
992
// {{{ maybeExpandPath
993

994         /**
995          * Recursively expand/collapse the child nodes or a node while
996          * checking whether the node has any direct or indirect children with
997          * a non-null level.
998          *
999          * @param path Path to the start node.
1000         *
1001         * @return True if the node has children wit a non-null level.
1002         */

1003        private boolean maybeExpandPath(TreePath JavaDoc path)
1004        {
1005            if (logging && sslaLogger.level >= Log.MTD) {
1006                sslaLogger.log(Log.MTD, "maybeExpandPath(TreePath)",
1007                           sslaLogger.level < Log.MTDDETAIL ? "" :
1008                           "path: " + path);
1009            }
1010            Object JavaDoc node = path.getLastPathComponent();
1011            boolean isLevel = model.getLevel(node) != null;
1012            boolean expand = false;
1013            if (model.isLeaf(node)) {
1014                return isLevel;
1015            }
1016
1017            int num = model.getChildCount(node);
1018            for (int i = 0; i < num; i++) {
1019                Object JavaDoc child = model.getChild(node, i);
1020                if (maybeExpandPath(path.pathByAddingChild(child))) {
1021                    expand = true;
1022                }
1023            }
1024            if (sslaLogger.level >= Log.DBG) {
1025                sslaLogger.log(Log.DBG, "maybeExpandPath(TreePath)",
1026                           "expand: " + expand);
1027            }
1028
1029            if (expand) {
1030                tree.expandPath(path);
1031            } else {
1032                tree.collapsePath(path);
1033            }
1034            return expand || isLevel;
1035        }
1036
1037        // }}}
1038
}
1039
1040    // }}}
1041

1042    //----------------------------------------------------------------------
1043
// Popup menu listener
1044
//----------------------------------------------------------------------
1045
// {{{ class PopupListener
1046

1047    /**
1048     * Listener for mouseclicks that brings up a popup menu.
1049     */

1050    class PopupListener
1051        extends MouseAdapter JavaDoc
1052    {
1053        /**
1054         * Notify the listener that a mouse button has been pressed.
1055         *
1056         * @param event Details aobut the event.
1057         */

1058        public void mousePressed(MouseEvent JavaDoc event)
1059        {
1060            maybePopup(event);
1061        }
1062
1063        /**
1064         * Notify the listener that a mouse button has been released.
1065         *
1066         * @param event Details aobut the event.
1067         */

1068        public void mouseReleased(MouseEvent JavaDoc event)
1069        {
1070            maybePopup(event);
1071        }
1072
1073        /**
1074         * Check if the event is a popup trigger and bring up a popup menu if
1075         * required. If the click happens on a tree node that is selected, the
1076         * selection doesn't change. If the node is not selected, it will be
1077         * made the only selected node.
1078         *
1079         * @param event The MouseEvent containing the details.
1080         */

1081        private void maybePopup(MouseEvent JavaDoc event)
1082        {
1083            boolean excluded = !logging;
1084            if (excluded) {
1085                Log.excludeThread();
1086            }
1087            try {
1088                if (event.isPopupTrigger()) {
1089                    int row =
1090                        tree.getRowForLocation(event.getX(), event.getY());
1091                    if (row >= 0) {
1092                        if (! tree.isRowSelected(row)) {
1093                            tree.setSelectionRow(row);
1094                        }
1095                    }
1096                    SwingUtil.showPopup(popup, tree,
1097                                        event.getX(), event.getY(),
1098                                        false);
1099                    popup.requestFocus();
1100                }
1101            } finally {
1102                if (excluded) {
1103                    Log.includeThread();
1104                }
1105            }
1106        }
1107    }
1108
1109    // }}}
1110

1111    //----------------------------------------------------------------------
1112
// Renderer for the tree
1113
//----------------------------------------------------------------------
1114
// {{{ class Renderer
1115

1116    // {{{ static Renderer variables
1117

1118    /**
1119     * Index of the method icon.
1120     */

1121    private final static int METHOD = 10;
1122
1123    /**
1124     * Index of the class icon.
1125     */

1126    private final static int CLASS = 11;
1127
1128    /**
1129     * Index of the open class icon.
1130     */

1131    private final static int CLASS_OPEN = 12;
1132
1133    /**
1134     * Index of the package icon.
1135     */

1136    private final static int PACKAGE = 13;
1137
1138    /**
1139     * Index of the open package icon.
1140     */

1141    private final static int PACKAGE_OPEN = 14;
1142
1143    /**
1144     * The names of the icons resources.
1145     */

1146    private final static String JavaDoc iconNames[] = {
1147        "logFilterView.icon.err", "logFilterView.icon.errDetail",
1148        "logFilterView.icon.wrn", "logFilterView.icon.wrnDetail",
1149        "logFilterView.icon.msg", "logFilterView.icon.msgDetail",
1150        "logFilterView.icon.mtd", "logFilterView.icon.mtdDetail",
1151        "logFilterView.icon.dbg", "logFilterView.icon.dbgDetail",
1152        "logFilterView.icon.method",
1153        "logFilterView.icon.class", "logFilterView.icon.classOpen",
1154        "logFilterView.icon.package", "logFilterView.icon.packageOpen"
1155    };
1156
1157    /**
1158     * The icons to render.
1159     */

1160    private final static Icon JavaDoc[] icons = new Icon JavaDoc[iconNames.length];
1161
1162    // }}}
1163

1164    /**
1165     * Renderer for the tree nodes. Sets package, class or method icons if no
1166     * level is set, or the level icon for the node's level. <p>
1167     *
1168     * If the node is used as an extra filter, it is displayed in red.
1169     */

1170    private class Renderer
1171        extends WindowsTreeCellRenderer
1172    {
1173        // {{{ constructor
1174

1175        /**
1176         * Create a new Renderer.
1177         */

1178        public Renderer ()
1179        {
1180            initIcons();
1181        }
1182
1183        // }}}
1184

1185        // {{{ getTreeCellRendererComponent
1186

1187       /**
1188         * Get the renderer component for the tree node.
1189         *
1190         * @param tree The tree being drawn.
1191         * @param obj The tree node.
1192         * @param selected Whether the node is selected.
1193         * @param expanded Whether the node is expanded.
1194         * @param leaf Whether the node is a leaf.
1195         * @param row The node's row index.
1196         * @param hasFocus Whether the node has the focus.
1197         *
1198         * @return A label with the node's name and correct icon.
1199         */

1200         public Component JavaDoc getTreeCellRendererComponent
1201        (JTree JavaDoc tree, Object JavaDoc obj, boolean selected, boolean expanded,
1202         boolean leaf, int row, boolean hasFocus)
1203        {
1204            JLabel JavaDoc com = (JLabel JavaDoc) super.getTreeCellRendererComponent
1205                (tree, obj, selected, expanded, leaf, row, hasFocus);
1206
1207            com.setForeground
1208                (((FilterNode) obj).isExtra()
1209                 ? Color.red :
1210                 (selected ? getTextSelectionColor()
1211                           : getTextNonSelectionColor()));
1212            Integer JavaDoc level = model.getLevel(obj);
1213
1214            Icon JavaDoc outer;
1215            if (leaf) {
1216                outer = icons[METHOD];
1217            } else if ((obj instanceof FilterRootNode)
1218                       || ! ((FilterNode) obj).getData().getClazz()
1219                       .endsWith(".")) {
1220                outer = icons[expanded ? CLASS_OPEN : CLASS];
1221            } else {
1222                outer = icons[expanded ? PACKAGE_OPEN : PACKAGE];
1223            }
1224            if (level == null) {
1225                com.setIcon(outer);
1226                return com;
1227            }
1228            int lvl = level.intValue();
1229            if (lvl < Log.ERR || lvl > Log.DBGDETAIL) {
1230                com.setIcon(outer);
1231            } else {
1232                com.setIcon(icons[level.intValue() - 1]);
1233            }
1234            return com;
1235        }
1236
1237        // }}}
1238
// {{{ initIcons
1239

1240        /**
1241         * Fetch the icons.
1242         */

1243        private void initIcons()
1244        {
1245            if (icons[0] == null) {
1246                for (int i = 0; i < icons.length; i++) {
1247                    icons[i] = resources.getIcon(iconNames[i], null);
1248                }
1249            }
1250        }
1251
1252        // }}}
1253
}
1254
1255    // }}}
1256
}
1257
Popular Tags