View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  package org.apache.log4j.lf5.viewer.categoryexplorer;
    18
    19  import javax.swing.*;
    20  import javax.swing.tree.TreePath;
    21  import java.awt.*;
    22  import java.awt.event.ActionEvent;
    23  import java.awt.event.ActionListener;
    24  import java.awt.event.MouseAdapter;
    25  import java.awt.event.MouseEvent;
    26  import java.util.ArrayList;
    27  import java.util.Enumeration;
    28
    29  /***
    30   * CategoryNodeEditor
    31   *
    32   * @author Michael J. Sikorsky
    33   * @author Robert Shaw
    34   */
    35
    36  // Contributed by ThoughtWorks Inc.
    37
    38  public class CategoryNodeEditor extends CategoryAbstractCellEditor {
    39    //--------------------------------------------------------------------------
    40    //   Constants:
    41    //--------------------------------------------------------------------------
    42
    43    //--------------------------------------------------------------------------
    44    //   Protected Variables:
    45    //--------------------------------------------------------------------------
    46    protected CategoryNodeEditorRenderer _renderer;
    47    protected CategoryNode _lastEditedNode;
    48    protected JCheckBox _checkBox;
    49    protected CategoryExplorerModel _categoryModel;
    50    protected JTree _tree;
    51
    52    //--------------------------------------------------------------------------
    53    //   Private Variables:
    54    //--------------------------------------------------------------------------
    55
    56    //--------------------------------------------------------------------------
    57    //   Constructors:
    58    //--------------------------------------------------------------------------
    59
    60    public CategoryNodeEditor(CategoryExplorerModel model) {
    61      _renderer = new CategoryNodeEditorRenderer();
    62      _checkBox = _renderer.getCheckBox();
    63      _categoryModel = model;
    64
    65      _checkBox.addActionListener(new ActionListener() {
    66        public void actionPerformed(ActionEvent e) {
    67          _categoryModel.update(_lastEditedNode, _checkBox.isSelected());
    68          stopCellEditing();
    69        }
    70      });
    71
    72      _renderer.addMouseListener(new MouseAdapter() {
    73        public void mousePressed(MouseEvent e) {
    74          if ((e.getModifiers() & MouseEvent.BUTTON3_MASK) != 0) {
    75            showPopup(_lastEditedNode, e.getX(), e.getY());
    76          }
    77          stopCellEditing();
    78        }
    79      });
    80    }
    81
    82    //--------------------------------------------------------------------------
    83    //   Public Methods:
    84    //--------------------------------------------------------------------------
    85
    86    public Component getTreeCellEditorComponent(JTree tree, Object value,
    87        boolean selected, boolean expanded,
    88        boolean leaf, int row) {
    89      _lastEditedNode = (CategoryNode) value;
    90      _tree = tree;
    91
    92      return _renderer.getTreeCellRendererComponent(tree,
    93          value, selected, expanded,
    94          leaf, row, true);
    95      // hasFocus ignored
    96    }
    97
    98    public Object getCellEditorValue() {
    99      return _lastEditedNode.getUserObject();
    100   }
    101   //--------------------------------------------------------------------------
    102   //   Protected Methods:
    103   //--------------------------------------------------------------------------
    104
    105   protected JMenuItem createPropertiesMenuItem(final CategoryNode node) {
    106     JMenuItem result = new JMenuItem("Properties");
    107     result.addActionListener(new ActionListener() {
    108       public void actionPerformed(ActionEvent e) {
    109         showPropertiesDialog(node);
    110       }
    111     });
    112     return result;
    113   }
    114
    115   protected void showPropertiesDialog(CategoryNode node) {
    116     JOptionPane.showMessageDialog(
    117         _tree,
    118         getDisplayedProperties(node),
    119         "Category Properties: " + node.getTitle(),
    120         JOptionPane.PLAIN_MESSAGE
    121     );
    122   }
    123
    124   protected Object getDisplayedProperties(CategoryNode node) {
    125     ArrayList result = new ArrayList();
    126     result.add("Category: " + node.getTitle());
    127     if (node.hasFatalRecords()) {
    128       result.add("Contains at least one fatal LogRecord.");
    129     }
    130     if (node.hasFatalChildren()) {
    131       result.add("Contains descendants with a fatal LogRecord.");
    132     }
    133     result.add("LogRecords in this category alone: " +
    134         node.getNumberOfContainedRecords());
    135     result.add("LogRecords in descendant categories: " +
    136         node.getNumberOfRecordsFromChildren());
    137     result.add("LogRecords in this category including descendants: " +
    138         node.getTotalNumberOfRecords());
    139     return result.toArray();
    140   }
    141
    142   protected void showPopup(CategoryNode node, int x, int y) {
    143     JPopupMenu popup = new JPopupMenu();
    144     popup.setSize(150, 400);
    145     //
    146     // Configure the Popup
    147     //
    148     if (node.getParent() == null) {
    149       popup.add(createRemoveMenuItem());
    150       popup.addSeparator();
    151     }
    152     popup.add(createSelectDescendantsMenuItem(node));
    153     popup.add(createUnselectDescendantsMenuItem(node));
    154     popup.addSeparator();
    155     popup.add(createExpandMenuItem(node));
    156     popup.add(createCollapseMenuItem(node));
    157     popup.addSeparator();
    158     popup.add(createPropertiesMenuItem(node));
    159     popup.show(_renderer, x, y);
    160   }
    161
    162   protected JMenuItem createSelectDescendantsMenuItem(final CategoryNode node) {
    163     JMenuItem selectDescendants =
    164         new JMenuItem("Select All Descendant Categories");
    165     selectDescendants.addActionListener(
    166         new ActionListener() {
    167           public void actionPerformed(ActionEvent e) {
    168             _categoryModel.setDescendantSelection(node, true);
    169           }
    170         }
    171     );
    172     return selectDescendants;
    173   }
    174
    175   protected JMenuItem createUnselectDescendantsMenuItem(final CategoryNode node) {
    176     JMenuItem unselectDescendants =
    177         new JMenuItem("Deselect All Descendant Categories");
    178     unselectDescendants.addActionListener(
    179
    180         new ActionListener() {
    181           public void actionPerformed(ActionEvent e) {
    182             _categoryModel.setDescendantSelection(node, false);
    183           }
    184         }
    185
    186     );
    187     return unselectDescendants;
    188   }
    189
    190   protected JMenuItem createExpandMenuItem(final CategoryNode node) {
    191     JMenuItem result = new JMenuItem("Expand All Descendant Categories");
    192     result.addActionListener(new ActionListener() {
    193       public void actionPerformed(ActionEvent e) {
    194         expandDescendants(node);
    195       }
    196     });
    197     return result;
    198   }
    199
    200   protected JMenuItem createCollapseMenuItem(final CategoryNode node) {
    201     JMenuItem result = new JMenuItem("Collapse All Descendant Categories");
    202     result.addActionListener(new ActionListener() {
    203       public void actionPerformed(ActionEvent e) {
    204         collapseDescendants(node);
    205       }
    206     });
    207     return result;
    208   }
    209
    210   /***
    211    * This featured was moved from the LogBrokerMonitor class
    212    * to the CategoryNodeExplorer so that the Category tree
    213    * could be pruned from the Category Explorer popup menu.
    214    * This menu option only appears when a user right clicks on
    215    * the Category parent node.
    216    *
    217    * See removeUnusedNodes()
    218    */
    219   protected JMenuItem createRemoveMenuItem() {
    220     JMenuItem result = new JMenuItem("Remove All Empty Categories");
    221     result.addActionListener(new ActionListener() {
    222       public void actionPerformed(ActionEvent e) {
    223         while (removeUnusedNodes() > 0) ;
    224       }
    225     });
    226     return result;
    227   }
    228
    229   protected void expandDescendants(CategoryNode node) {
    230     Enumeration descendants = node.depthFirstEnumeration();
    231     CategoryNode current;
    232     while (descendants.hasMoreElements()) {
    233       current = (CategoryNode) descendants.nextElement();
    234       expand(current);
    235     }
    236   }
    237
    238   protected void collapseDescendants(CategoryNode node) {
    239     Enumeration descendants = node.depthFirstEnumeration();
    240     CategoryNode current;
    241     while (descendants.hasMoreElements()) {
    242       current = (CategoryNode) descendants.nextElement();
    243       collapse(current);
    244     }
    245   }
    246
    247   /***
    248    * Removes any inactive nodes from the Category tree.
    249    */
    250   protected int removeUnusedNodes() {
    251     int count = 0;
    252     CategoryNode root = _categoryModel.getRootCategoryNode();
    253     Enumeration enumeration = root.depthFirstEnumeration();
    254     while (enumeration.hasMoreElements()) {
    255       CategoryNode node = (CategoryNode) enumeration.nextElement();
    256       if (node.isLeaf() && node.getNumberOfContainedRecords() == 0
    257           && node.getParent() != null) {
    258         _categoryModel.removeNodeFromParent(node);
    259         count++;
    260       }
    261     }
    262
    263     return count;
    264   }
    265
    266   protected void expand(CategoryNode node) {
    267     _tree.expandPath(getTreePath(node));
    268   }
    269
    270   protected TreePath getTreePath(CategoryNode node) {
    271     return new TreePath(node.getPath());
    272   }
    273
    274   protected void collapse(CategoryNode node) {
    275     _tree.collapsePath(getTreePath(node));
    276   }
    277
    278   //-----------------------------------------------------------------------
    279   //   Private Methods:
    280   //--------------------------------------------------------------------------
    281
    282   //--------------------------------------------------------------------------
    283   //   Nested Top-Level Classes or Interfaces:
    284   //--------------------------------------------------------------------------
    285
    286 }