All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.parosproxy.paros.view.SiteMapPanel Maven / Gradle / Ivy

Go to download

The Zed Attack Proxy (ZAP) is an easy to use integrated penetration testing tool for finding vulnerabilities in web applications. It is designed to be used by people with a wide range of security experience and as such is ideal for developers and functional testers who are new to penetration testing. ZAP provides automated scanners as well as a set of tools that allow you to find security vulnerabilities manually.

There is a newer version: 2.15.0
Show newest version
/*
 *
 * Paros and its related class files.
 *
 * Paros is an HTTP/HTTPS proxy for assessing web application security.
 * Copyright (C) 2003-2004 Chinotec Technologies Company
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the Clarified Artistic License
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * Clarified Artistic License for more details.
 *
 * You should have received a copy of the Clarified Artistic License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
// ZAP: 2012/03/03 Moved popups to stdmenus extension
// ZAP: 2012/03/15 Changed to initiate the tree with a default model. Changed to
// clear the http panels when the root node is selected.
// ZAP: 2012/04/23 Added @Override annotation to all appropriate methods.
// ZAP: 2012/06/13 Added custom tree cell renderer to treeSite in getTreeSite().
// ZAP: 2013/01/25 Added method for removing listener.
// ZAP: 2013/11/16 Issue 886: Main pop up menu invoked twice on some components
// ZAP: 2014/01/28 Issue 207: Support keyboard shortcuts
// ZAP: 2014/03/23 Tidy up, removed the instance variable rootTreePath, no need to
// cache the path
// ZAP: 2014/03/23 Issue 609: Provide a common interface to query the state and
// access the data (HttpMessage and HistoryReference) displayed in the tabs
// ZAP: 2014/10/07 Issue 1357: Hide unused tabs
// ZAP: 2014/12/17 Issue 1174: Support a Site filter
// ZAP: 2014/12/22 Issue 1476: Display contexts in the Sites tree
// ZAP: 2015/02/09 Issue 1525: Introduce a database interface layer to allow for alternative
// implementations
// ZAP: 2015/02/10 Issue 1528: Support user defined font size
// ZAP: 2015/06/01 Issue 1653: Support context menu key for trees
// ZAP: 2016/04/14 Use View to display the HTTP messages
// ZAP: 2016/07/01 Issue 2642: Slow mouse wheel scrolling in site tree
// ZAP: 2017/03/28 Issue 3253: Facilitate exporting URLs by context (add getSelectedContext)
// ZAP: 2017/09/02 Use KeyEvent instead of Event (deprecated in Java 9).
// ZAP: 2017/11/01 Delete context with keyboard shortcut.
// ZAP: 2017/11/16 Hide filtered nodes in macOS L&F.
// ZAP: 2017/11/29 Delete site nodes with keyboard shortcut.
// ZAP: 2017/12/22 Select context on row click.
// ZAP: 2018/03/26 Expand node of selected context.
// ZAP: 2018/04/12 Keep panel of selected context selected.
// ZAP: 2018/07/17 Use ViewDelegate.getMenuShortcutKeyStroke.
// ZAP: 2019/06/01 Normalise line endings.
// ZAP: 2019/06/05 Normalise format/style.
// ZAP: 2019/07/10 Update to use Context.getId following deprecation of Context.getIndex
// ZAP: 2019/09/09 Issue 3491: Add support for selecting multiple contexts
// ZAP: 2020/11/26 Use Log4j 2 classes for logging.
package org.parosproxy.paros.view;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JToggleButton;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
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;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.parosproxy.paros.Constant;
import org.parosproxy.paros.control.Control;
import org.parosproxy.paros.db.DatabaseException;
import org.parosproxy.paros.extension.AbstractPanel;
import org.parosproxy.paros.extension.history.ExtensionHistory;
import org.parosproxy.paros.extension.history.LogPanel;
import org.parosproxy.paros.model.HistoryReference;
import org.parosproxy.paros.model.Model;
import org.parosproxy.paros.model.SiteMap;
import org.parosproxy.paros.model.SiteNode;
import org.parosproxy.paros.network.HttpMessage;
import org.zaproxy.zap.extension.history.HistoryFilterPlusDialog;
import org.zaproxy.zap.model.Context;
import org.zaproxy.zap.model.Target;
import org.zaproxy.zap.utils.DisplayUtils;
import org.zaproxy.zap.view.ContextCreateDialog;
import org.zaproxy.zap.view.ContextGeneralPanel;
import org.zaproxy.zap.view.ContextsSitesPanel;
import org.zaproxy.zap.view.ContextsTreeCellRenderer;
import org.zaproxy.zap.view.DeleteContextAction;
import org.zaproxy.zap.view.LayoutHelper;
import org.zaproxy.zap.view.SiteMapListener;
import org.zaproxy.zap.view.SiteMapTreeCellRenderer;
import org.zaproxy.zap.view.SiteTreeFilter;
import org.zaproxy.zap.view.ZapToggleButton;
import org.zaproxy.zap.view.messagecontainer.http.DefaultSelectableHistoryReferencesContainer;
import org.zaproxy.zap.view.messagecontainer.http.SelectableHistoryReferencesContainer;

public class SiteMapPanel extends AbstractPanel {

    public static final String CONTEXT_TREE_COMPONENT_NAME = "ContextTree";

    private static final long serialVersionUID = -3161729504065679088L;

    // ZAP: Added logger
    private static Logger log = LogManager.getLogger(SiteMapPanel.class);

    private JTree treeSite = null;
    private JTree treeContext = null;
    private DefaultTreeModel contextTree = null;
    private View view = null;

    private javax.swing.JToolBar panelToolbar = null;
    private ZapToggleButton scopeButton = null;
    private JButton filterButton = null;
    private JLabel filterStatus = null;
    private HistoryFilterPlusDialog filterPlusDialog = null;
    private JButton createContextButton = null;
    private JButton importContextButton = null;
    private JButton exportContextButton = null;

    // ZAP: Added SiteMapListenners
    private List listeners = new ArrayList<>();

    /** This is the default constructor */
    public SiteMapPanel() {
        super();
        initialize();
    }

    private View getView() {
        if (view == null) {
            view = View.getSingleton();
        }

        return view;
    }
    /** This method initializes this */
    private void initialize() {
        this.setHideable(false);
        this.setIcon(new ImageIcon(View.class.getResource("/resource/icon/16/094.png")));
        this.setName(Constant.messages.getString("sites.panel.title"));
        this.setDefaultAccelerator(
                getView().getMenuShortcutKeyStroke(KeyEvent.VK_S, KeyEvent.SHIFT_DOWN_MASK, false));
        this.setMnemonic(Constant.messages.getChar("sites.panel.mnemonic"));

        if (Model.getSingleton().getOptionsParam().getViewParam().getWmUiHandlingOption() == 0) {
            this.setSize(300, 200);
        }

        this.setLayout(new GridBagLayout());
        this.add(this.getPanelToolbar(), LayoutHelper.getGBC(0, 0, 1, 0, new Insets(2, 2, 2, 2)));
        this.add(
                new ContextsSitesPanel(getTreeContext(), getTreeSite(), "sitesPanelScrollPane"),
                LayoutHelper.getGBC(
                        0, 1, 1, 1.0, 1.0, GridBagConstraints.BOTH, new Insets(2, 2, 2, 2)));

        expandRoot();
    }

    private javax.swing.JToolBar getPanelToolbar() {
        if (panelToolbar == null) {

            panelToolbar = new javax.swing.JToolBar();
            panelToolbar.setLayout(new GridBagLayout());
            panelToolbar.setEnabled(true);
            panelToolbar.setFloatable(false);
            panelToolbar.setRollover(true);
            panelToolbar.setPreferredSize(new Dimension(800, 30));
            panelToolbar.setName("ScriptsListToolbar");

            int i = 1;
            panelToolbar.add(getScopeButton(), LayoutHelper.getGBC(i++, 0, 1, 0.0D));
            panelToolbar.add(getCreateContextButton(), LayoutHelper.getGBC(i++, 0, 1, 0.0D));
            panelToolbar.add(getImportContextButton(), LayoutHelper.getGBC(i++, 0, 1, 0.0D));
            panelToolbar.add(getExportContextButton(), LayoutHelper.getGBC(i++, 0, 1, 0.0D));

            // TODO Disabled for now due to problems with scrolling with sparcely populated filtered
            // trees
            // panelToolbar.add(getFilterButton(), LayoutHelper.getGBC(i++, 0, 1, 0.0D));
            // panelToolbar.add(getFilterStatus(), LayoutHelper.getGBC(i++, 0, 1, 0.0D));
            panelToolbar.add(new JLabel(), LayoutHelper.getGBC(20, 0, 1, 1.0D)); // spacer
        }
        return panelToolbar;
    }

    private HistoryFilterPlusDialog getFilterPlusDialog() {
        if (filterPlusDialog == null) {
            filterPlusDialog = new HistoryFilterPlusDialog(getView().getMainFrame(), true);
            // Override the title as we're reusing the history filter dialog
            filterPlusDialog.setTitle(Constant.messages.getString("sites.filter.title"));
        }
        return filterPlusDialog;
    }

    private JLabel getFilterStatus() {
        filterStatus =
                new JLabel(
                        Constant.messages.getString("history.filter.label.filter")
                                + Constant.messages.getString("history.filter.label.off"));
        return filterStatus;
    }

    private JButton getFilterButton() {
        if (filterButton == null) {
            filterButton = new JButton();
            filterButton.setIcon(
                    DisplayUtils.getScaledIcon(
                            new ImageIcon(
                                    LogPanel.class.getResource(
                                            "/resource/icon/16/054.png")))); // 'filter' icon
            filterButton.setToolTipText(
                    Constant.messages.getString("history.filter.button.filter"));

            filterButton.addActionListener(
                    new java.awt.event.ActionListener() {

                        @Override
                        public void actionPerformed(java.awt.event.ActionEvent e) {
                            showFilterPlusDialog();
                        }
                    });
        }
        return filterButton;
    }

    private JButton getCreateContextButton() {
        if (createContextButton == null) {
            createContextButton = new JButton();
            createContextButton.setIcon(
                    DisplayUtils.getScaledIcon(
                            new ImageIcon(
                                    LogPanel.class.getResource(
                                            "/resource/icon/fugue/application-blue-plus.png"))));
            createContextButton.setToolTipText(
                    Constant.messages.getString("menu.file.context.create"));
            createContextButton.addActionListener(
                    new java.awt.event.ActionListener() {
                        @Override
                        public void actionPerformed(java.awt.event.ActionEvent e) {
                            ContextCreateDialog ccd =
                                    new ContextCreateDialog(View.getSingleton().getMainFrame());
                            ccd.setVisible(true);
                        }
                    });
        }
        return createContextButton;
    }

    private JButton getImportContextButton() {
        if (importContextButton == null) {
            importContextButton = new JButton();
            importContextButton.setIcon(
                    DisplayUtils.getScaledIcon(
                            new ImageIcon(
                                    LogPanel.class.getResource(
                                            "/resource/icon/fugue/application-blue-import.png"))));
            importContextButton.setToolTipText(
                    Constant.messages.getString("menu.file.context.import"));
            importContextButton.addActionListener(
                    new java.awt.event.ActionListener() {
                        @Override
                        public void actionPerformed(java.awt.event.ActionEvent e) {
                            Control.getSingleton().getMenuFileControl().importContext();
                        }
                    });
        }
        return importContextButton;
    }

    private JButton getExportContextButton() {
        if (exportContextButton == null) {
            exportContextButton = new JButton();
            exportContextButton.setIcon(
                    DisplayUtils.getScaledIcon(
                            new ImageIcon(
                                    LogPanel.class.getResource(
                                            "/resource/icon/fugue/application-blue-export.png"))));
            exportContextButton.setToolTipText(
                    Constant.messages.getString("menu.file.context.export"));
            exportContextButton.addActionListener(
                    new java.awt.event.ActionListener() {
                        @Override
                        public void actionPerformed(java.awt.event.ActionEvent e) {
                            Control.getSingleton().getMenuFileControl().exportContext();
                        }
                    });
        }
        return exportContextButton;
    }

    private void showFilterPlusDialog() {
        HistoryFilterPlusDialog dialog = getFilterPlusDialog();
        dialog.setModal(true);
        try {
            dialog.setAllTags(Model.getSingleton().getDb().getTableTag().getAllTags());
        } catch (DatabaseException e) {
            log.error(e.getMessage(), e);
        }

        int exit = dialog.showDialog();
        SiteTreeFilter filter = new SiteTreeFilter(dialog.getFilter());
        filter.setInScope(this.getScopeButton().isSelected());
        if (exit != JOptionPane.CANCEL_OPTION) {
            setFilter();
        }
    }

    private void setFilter() {
        SiteTreeFilter filter = new SiteTreeFilter(getFilterPlusDialog().getFilter());
        filter.setInScope(scopeButton.isSelected());
        ((SiteMap) treeSite.getModel()).setFilter(filter);
        ((DefaultTreeModel) treeSite.getModel())
                .nodeStructureChanged((SiteNode) treeSite.getModel().getRoot());
        getFilterStatus().setText(filter.toShortString());
        getFilterStatus().setToolTipText(filter.toLongString());
        expandRoot();

        // Remove any out of scope contexts too
        this.reloadContextTree();
    }

    private JToggleButton getScopeButton() {
        if (scopeButton == null) {
            scopeButton = new ZapToggleButton();
            scopeButton.setIcon(
                    DisplayUtils.getScaledIcon(
                            new ImageIcon(
                                    SiteMapPanel.class.getResource(
                                            "/resource/icon/fugue/target-grey.png"))));
            scopeButton.setToolTipText(
                    Constant.messages.getString("history.scope.button.unselected"));
            scopeButton.setSelectedIcon(
                    DisplayUtils.getScaledIcon(
                            new ImageIcon(
                                    SiteMapPanel.class.getResource(
                                            "/resource/icon/fugue/target.png"))));
            scopeButton.setSelectedToolTipText(
                    Constant.messages.getString("history.scope.button.selected"));

            scopeButton.addActionListener(
                    new java.awt.event.ActionListener() {
                        @Override
                        public void actionPerformed(java.awt.event.ActionEvent e) {
                            setFilter();
                        }
                    });
        }
        return scopeButton;
    }

    /**
     * This method initializes treeSite
     *
     * @return javax.swing.JTree
     */
    public JTree getTreeSite() {
        if (treeSite == null) {
            treeSite = new JTree(new DefaultTreeModel(new DefaultMutableTreeNode()));
            treeSite.setShowsRootHandles(true);
            treeSite.setName("treeSite");
            treeSite.setToggleClickCount(1);

            // Force macOS L&F to query the row height from SiteMapTreeCellRenderer to hide the
            // filtered nodes.
            // Other L&Fs hide the filtered nodes by default.
            LookAndFeel laf = UIManager.getLookAndFeel();
            if (laf != null
                    && Constant.isMacOsX()
                    && UIManager.getSystemLookAndFeelClassName().equals(laf.getClass().getName())) {
                treeSite.setRowHeight(0);
            }

            treeSite.addTreeSelectionListener(
                    new javax.swing.event.TreeSelectionListener() {

                        @Override
                        public void valueChanged(javax.swing.event.TreeSelectionEvent e) {

                            SiteNode node = (SiteNode) treeSite.getLastSelectedPathComponent();
                            if (node == null) {
                                return;
                            }
                            if (!node.isRoot()) {
                                HttpMessage msg = null;
                                try {
                                    msg = node.getHistoryReference().getHttpMessage();
                                } catch (Exception e1) {
                                    // ZAP: Log exceptions
                                    log.warn(e1.getMessage(), e1);
                                    return;
                                }

                                getView().displayMessage(msg);

                                // ZAP: Call SiteMapListenners
                                for (SiteMapListener listener : listeners) {
                                    listener.nodeSelected(node);
                                }
                            } else {
                                // ZAP: clear the views when the root is selected
                                getView().displayMessage(null);
                            }
                        }
                    });
            treeSite.setComponentPopupMenu(new SitesCustomPopupMenu());

            // ZAP: Add custom tree cell renderer.
            DefaultTreeCellRenderer renderer = new SiteMapTreeCellRenderer(listeners);
            treeSite.setCellRenderer(renderer);

            String deleteSiteNode = "zap.delete.sitenode";
            treeSite.getInputMap().put(getView().getDefaultDeleteKeyStroke(), deleteSiteNode);
            treeSite.getActionMap()
                    .put(
                            deleteSiteNode,
                            new AbstractAction() {

                                private static final long serialVersionUID = 1L;

                                @Override
                                public void actionPerformed(ActionEvent e) {
                                    ExtensionHistory extHistory =
                                            Control.getSingleton()
                                                    .getExtensionLoader()
                                                    .getExtension(ExtensionHistory.class);
                                    if (extHistory == null || treeSite.getSelectionCount() == 0) {
                                        return;
                                    }

                                    int result =
                                            View.getSingleton()
                                                    .showConfirmDialog(
                                                            Constant.messages.getString(
                                                                    "sites.purge.warning"));
                                    if (result != JOptionPane.YES_OPTION) {
                                        return;
                                    }

                                    SiteMap siteMap =
                                            Model.getSingleton().getSession().getSiteTree();
                                    for (TreePath path : treeSite.getSelectionPaths()) {
                                        extHistory.purge(
                                                siteMap, (SiteNode) path.getLastPathComponent());
                                    }
                                }
                            });
        }
        return treeSite;
    }

    public void reloadContextTree() {
        SiteNode root;
        if (this.contextTree == null) {
            root = new SiteNode(null, -1, Constant.messages.getString("context.list"));
            this.contextTree = new DefaultTreeModel(root);
        } else {
            root = (SiteNode) this.contextTree.getRoot();
            root.removeAllChildren();
        }
        for (Context ctx : Model.getSingleton().getSession().getContexts()) {
            if (ctx.isInScope() || !this.getScopeButton().isSelected()) {
                // Add all in scope contexts, and out of scope ones if scope button not pressed
                SiteNode node = new SiteNode(null, HistoryReference.TYPE_PROXIED, ctx.getName());
                node.setUserObject(new Target(ctx));
                root.add(node);
            }
        }
        this.contextTree.nodeStructureChanged(root);
    }

    /**
     * Returns the Context which is selected in the Site Map panel of the UI or {@code null} if
     * nothing is selected or the selection is the root node.
     *
     * @return Context the context which is selected in the UI
     * @since 2.7.0
     */
    public Context getSelectedContext() {
        SiteNode node = (SiteNode) treeContext.getLastSelectedPathComponent();
        if (node == null || node.isRoot()) {
            return null;
        }
        Target target = (Target) node.getUserObject();
        if (target != null) {
            return target.getContext();
        }
        return null;
    }

    /**
     * Returns the List of Context selected in the Site Map panel of the UI or an empty List if
     * nothing is selected or the selection is the root node.
     *
     * @return List of Context selected in the UI
     * @since 2.9.0
     */
    public List getSelectedContexts() {
        TreePath[] paths = treeContext.getSelectionPaths();
        if (paths == null || paths.length == 0) return Collections.emptyList();

        SiteNode[] nodes =
                Arrays.stream(paths)
                        .map(p -> (SiteNode) p.getLastPathComponent())
                        .toArray(SiteNode[]::new);

        // if only the root is selected no contexts are selected
        if (nodes.length == 1 && nodes[0].isRoot()) return Collections.emptyList();

        Stream targets = Arrays.stream(nodes).map(n -> (Target) n.getUserObject());

        return Arrays.asList(targets.map(Target::getContext).toArray(Context[]::new));
    }

    private JTree getTreeContext() {
        if (treeContext == null) {
            reloadContextTree();
            treeContext = new JTree(this.contextTree);
            treeContext.setShowsRootHandles(true);
            treeContext.setName(CONTEXT_TREE_COMPONENT_NAME);
            treeContext.setToggleClickCount(1);
            treeContext
                    .getSelectionModel()
                    .setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);

            treeContext.addMouseListener(
                    new java.awt.event.MouseAdapter() {
                        @Override
                        public void mousePressed(java.awt.event.MouseEvent e) {}

                        @Override
                        public void mouseReleased(java.awt.event.MouseEvent e) {
                            mouseClicked(e);
                        }

                        @Override
                        public void mouseClicked(java.awt.event.MouseEvent e) {
                            TreePath path =
                                    treeContext.getClosestPathForLocation(e.getX(), e.getY());
                            if (treeSite.getLastSelectedPathComponent() != null) {
                                getTreeSite().clearSelection();
                            }
                            if (path != null) {
                                if (((SiteNode) path.getLastPathComponent()).isRoot()) {
                                    treeContext.removeSelectionPath(path);
                                }
                            }
                            if (e.getClickCount() > 1) {
                                // Its a double click - show the relevant context dialog
                                SiteNode node =
                                        (SiteNode) treeContext.getLastSelectedPathComponent();
                                if (node != null && node.getUserObject() != null) {
                                    Target target = (Target) node.getUserObject();
                                    String panelName =
                                            ContextGeneralPanel.getPanelName(target.getContext());
                                    getView().getSessionDialog().expandParamPanelNode(panelName);
                                    if (getView()
                                            .getSessionDialog()
                                            .isParamPanelOrChildSelected(panelName)) {
                                        panelName = null;
                                    }
                                    getView()
                                            .showSessionDialog(
                                                    Model.getSingleton().getSession(), panelName);
                                }
                            }
                        }
                    });
            treeContext.setComponentPopupMenu(new ContextsCustomPopupMenu());

            treeContext.setCellRenderer(new ContextsTreeCellRenderer());
            DeleteContextAction delContextAction =
                    new DeleteContextAction() {

                        private static final long serialVersionUID = 1L;

                        @Override
                        protected List getContexts() {
                            return getSelectedContexts();
                        }

                        @Override
                        protected Context getContext() {
                            return getSelectedContext();
                        }
                    };
            treeContext
                    .getInputMap()
                    .put(
                            (KeyStroke)
                                    delContextAction.getValue(DeleteContextAction.ACCELERATOR_KEY),
                            DeleteContextAction.ACTION_NAME);
            treeContext.getActionMap().put(DeleteContextAction.ACTION_NAME, delContextAction);
        }
        return treeContext;
    }

    public void expandRoot() {
        TreeNode root = (TreeNode) treeSite.getModel().getRoot();
        if (root == null) {
            return;
        }
        final TreePath rootTreePath = new TreePath(root);

        if (EventQueue.isDispatchThread()) {
            getTreeSite().expandPath(rootTreePath);
            return;
        }
        try {
            EventQueue.invokeLater(
                    new Runnable() {
                        @Override
                        public void run() {
                            getTreeSite().expandPath(rootTreePath);
                        }
                    });
        } catch (Exception e) {
            // ZAP: Log exceptions
            log.warn(e.getMessage(), e);
        }
    }

    // ZAP: Added addSiteMapListenners
    public void addSiteMapListener(SiteMapListener listenner) {
        this.listeners.add(listenner);
    }

    public void removeSiteMapListener(SiteMapListener listener) {
        this.listeners.remove(listener);
    }

    public void showInSites(SiteNode node) {
        TreeNode[] path = node.getPath();
        TreePath tp = new TreePath(path);
        treeSite.setExpandsSelectedPaths(true);
        treeSite.setSelectionPath(tp);
        treeSite.scrollPathToVisible(tp);
    }

    public void contextChanged(Context c) {
        getTreeContext();
        SiteNode root = (SiteNode) this.contextTree.getRoot();
        for (int i = 0; i < root.getChildCount(); i++) {
            SiteNode node = (SiteNode) root.getChildAt(i);
            Target target = (Target) node.getUserObject();
            if (c.getId() == target.getContext().getId()) {
                target.setContext(c);
                if (node.getNodeName().equals(c.getName())) {
                    this.contextTree.nodeChanged(node);
                } else {
                    this.reloadContextTree();
                }
                break;
            }
        }
    }

    protected class SitesCustomPopupMenu extends JPopupMenu {
        private static final long serialVersionUID = 1L;

        @Override
        public void show(Component invoker, int x, int y) {
            // ZAP: Select site list item on right click / menu key
            TreePath tp = treeSite.getPathForLocation(x, y);
            if (tp != null) {
                boolean select = true;
                // Only select a new item if the current item is not
                // already selected - this is to allow multiple items
                // to be selected
                if (treeSite.getSelectionPaths() != null) {
                    for (TreePath t : treeSite.getSelectionPaths()) {
                        if (t.equals(tp)) {
                            select = false;
                            break;
                        }
                    }
                }
                if (select) {
                    treeSite.getSelectionModel().setSelectionPath(tp);
                }
            }

            final int countSelectedNodes = treeSite.getSelectionCount();
            final List historyReferences = new ArrayList<>(countSelectedNodes);
            if (countSelectedNodes > 0) {
                for (TreePath path : treeSite.getSelectionPaths()) {
                    final SiteNode node = (SiteNode) path.getLastPathComponent();
                    final HistoryReference historyReference = node.getHistoryReference();
                    if (historyReference != null) {
                        historyReferences.add(historyReference);
                    }
                }
            }
            SelectableHistoryReferencesContainer messageContainer =
                    new DefaultSelectableHistoryReferencesContainer(
                            treeSite.getName(),
                            treeSite,
                            Collections.emptyList(),
                            historyReferences);
            View.getSingleton().getPopupMenu().show(messageContainer, x, y);
        }
    }

    protected class ContextsCustomPopupMenu extends JPopupMenu {
        private static final long serialVersionUID = 1L;

        @Override
        public void show(Component invoker, int x, int y) {
            // Select context list item on right click
            TreePath tp = treeContext.getPathForLocation(x, y);
            if (tp != null) {
                boolean select = true;
                // Only select a new item if the current item is not
                // already selected - this is to allow multiple items
                // to be selected
                if (treeContext.getSelectionPaths() != null) {
                    for (TreePath t : treeContext.getSelectionPaths()) {
                        if (t.equals(tp)) {
                            select = false;
                            break;
                        }
                    }
                }
                if (select) {
                    treeContext.getSelectionModel().setSelectionPath(tp);
                }
            }
            View.getSingleton().getPopupMenu().show(treeContext, x, y);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy