Project: des
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more 
 * contributor license agreements.  See the NOTICE file distributed with 
 * this work for additional information regarding copyright ownership. 
 * The ASF licenses this file to You under the Apache License, Version 2.0 
 * (the "License"); you may not use this file except in compliance with 
 * the License.  You may obtain a copy of the License at 
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0 
 *  
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 */
package org.apache.log4j.lf5.viewer.categoryexplorer; 
 
import java.awt.Component; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.util.ArrayList; 
import java.util.Enumeration; 
 
import javax.swing.JCheckBox; 
import javax.swing.JMenuItem; 
import javax.swing.JOptionPane; 
import javax.swing.JPopupMenu; 
import javax.swing.JTree; 
import javax.swing.tree.TreePath; 
 
/**
 * CategoryNodeEditor 
 * 
 * @author Michael J. Sikorsky 
 * @author Robert Shaw 
 */
 
 
// Contributed by ThoughtWorks Inc. 
 
public class CategoryNodeEditor extends CategoryAbstractCellEditor { 
  //-------------------------------------------------------------------------- 
  //   Constants: 
  //-------------------------------------------------------------------------- 
 
  //-------------------------------------------------------------------------- 
  //   Protected Variables: 
  //-------------------------------------------------------------------------- 
  protected CategoryNodeEditorRenderer _renderer; 
  protected CategoryNode _lastEditedNode; 
  protected JCheckBox _checkBox; 
  protected CategoryExplorerModel _categoryModel; 
  protected JTree _tree; 
 
  //-------------------------------------------------------------------------- 
  //   Private Variables: 
  //-------------------------------------------------------------------------- 
 
  //-------------------------------------------------------------------------- 
  //   Constructors: 
  //-------------------------------------------------------------------------- 
 
  public CategoryNodeEditor(CategoryExplorerModel model) { 
    _renderer = new CategoryNodeEditorRenderer(); 
    _checkBox = _renderer.getCheckBox(); 
    _categoryModel = model; 
 
    _checkBox.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        _categoryModel.update(_lastEditedNode, _checkBox.isSelected()); 
        stopCellEditing(); 
      } 
    }); 
 
    _renderer.addMouseListener(new MouseAdapter() { 
      public void mousePressed(MouseEvent e) { 
        if ((e.getModifiers() & MouseEvent.BUTTON3_MASK) != 0) { 
          showPopup(_lastEditedNode, e.getX(), e.getY()); 
        } 
        stopCellEditing(); 
      } 
    }); 
  } 
 
  //-------------------------------------------------------------------------- 
  //   Public Methods: 
  //-------------------------------------------------------------------------- 
 
  public Component getTreeCellEditorComponent(JTree tree, Object value, 
      boolean selected, boolean expanded, 
      boolean leaf, int row) { 
    _lastEditedNode = (CategoryNode) value; 
    _tree = tree; 
 
    return _renderer.getTreeCellRendererComponent(tree, 
        value, selected, expanded, 
        leaf, row, true); 
    // hasFocus ignored 
  } 
 
  public Object getCellEditorValue() { 
    return _lastEditedNode.getUserObject(); 
  } 
  //-------------------------------------------------------------------------- 
  //   Protected Methods: 
  //-------------------------------------------------------------------------- 
 
  protected JMenuItem createPropertiesMenuItem(final CategoryNode node) { 
    JMenuItem result = new JMenuItem("Properties"); 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        showPropertiesDialog(node); 
      } 
    }); 
    return result; 
  } 
 
  protected void showPropertiesDialog(CategoryNode node) { 
    JOptionPane.showMessageDialog( 
        _tree, 
        getDisplayedProperties(node), 
        "Category Properties: " + node.getTitle(), 
        JOptionPane.PLAIN_MESSAGE 
    ); 
  } 
 
  protected Object getDisplayedProperties(CategoryNode node) { 
    ArrayList result = new ArrayList(); 
    result.add("Category: " + node.getTitle()); 
    if (node.hasFatalRecords()) { 
      result.add("Contains at least one fatal LogRecord."); 
    } 
    if (node.hasFatalChildren()) { 
      result.add("Contains descendants with a fatal LogRecord."); 
    } 
    result.add("LogRecords in this category alone: " + 
        node.getNumberOfContainedRecords()); 
    result.add("LogRecords in descendant categories: " + 
        node.getNumberOfRecordsFromChildren()); 
    result.add("LogRecords in this category including descendants: " + 
        node.getTotalNumberOfRecords()); 
    return result.toArray(); 
  } 
 
  protected void showPopup(CategoryNode node, int x, int y) { 
    JPopupMenu popup = new JPopupMenu(); 
    popup.setSize(150400); 
    // 
    // Configure the Popup 
    // 
    if (node.getParent() == null) { 
      popup.add(createRemoveMenuItem()); 
      popup.addSeparator(); 
    } 
    popup.add(createSelectDescendantsMenuItem(node)); 
    popup.add(createUnselectDescendantsMenuItem(node)); 
    popup.addSeparator(); 
    popup.add(createExpandMenuItem(node)); 
    popup.add(createCollapseMenuItem(node)); 
    popup.addSeparator(); 
    popup.add(createPropertiesMenuItem(node)); 
    popup.show(_renderer, x, y); 
  } 
 
  protected JMenuItem createSelectDescendantsMenuItem(final CategoryNode node) { 
    JMenuItem selectDescendants = 
        new JMenuItem("Select All Descendant Categories"); 
    selectDescendants.addActionListener( 
        new ActionListener() { 
          public void actionPerformed(ActionEvent e) { 
            _categoryModel.setDescendantSelection(node, true); 
          } 
        } 
    ); 
    return selectDescendants; 
  } 
 
  protected JMenuItem createUnselectDescendantsMenuItem(final CategoryNode node) { 
    JMenuItem unselectDescendants = 
        new JMenuItem("Deselect All Descendant Categories"); 
    unselectDescendants.addActionListener( 
 
        new ActionListener() { 
          public void actionPerformed(ActionEvent e) { 
            _categoryModel.setDescendantSelection(node, false); 
          } 
        } 
 
    ); 
    return unselectDescendants; 
  } 
 
  protected JMenuItem createExpandMenuItem(final CategoryNode node) { 
    JMenuItem result = new JMenuItem("Expand All Descendant Categories"); 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        expandDescendants(node); 
      } 
    }); 
    return result; 
  } 
 
  protected JMenuItem createCollapseMenuItem(final CategoryNode node) { 
    JMenuItem result = new JMenuItem("Collapse All Descendant Categories"); 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        collapseDescendants(node); 
      } 
    }); 
    return result; 
  } 
 
  /**
   * This featured was moved from the LogBrokerMonitor class 
   * to the CategoryNodeExplorer so that the Category tree 
   * could be pruned from the Category Explorer popup menu. 
   * This menu option only appears when a user right clicks on 
   * the Category parent node. 
   * 
   * See removeUnusedNodes() 
   */
 
  protected JMenuItem createRemoveMenuItem() { 
    JMenuItem result = new JMenuItem("Remove All Empty Categories"); 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        while (removeUnusedNodes() > 0) ; 
      } 
    }); 
    return result; 
  } 
 
  protected void expandDescendants(CategoryNode node) { 
    Enumeration descendants = node.depthFirstEnumeration(); 
    CategoryNode current; 
    while (descendants.hasMoreElements()) { 
      current = (CategoryNode) descendants.nextElement(); 
      expand(current); 
    } 
  } 
 
  protected void collapseDescendants(CategoryNode node) { 
    Enumeration descendants = node.depthFirstEnumeration(); 
    CategoryNode current; 
    while (descendants.hasMoreElements()) { 
      current = (CategoryNode) descendants.nextElement(); 
      collapse(current); 
    } 
  } 
 
  /**
   * Removes any inactive nodes from the Category tree. 
   */
 
  protected int removeUnusedNodes() { 
    int count = 0
    CategoryNode root = _categoryModel.getRootCategoryNode(); 
    Enumeration enumeration = root.depthFirstEnumeration(); 
    while (enumeration.hasMoreElements()) { 
      CategoryNode node = (CategoryNode) enumeration.nextElement(); 
      if (node.isLeaf() && node.getNumberOfContainedRecords() == 0 
          && node.getParent() != null) { 
        _categoryModel.removeNodeFromParent(node); 
        count++; 
      } 
    } 
 
    return count; 
  } 
 
  protected void expand(CategoryNode node) { 
    _tree.expandPath(getTreePath(node)); 
  } 
 
  protected TreePath getTreePath(CategoryNode node) { 
    return new TreePath(node.getPath()); 
  } 
 
  protected void collapse(CategoryNode node) { 
    _tree.collapsePath(getTreePath(node)); 
  } 
 
  //----------------------------------------------------------------------- 
  //   Private Methods: 
  //-------------------------------------------------------------------------- 
 
  //-------------------------------------------------------------------------- 
  //   Nested Top-Level Classes or Interfaces: 
  //-------------------------------------------------------------------------- 
 
}