/*
 * Copyright 2008 Google Inc.
 *
 * Licensed 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 com.google.gwt.dev.shell.log;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.dev.BootStrapPlatform;
import com.google.gwt.dev.shell.CloseButton;
import com.google.gwt.dev.shell.CloseButton.Callback;
import com.google.gwt.dev.shell.WrapLayout;
import com.google.gwt.dev.shell.log.SwingTreeLogger.LogEvent;
import com.google.gwt.dev.util.BrowserLauncher;
import com.google.gwt.dev.util.log.AbstractTreeLogger;
import com.google.gwt.dev.util.log.CompositeTreeLogger;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.HeadlessException;
import java.awt.Point;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.UIManager;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkEvent.EventType;
import javax.swing.event.HyperlinkListener;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.html.HTMLDocument;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

/**
 * Swing widget containing a tree logger.
 *
 * <p>
 * This class should not be serialized.
 * </p>
 */
public class SwingLoggerPanel extends JPanel implements TreeSelectionListener,
    HyperlinkListener {

  /**
   * Callback interface for optional close button behavior.
   */
  public interface CloseHandler {

    /**
     * Called when the close button has been clicked on the tree logger
     * and any confirmation needed has been handled.
     *
     * @param loggerPanel SwingTreeLogger instance being closed
     */
    void onCloseRequest(SwingLoggerPanel loggerPanel);
  }

  private class FindBox extends JPanel {

    private Popup findPopup;
    private String lastSearch;

    private ArrayList<DefaultMutableTreeNode> matches;

    private int matchNumber;
    private JTextField searchField;
    private JLabel searchStatus;

    public FindBox() {
      super(new BorderLayout());
      JPanel top = new JPanel(new FlowLayout());
      searchField = new JTextField(20);
      top.add(searchField);
      JButton nextButton = new JButton("+");
      top.add(nextButton);
      nextButton.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
          nextMatch();
        }
      });
      JButton prevButton = new JButton("-");
      top.add(prevButton);
      prevButton.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
          prevMatch();
        }
      });
      CloseButton closeButton = new CloseButton("Close this search box");
      closeButton.setCallback(new Callback() {
        @Override
        public void onCloseRequest() {
          hideFindBox();
        }
      });
      top.add(closeButton);
      KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
      getInputMap(WHEN_IN_FOCUSED_WINDOW).put(key, "find-cancel");
      key = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
      getInputMap(WHEN_IN_FOCUSED_WINDOW).put(key, "find-search");
      getActionMap().put("find-search", new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
          lastSearch = searchField.getText();
          matches = doFind(lastSearch);
          matchNumber = 0;
          updateSearchResult();
        }
      });
      AbstractAction closeFindBox = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
          hideFindBox();
        }
      };
      getActionMap().put("find-cancel", closeFindBox);
      add(top, BorderLayout.NORTH);
      searchStatus = new JLabel("Type search text and press Enter");
      searchStatus.setBorder(BorderFactory.createEmptyBorder(0, 2, 2, 0));
      add(searchStatus, BorderLayout.SOUTH);
    }

    public void hideBox() {
      if (findPopup != null) {
        findPopup.hide();
        findPopup = null;
      }
    }

    public void nextMatch() {
      if (matches != null && matches.size() > 0) {
        matchNumber = (matchNumber + 1) % matches.size();
        updateSearchResult();
      }
    }

    public void prevMatch() {
      if (matches != null) {
        int n = matches.size();
        if (n > 0) {
          matchNumber = (matchNumber + n - 1) % n;
          updateSearchResult();
        }
      }
    }

    public void showBox() {
      Point loggerOrigin = details.getLocationOnScreen();
      Dimension dim = details.getSize();
      if (findPopup != null) {
        findPopup.hide();
      }
      // have to display once to get the correct size
      int width = findBox.getWidth();
      boolean needsRelocate = (width <= 0);
      int x = loggerOrigin.x + dim.width - width;
      int y = loggerOrigin.y + dim.height - findBox.getHeight();
      PopupFactory popupFactory = PopupFactory.getSharedInstance();
      // TODO(jat): need to track window resize?
      findPopup = popupFactory.getPopup(SwingLoggerPanel.this, findBox, x, y);
      findPopup.show();
      if (needsRelocate) {
        x = loggerOrigin.x + dim.width - findBox.getWidth();
        y = loggerOrigin.y + dim.height - findBox.getHeight();
        findPopup.hide();
        findPopup = popupFactory.getPopup(SwingLoggerPanel.this, findBox, x, y);
        findPopup.show();
      }
      searchField.requestFocusInWindow();
    }

    private void updateSearchResult() {
      int n = matches.size();
      if (n == 0) {
        searchStatus.setText("No matches");
      } else {
        searchStatus.setText(String.valueOf(matchNumber + 1) + " of "
            + n + " matches");
        showFindResult(matches.get(matchNumber), lastSearch);
      }
    }
  }

  private static class TreeRenderer extends DefaultTreeCellRenderer {
    @Override
    public Component getTreeCellRendererComponent(JTree tree, Object value,
        boolean sel, boolean expanded, boolean leaf, int row,
        boolean componentHasFocus) {
      super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row,
          componentHasFocus);
      DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
      Object userObject = node.getUserObject();
      if (userObject instanceof LogEvent) {
        LogEvent event = (LogEvent) userObject;
        event.setDisplayProperties(this);
      }
      return this;
    }
  }

  /**
   * The mask to use for Ctrl -- mapped to Command on Mac.
   */
  private static int ctrlKeyDown;

  private static final Color DISCONNECTED_COLOR = Color.decode("0xFFDDDD");

  static {
    ctrlKeyDown = BootStrapPlatform.isMac() ?  InputEvent.ALT_DOWN_MASK
        : InputEvent.CTRL_DOWN_MASK;
  }

  // package protected for SwingTreeLogger to access
  Type levelFilter;

  String regexFilter;

  private final JTree tree;

  DefaultTreeModel treeModel;

  private CloseHandler closeHandler;

  private CloseButton closeLogger;

  private final JEditorPane details;

  private boolean disconnected = false;

  private FindBox findBox;

  private JComboBox levelComboBox;

  private final TreeLogger logger;

  private JTextField regexField;

  private DefaultMutableTreeNode root;

  private JPanel topPanel;

  private JScrollPane treeView;

  private JCheckBox autoScroll;

  /**
   * Create a Swing-based logger panel, with a tree section and a detail
   * section.
   *
   * @param maxLevel
   * @param logFile
   */
  public SwingLoggerPanel(TreeLogger.Type maxLevel, File logFile) {
    super(new BorderLayout());
    regexFilter = "";
    levelFilter = maxLevel;
    // TODO(jat): how to make the topPanel properly layout items
    // when the window is resized
    topPanel = new JPanel(new BorderLayout());
    JPanel logButtons = new JPanel(new WrapLayout());
    JButton expandButton = new JButton("Expand All");
    expandButton.setMnemonic(KeyEvent.VK_E);
    expandButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        expandAll();
      }
    });
    logButtons.add(expandButton);
    JButton collapseButton = new JButton("Collapse All");
    collapseButton.setMnemonic(KeyEvent.VK_O);
    collapseButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        collapseAll();
      }
    });
    logButtons.add(collapseButton);
    autoScroll = new JCheckBox("Auto-scroll", true);
    autoScroll.setMnemonic(KeyEvent.VK_U);
    logButtons.add(autoScroll);
    topPanel.add(logButtons, BorderLayout.CENTER);
    // TODO(jat): temporarily avoid showing parts that aren't implemented.
    if (false) {
      logButtons.add(new JLabel("Filter Log Messages: "));
      levelComboBox = new JComboBox();
      for (TreeLogger.Type type : TreeLogger.Type.instances()) {
        if (type.compareTo(maxLevel) > 0) {
          break;
        }
        levelComboBox.addItem(type);
      }
      levelComboBox.setEditable(false);
      levelComboBox.setSelectedIndex(levelComboBox.getItemCount() - 1);
      topPanel.add(levelComboBox);
      levelComboBox.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
          setLevelFilter((TreeLogger.Type) levelComboBox.getSelectedItem());
        }
      });
      regexField = new JTextField(20);
      logButtons.add(regexField);
      JButton applyRegexButton = new JButton("Apply Regex");
      applyRegexButton.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
          setRegexFilter(regexField.getText());
        }
      });
      logButtons.add(applyRegexButton);
      JButton clearRegexButton = new JButton("Clear Regex");
      clearRegexButton.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
          regexField.setText("");
          setRegexFilter("");
        }
      });
      logButtons.add(clearRegexButton);
    }
    closeLogger = new CloseButton("Close this log window");
    closeLogger.setCallback(new Callback() {
      // TODO(jat): add support for closing active session when SWT is removed
      @Override
      public void onCloseRequest() {
        if (disconnected && closeHandler != null) {
          closeHandler.onCloseRequest(SwingLoggerPanel.this);
        }
      }
    });
    closeLogger.setEnabled(false);
    closeLogger.setVisible(false);
    topPanel.add(closeLogger, BorderLayout.EAST);
    add(topPanel, BorderLayout.NORTH);
    root = new DefaultMutableTreeNode();
    treeModel = new DefaultTreeModel(root);
    treeModel.addTreeModelListener(new TreeModelListener() {
      @Override public void treeNodesInserted(TreeModelEvent e) {
        for (Object treeNode : e.getChildren()) {
          onTreeNodeAdded((DefaultMutableTreeNode) treeNode);
        }
      }
      @Override public void treeStructureChanged(TreeModelEvent e) { }
      @Override public void treeNodesRemoved(TreeModelEvent e) { }
      @Override public void treeNodesChanged(TreeModelEvent e) { }
    });
    tree = new JTree(treeModel);
    tree.setRootVisible(false);
    tree.setEditable(false);
    tree.setExpandsSelectedPaths(true);
    tree.setShowsRootHandles(true);
    tree.setCellRenderer(new TreeRenderer());
    tree.getSelectionModel().setSelectionMode(
        TreeSelectionModel.SINGLE_TREE_SELECTION);
    tree.addTreeSelectionListener(this);
    treeView = new JScrollPane(tree);
    // TODO(jat): better way to do this
    details = new JEditorPane() {
      @Override
      public boolean getScrollableTracksViewportWidth() {
        return true;
      }
    };
    details.setEditable(false);
    details.setContentType("text/html");
    details.setForeground(Color.BLACK);
    details.addHyperlinkListener(this);
    // font trick from http://explodingpixels.wordpress.com/2008/10/28/make-jeditorpane-use-the-system-font/
    Font font = UIManager.getFont("Label.font");
    String bodyRule = "body { font-family: " + font.getFamily() + "; "
        + "font-size: " + font.getSize() + "pt; }";
    ((HTMLDocument) details.getDocument()).getStyleSheet().addRule(bodyRule);
    JScrollPane msgView = new JScrollPane(details);
    JSplitPane splitter = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
    splitter.setTopComponent(treeView);
    splitter.setBottomComponent(msgView);
    Dimension minSize = new Dimension(100, 50);
    msgView.setMinimumSize(minSize);
    treeView.setMinimumSize(minSize);
    splitter.setDividerLocation(0.80);
    add(splitter);

    AbstractTreeLogger uiLogger = new SwingTreeLogger(this);
    uiLogger.setMaxDetail(maxLevel);
    TreeLogger bestLogger = uiLogger;
    if (logFile != null) {
      try {
        PrintWriterTreeLogger fileLogger = new PrintWriterTreeLogger(logFile);
        fileLogger.setMaxDetail(maxLevel);
        bestLogger = new CompositeTreeLogger(bestLogger, fileLogger);
      } catch (IOException ex) {
        bestLogger.log(TreeLogger.ERROR, "Can't log to file "
            + logFile.getAbsolutePath(), ex);
      }
    }
    logger = bestLogger;
    KeyStroke key = getCommandKeyStroke(KeyEvent.VK_F, false);
    getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(key, "find");
    getActionMap().put("find", new AbstractAction() {
      @Override
      public void actionPerformed(ActionEvent e) {
        showFindBox();
      }
    });
    key = getCommandKeyStroke(KeyEvent.VK_C, false);
    tree.getInputMap().put(key, "copy");
    tree.getActionMap().put("copy", new AbstractAction() {
      @Override
      public void actionPerformed(ActionEvent e) {
        treeCopy();
      }
    });
    findBox = new FindBox();
    key = getCommandKeyStroke(KeyEvent.VK_G, false);
    tree.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(key, "findnext");
    tree.getActionMap().put("findnext", new AbstractAction() {
      @Override
      public void actionPerformed(ActionEvent e) {
        findBox.nextMatch();
      }
    });
    key = getCommandKeyStroke(KeyEvent.VK_G, true);
    tree.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(key, "findprev");
    tree.getActionMap().put("findprev", new AbstractAction() {
      @Override
      public void actionPerformed(ActionEvent e) {
        findBox.prevMatch();
      }
    });
  }

  /**
   * Collapse all tree nodes.
   */
  @SuppressWarnings("unchecked")
  public void collapseAll() {
    Enumeration<TreeNode> children = root.postorderEnumeration();
    while (children.hasMoreElements()) {
      DefaultMutableTreeNode node = (DefaultMutableTreeNode) children.nextElement();
      if (node != root) {
        tree.collapsePath(new TreePath(node.getPath()));
      }
    }
    tree.invalidate();
  }

  /**
   * Show that the client connected to this logger has disconnected.
   */
  public void disconnected() {
    disconnected  = true;
    tree.setBackground(DISCONNECTED_COLOR);
    tree.repaint();
  }

  /**
   * Expand all tree nodes.
   */
  @SuppressWarnings("unchecked")
  public void expandAll() {
    Enumeration<TreeNode> children = root.postorderEnumeration();
    while (children.hasMoreElements()) {
      DefaultMutableTreeNode node = (DefaultMutableTreeNode) children.nextElement();
      if (node != root) {
        tree.expandPath(new TreePath(node.getPath()));
      }
    }
    tree.invalidate();
  }

  /**
   * @return the TreeLogger for this panel
   */
  public TreeLogger getLogger() {
    return logger;
  }

  @Override
  public void hyperlinkUpdate(HyperlinkEvent event) {
    EventType eventType = event.getEventType();
    if (eventType == HyperlinkEvent.EventType.ACTIVATED) {
      URL url = event.getURL();
      try {
        BrowserLauncher.browse(url.toExternalForm());
        return;
      } catch (Exception e) {
        // if anything fails, fall-through to failsafe implementation
      }
      // As a last resort, just use the details pane to display the HTML, but
      // this is rather poor.
      try {
        details.setPage(url);
      } catch (IOException e) {
        logger.log(TreeLogger.ERROR, "Unable to follow link to " + url, e);
      }
    }
  }

  @Override
  public void removeAll() {
    tree.removeAll();
    details.setText("");
  }

  /**
   * Sets a callback for handling a close request, which also makes the close
   * button visible.
   *
   * @param handler
   */
  public void setCloseHandler(CloseHandler handler) {
    closeHandler = handler;
    closeLogger.setEnabled(true);
    closeLogger.setVisible(true);
  }

  @Override
  public void valueChanged(TreeSelectionEvent e) {
    if (e.isAddedPath()) {
      TreePath path = e.getPath();
      Object treeNode = path.getLastPathComponent();
      if (treeNode == null) {
        // handle the case of no selection
        details.setText("");
        return;
      }
      Object userObject = ((DefaultMutableTreeNode) treeNode).getUserObject();
      String text = userObject.toString();
      if (userObject instanceof LogEvent) {
        LogEvent event = (LogEvent) userObject;
        text = event.getFullText();
      }
      details.setText(text);
    }
  }

  protected void alert(String msg) {
    JOptionPane.showMessageDialog(null, msg, "Alert: Not Implemented",
        JOptionPane.INFORMATION_MESSAGE);
  }

  /**
   * Ask the user for confirmation to close the current logger.
   *
   * @return true if the user confirmed the request
   */
  protected boolean confirmClose() {
    int response = JOptionPane.showConfirmDialog(null,
        "Close the logger for the currently displayed module",
        "Close this Logger", JOptionPane.OK_CANCEL_OPTION,
        JOptionPane.WARNING_MESSAGE);
    return response != JOptionPane.YES_OPTION;
  }

  protected ArrayList<DefaultMutableTreeNode> doFind(String search) {
    @SuppressWarnings("unchecked")
    Enumeration<TreeNode> children = root.preorderEnumeration();
    ArrayList<DefaultMutableTreeNode> matches = new ArrayList<DefaultMutableTreeNode>();
    while (children.hasMoreElements()) {
      DefaultMutableTreeNode node = (DefaultMutableTreeNode) children.nextElement();
      if (node != root && nodeMatches(node, search)) {
        matches.add(node);
        // Make sure our this entry is visible by expanding up to parent
        TreeNode[] nodePath = node.getPath();
        if (nodePath.length > 1) {
          TreeNode[] parentPath = new TreeNode[nodePath.length - 1];
          System.arraycopy(nodePath, 0, parentPath, 0, parentPath.length);
          tree.expandPath(new TreePath(parentPath));
        }
      }
    }
    tree.invalidate();
    return matches;
  }

  protected void hideFindBox() {
    findBox.hideBox();
  }

  protected void setLevelFilter(Type selectedLevel) {
    levelFilter = selectedLevel;
    // TODO(jat): filter current tree
    alert("Filtering not implemented yet");
  }

  protected void setRegexFilter(String regex) {
    regexFilter = regex;
    // TODO(jat): filter current tree
    alert("Regex filtering not implemented yet");
  }

  protected void showFindBox() {
    findBox.showBox();
  }

  protected void treeCopy() {
    DefaultMutableTreeNode node = (DefaultMutableTreeNode)
        tree.getLastSelectedPathComponent();
    if (node == null) {
      return;
    }
    // is it better to use SwingUtilities2.canAccessSystemClipboard() here?
    Clipboard clipboard;
    try {
      clipboard = tree.getToolkit().getSystemClipboard();
    } catch (SecurityException e) {
      return;
    } catch (HeadlessException e) {
      return;
    }
    if (clipboard == null) {
      return;
    }
    StringBuilder text = new StringBuilder();
    treeLogTraverse(text, node, 0);
    StringSelection selection = new StringSelection(text.toString());
    clipboard.setContents(selection, selection);
  }

  /**
   * Returns a keystroke which adds the appropriate modifier for a command key:
   * Command on mac, Ctrl everywhere else.
   *
   * @param key virtual key defined in {@code KeyEvent#VK_*}
   * @param shift true if the Ctrl/Command key must be shifted
   * @return KeyStroke of the Ctrl/Command-key
   */
  private KeyStroke getCommandKeyStroke(int key, boolean shift) {
    int mask = ctrlKeyDown;
    if (shift) {
      mask |= InputEvent.SHIFT_DOWN_MASK;
    }
    return KeyStroke.getKeyStroke(key, mask);
  }

  private String htmlUnescape(String str) {
    // TODO(jat): real implementation, needs to correspond to
    // SwingTreeLogger.htmlEscape()
    return str.replace("&lt;", "<").replace("&gt;", ">").replace("&amp;",
        "&").replace("<br>", "\n");
  }

  private boolean nodeMatches(DefaultMutableTreeNode node, String search) {
    Object userObject = node.getUserObject();
    if (userObject instanceof LogEvent) {
      LogEvent event = (LogEvent) userObject;
      String text = htmlUnescape(event.getFullText());
      // TODO(jat): should this be more than a substring match, such as regex?
      if (text.contains(search)) {
        return true;
      }
    }
    return false;
  }

  /**
   * @param search the search string, currently ignored.
   */
  private void showFindResult(DefaultMutableTreeNode node, String search) {
    // TODO(jat): highlight search string
    TreePath path = new TreePath(node.getPath());
    tree.scrollPathToVisible(path);
    tree.setSelectionPath(path);
  }

  private void treeLogTraverse(StringBuilder buf, TreeNode node,
      int indent) {
    for (int i = 0; i < indent; ++i) {
      buf.append(' ');
    }
    if (node instanceof DefaultMutableTreeNode) {
      DefaultMutableTreeNode mutableNode = (DefaultMutableTreeNode) node;
      Object userObject = mutableNode.getUserObject();
      if (userObject instanceof LogEvent) {
        LogEvent event = (LogEvent) userObject;
        buf.append(htmlUnescape(event.getFullText()));
        if (event.isBranchCommit) {
          SwingTreeLogger childLogger = event.childLogger;
          DefaultMutableTreeNode parent = childLogger.treeNode;
          for (int i = 0; i < parent.getChildCount(); ++i) {
            treeLogTraverse(buf, parent.getChildAt(i), indent + 2);
          }
        }
      } else {
        buf.append(userObject.toString());
        buf.append('\n');
      }
    } else {
      buf.append(node.toString());
      buf.append('\n');
    }
  }

  private void onTreeNodeAdded(DefaultMutableTreeNode treeNode) {
    TreePath path = new TreePath(treeNode.getPath());
    if (autoScroll.isSelected()) {
      tree.scrollPathToVisible(path); // internally will also call makeVisible
    } else {
      Object userObject = treeNode.getUserObject();
      if (userObject instanceof LogEvent) {
        if (((LogEvent) userObject).type.needsAttention()) {
          tree.makeVisible(path);
        }
      }
    }
  }
}
