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