blob: 6fbf47fd98323e7555706f1055653fa648a67f21 [file] [log] [blame]
/*
* 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.netbeans.modules.maven.dependencies;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.Icon;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.dependency.tree.DependencyNode;
import static org.netbeans.modules.maven.dependencies.Bundle.*;
import org.netbeans.modules.maven.embedder.DependencyTreeFactory;
import org.netbeans.modules.maven.embedder.EmbedderFactory;
import org.netbeans.modules.maven.spi.IconResources;
import org.openide.NotificationLineSupport;
import org.openide.util.ImageUtilities;
import org.openide.util.NbBundle.Messages;
import org.openide.util.RequestProcessor;
/**
*
* @author mkleint
*/
public class ExcludeDependencyPanel extends javax.swing.JPanel {
private MavenProject project;
private DependencyNode rootnode;
private Map<Artifact, TreeModel> modelCache;
private Map<ChangeListener, CheckNode> change2Trans;
private Map<ChangeListener, List<CheckNode>> change2Refs;
private boolean isSingle = false;
private NotificationLineSupport lineSupport;
/** Creates new form ExcludeDependencyPanel */
public ExcludeDependencyPanel(MavenProject prj, final Artifact single, final Set<DependencyNode> directs, final DependencyNode root) {
project = prj;
modelCache = new HashMap<Artifact, TreeModel>();
change2Trans = new HashMap<ChangeListener, CheckNode>();
change2Refs = new HashMap<ChangeListener, List<CheckNode>>();
initComponents();
isSingle = single != null;
if (isSingle) {
trTrans.setVisible(false);
jScrollPane1.setVisible(false);
jLabel1.setVisible(false);
}
// ToolTipManager.sharedInstance().registerComponent(trRef);
trRef.setCellRenderer(new CheckRenderer(false));
trTrans.setCellRenderer(new CheckRenderer(true));
CheckNodeListener l = new CheckNodeListener(false);
trRef.addMouseListener(l);
trRef.addKeyListener(l);
trRef.setToggleClickCount(0);
trRef.setRootVisible(false);
SwingUtilities.invokeLater(() -> trRef.setModel(new DefaultTreeModel(new DefaultMutableTreeNode())));
new RequestProcessor(ExcludeDependencyPanel.class.getName()).post(() -> {
if (!isSingle) {
rootnode = DependencyTreeFactory.createDependencyTree(project, EmbedderFactory.getOnlineEmbedder(), Artifact.SCOPE_TEST);
} else {
rootnode = root;
}
SwingUtilities.invokeLater(() -> {
if (!isSingle) {
trTrans.setModel(new DefaultTreeModel(createTransitiveDependenciesList()));
} else {
CheckNode nd = new CheckNode(single, null, null);
DefaultTreeModel dtm = new DefaultTreeModel(createReferenceModel(directs, nd));
modelCache.put(single, dtm);
setReferenceTree(nd);
trTrans.setModel(new DefaultTreeModel(new DefaultMutableTreeNode()));
}
});
});
trTrans.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
printSpaceMessage();
}
@Override
public void focusLost(FocusEvent e) {
printSpaceMessage();
}
});
trTrans.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
printSpaceMessage();
}
});
trTrans.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {}
@Override
public void keyPressed(KeyEvent e) {
if (KeyEvent.VK_SPACE == e.getKeyCode()) {
TreePath path = trTrans.getSelectionPath();
CheckNode nd = (CheckNode) path.getLastPathComponent();
TreeModel mdl = trRef.getModel();
int childs = mdl.getChildCount(mdl.getRoot());
for (int i = 0; i < childs; i++) {
CheckNode refNode = (CheckNode) mdl.getChild(mdl.getRoot(), i);
refNode.setSelected(true);
}
trRef.repaint();
}
}
@Override
public void keyReleased(KeyEvent e) {}
});
}
public ExcludeDependencyPanel(MavenProject prj) {
this(prj, null, null, null);
}
public Map<Artifact, List<DependencyNode>> getDependencyExcludes() {
Map<Artifact, List<DependencyNode>> toRet = new HashMap<Artifact, List<DependencyNode>>();
for (ChangeListener list : change2Trans.keySet()) {
CheckNode trans = change2Trans.get(list);
List<CheckNode> refs = change2Refs.get(list);
List<DependencyNode> nds = new ArrayList<DependencyNode>();
for (CheckNode ref : refs) {
if (ref.isSelected()) {
nds.add((DependencyNode)ref.getUserObject());
}
}
toRet.put((Artifact)trans.getUserObject(), nds);
}
return toRet;
}
public void setStatusDisplayer(NotificationLineSupport createNotificationLineSupport) {
lineSupport = createNotificationLineSupport;
}
@Messages("TXT_Exclude_all=Exclude from all by pressing 'SPACE' key.")
private void printSpaceMessage() {
if (lineSupport == null) {
return;
}
if (trTrans.isFocusOwner() && trTrans.getSelectionPath() != null) {
lineSupport.setInformationMessage(TXT_Exclude_all());
} else {
lineSupport.clearMessages();
}
}
private TreeNode createReferenceModel(Set<DependencyNode> nds, CheckNode trans) {
DefaultMutableTreeNode root = new DefaultMutableTreeNode(null, true);
ChangeListener list = new Listener();
List<CheckNode> s = new ArrayList<CheckNode>();
Icon icn = ImageUtilities.image2Icon(ImageUtilities.loadImage(IconResources.DEPENDENCY_ICON, true)); //NOI18N
change2Trans.put(list, trans);
change2Refs.put(list, s);
for (DependencyNode nd : nds) {
String label = nd.getArtifact().getGroupId() + ":" + nd.getArtifact().getArtifactId();
CheckNode child = new CheckNode(nd, label, icn);
child.setSelected(isSingle);
child.addChangeListener(list);
s.add(child);
root.add(child);
}
return root;
}
private TreeNode createTransitiveDependenciesList() {
DefaultMutableTreeNode root = new DefaultMutableTreeNode(null, true);
Set<Artifact> artifacts = project.getArtifacts();
Icon icn = ImageUtilities.image2Icon(ImageUtilities.loadImage(IconResources.TRANSITIVE_DEPENDENCY_ICON, true)); //NOI18N
for (Artifact a : artifacts) {
if (a.getDependencyTrail().size() > 2) {
String label = a.getGroupId() + ":" + a.getArtifactId();
root.add(new CheckNode(a, label, icn));
}
}
return root;
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
trTrans = new javax.swing.JTree();
jScrollPane2 = new javax.swing.JScrollPane();
trRef = new javax.swing.JTree();
jLabel1 = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
trTrans.setRootVisible(false);
trTrans.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
public void valueChanged(javax.swing.event.TreeSelectionEvent evt) {
trTransValueChanged(evt);
}
});
jScrollPane1.setViewportView(trTrans);
javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("root");
trRef.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1));
trRef.setRootVisible(false);
jScrollPane2.setViewportView(trRef);
jLabel1.setText(org.openide.util.NbBundle.getBundle(ExcludeDependencyPanel.class).getString("ExcludeDependencyPanel.jLabel1.text")); // NOI18N
jLabel2.setText(org.openide.util.NbBundle.getBundle(ExcludeDependencyPanel.class).getString("ExcludeDependencyPanel.jLabel2.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel1)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 315, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jLabel2, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 320, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel1)
.addComponent(jLabel2))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 363, Short.MAX_VALUE)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 363, Short.MAX_VALUE)))
);
}// </editor-fold>//GEN-END:initComponents
private void setReferenceTree(CheckNode mtb) {
Artifact art = (Artifact) mtb.getUserObject();
if (modelCache.containsKey(art)) {
trRef.setModel(modelCache.get(art));
} else {
if (rootnode == null) {
trRef.setModel(new DefaultTreeModel(new DefaultMutableTreeNode()));
} else {
DependencyExcludeNodeVisitor nv = new DependencyExcludeNodeVisitor(art.getGroupId(), art.getArtifactId(), art.getType());
rootnode.accept(nv);
Set<DependencyNode> nds = nv.getDirectDependencies();
DefaultTreeModel dtm = new DefaultTreeModel(createReferenceModel(nds, mtb));
trRef.setModel(dtm);
modelCache.put(art, dtm);
}
}
}
private void trTransValueChanged(javax.swing.event.TreeSelectionEvent evt) {//GEN-FIRST:event_trTransValueChanged
TreeNode tn = (TreeNode) evt.getPath().getLastPathComponent();
if (tn instanceof CheckNode) {
setReferenceTree((CheckNode)tn);
} else {
trRef.setModel(new DefaultTreeModel(new DefaultMutableTreeNode()));
}
}//GEN-LAST:event_trTransValueChanged
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JTree trRef;
private javax.swing.JTree trTrans;
// End of variables declaration//GEN-END:variables
private class Listener implements ChangeListener {
@Override
public void stateChanged(ChangeEvent e) {
CheckNode trans = change2Trans.get(this);
List<CheckNode> refs = change2Refs.get(this);
boolean all = true;
boolean some = false;
for (CheckNode ref : refs) {
if (!ref.isSelected()) {
all = false;
}
if (ref.isSelected()) {
some = true;
}
}
if (all) {
//competely gone.. -> strikethrough
trans.strike();
} else {
trans.unstrike();
}
if (some) {
trans.italic();
} else {
trans.unitalic();
}
if (trTrans.isVisible()) {
trTrans.repaint();
}
}
}
}