2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org
.jetbrains
.idea
.maven
.navigator
;
18 import com
.intellij
.ide
.projectView
.impl
.nodes
.NamedLibraryElement
;
19 import com
.intellij
.ide
.util
.treeView
.NodeDescriptor
;
20 import com
.intellij
.ide
.util
.treeView
.NodeRenderer
;
21 import com
.intellij
.openapi
.module
.Module
;
22 import com
.intellij
.openapi
.project
.Project
;
23 import com
.intellij
.openapi
.roots
.OrderEntry
;
24 import com
.intellij
.openapi
.roots
.ui
.configuration
.ProjectSettingsService
;
25 import com
.intellij
.openapi
.util
.Comparing
;
26 import com
.intellij
.openapi
.util
.Disposer
;
27 import com
.intellij
.openapi
.util
.Pair
;
28 import com
.intellij
.openapi
.util
.text
.StringUtil
;
29 import com
.intellij
.openapi
.vfs
.VirtualFile
;
30 import com
.intellij
.pom
.Navigatable
;
31 import com
.intellij
.psi
.PsiManager
;
32 import com
.intellij
.ui
.ErrorLabel
;
33 import com
.intellij
.ui
.GroupedElementsRenderer
;
34 import com
.intellij
.ui
.SimpleTextAttributes
;
35 import com
.intellij
.ui
.treeStructure
.*;
36 import com
.intellij
.util
.containers
.ContainerUtil
;
37 import gnu
.trove
.THashMap
;
38 import org
.jetbrains
.annotations
.NonNls
;
39 import org
.jetbrains
.annotations
.Nullable
;
40 import org
.jetbrains
.annotations
.TestOnly
;
41 import org
.jetbrains
.idea
.maven
.embedder
.MavenEmbedderFactory
;
42 import org
.jetbrains
.idea
.maven
.importing
.MavenRootModelAdapter
;
43 import org
.jetbrains
.idea
.maven
.project
.*;
44 import org
.jetbrains
.idea
.maven
.tasks
.MavenShortcutsManager
;
45 import org
.jetbrains
.idea
.maven
.tasks
.MavenTasksManager
;
46 import org
.jetbrains
.idea
.maven
.utils
.*;
49 import javax
.swing
.tree
.DefaultTreeModel
;
50 import javax
.swing
.tree
.TreeCellRenderer
;
51 import javax
.swing
.tree
.TreePath
;
53 import java
.awt
.event
.InputEvent
;
56 import java
.util
.List
;
58 import static org
.jetbrains
.idea
.maven
.project
.ProjectBundle
.message
;
60 public class MavenProjectsStructure
extends SimpleTreeStructure
{
61 private static final URL ERROR_ICON_URL
= MavenProjectsStructure
.class.getResource("/images/error.png");
62 private static final Collection
<String
> BASIC_PHASES
= MavenEmbedderFactory
.getBasicPhasesList();
63 private static final Collection
<String
> PHASES
= MavenEmbedderFactory
.getPhasesList();
65 private static final Comparator
<MavenSimpleNode
> NODE_COMPARATOR
= new Comparator
<MavenSimpleNode
>() {
66 public int compare(MavenSimpleNode o1
, MavenSimpleNode o2
) {
67 return Comparing
.compare(o1
.getName(), o2
.getName());
71 private final Project myProject
;
72 private final MavenProjectsManager myProjectsManager
;
73 private final MavenTasksManager myTasksManager
;
74 private final MavenShortcutsManager myShortcutsManager
;
75 private final MavenProjectsNavigator myProjectsNavigator
;
77 private final SimpleTreeBuilder myTreeBuilder
;
78 private final RootNode myRoot
= new RootNode();
80 private final Map
<MavenProject
, ProjectNode
> myProjectToNodeMapping
= new THashMap
<MavenProject
, ProjectNode
>();
82 public MavenProjectsStructure(Project project
,
83 MavenProjectsManager projectsManager
,
84 MavenTasksManager tasksManager
,
85 MavenShortcutsManager shortcutsManager
,
86 MavenProjectsNavigator projectsNavigator
,
89 myProjectsManager
= projectsManager
;
90 myTasksManager
= tasksManager
;
91 myShortcutsManager
= shortcutsManager
;
92 myProjectsNavigator
= projectsNavigator
;
96 myTreeBuilder
= new SimpleTreeBuilder(tree
, (DefaultTreeModel
)tree
.getModel(), this, null);
97 Disposer
.register(myProject
, myTreeBuilder
);
99 myTreeBuilder
.initRoot();
100 myTreeBuilder
.expand(myRoot
, null);
103 private void configureTree(final SimpleTree tree
) {
104 tree
.setRootVisible(false);
105 tree
.setShowsRootHandles(true);
107 MavenUIUtil
.installCheckboxRenderer(tree
, new MavenUIUtil
.CheckboxHandler() {
108 public void toggle(TreePath treePath
, InputEvent e
) {
109 SimpleNode node
= tree
.getNodeFor(treePath
);
111 node
.handleDoubleClickOrEnter(tree
, e
);
115 public boolean isVisible(Object userObject
) {
116 return userObject
instanceof ProfileNode
;
119 public MavenUIUtil
.CheckBoxState
getState(Object userObject
) {
120 MavenProfileState state
= ((ProfileNode
)userObject
).getState();
122 case NONE
: return MavenUIUtil
.CheckBoxState
.UNCHECKED
;
123 case EXPLICIT
: return MavenUIUtil
.CheckBoxState
.CHECKED
;
124 case IMPLICIT
: return MavenUIUtil
.CheckBoxState
.PARTIAL
;
126 MavenLog
.LOG
.error("unknown profile state: " + state
);
127 return MavenUIUtil
.CheckBoxState
.UNCHECKED
;
132 public RootNode
getRootElement() {
136 public void update() {
137 List
<MavenProject
> projects
= myProjectsManager
.getProjects();
138 List
<MavenProject
> deleted
= new ArrayList
<MavenProject
>(myProjectToNodeMapping
.keySet());
139 deleted
.removeAll(projects
);
140 updateProjects(projects
, deleted
);
143 private void updateFrom(SimpleNode node
) {
144 myTreeBuilder
.addSubtreeToUpdateByElement(node
);
147 private void updateUpTo(SimpleNode node
) {
148 SimpleNode each
= node
;
149 while (each
!= null) {
151 each
= each
.getParent();
155 public void updateProjects(List
<MavenProject
> updated
, List
<MavenProject
> deleted
) {
156 for (MavenProject each
: updated
) {
157 ProjectNode node
= findNodeFor(each
);
159 node
= new ProjectNode(each
);
160 myProjectToNodeMapping
.put(each
, node
);
162 doUpdateProject(node
);
165 for (MavenProject each
: deleted
) {
166 ProjectNode node
= myProjectToNodeMapping
.remove(each
);
168 ProjectsGroupNode parent
= node
.getGroup();
173 myRoot
.updateProfiles();
176 private void doUpdateProject(ProjectNode node
) {
177 MavenProject project
= node
.getMavenProject();
179 ProjectsGroupNode newParentNode
= myRoot
;
181 if (myProjectsNavigator
.getGroupModules()) {
182 MavenProject aggregator
= myProjectsManager
.findAggregator(project
);
183 if (aggregator
!= null) {
184 ProjectNode aggregatorNode
= findNodeFor(aggregator
);
185 if (aggregatorNode
!= null && aggregatorNode
.isVisible()) {
186 newParentNode
= aggregatorNode
.getModulesNode();
191 node
.updateProject();
192 reconnectNode(node
, newParentNode
);
194 ProjectsGroupNode newModulesParentNode
= myProjectsNavigator
.getGroupModules() && node
.isVisible() ? node
.getModulesNode() : myRoot
;
195 for (MavenProject each
: myProjectsManager
.getModules(project
)) {
196 ProjectNode moduleNode
= findNodeFor(each
);
197 if (moduleNode
!= null && !moduleNode
.getParent().equals(newModulesParentNode
)) {
198 reconnectNode(moduleNode
, newModulesParentNode
);
203 private void reconnectNode(ProjectNode node
, ProjectsGroupNode newParentNode
) {
204 ProjectsGroupNode oldParentNode
= node
.getGroup();
205 if (oldParentNode
== null || !oldParentNode
.equals(newParentNode
)) {
206 if (oldParentNode
!= null) {
207 oldParentNode
.remove(node
);
209 newParentNode
.add(node
);
212 newParentNode
.sortProjects();
216 public void updateProfiles() {
217 myRoot
.updateProfiles();
220 public void updateIgnored(List
<MavenProject
> projects
) {
221 for (MavenProject each
: projects
) {
222 ProjectNode node
= findNodeFor(each
);
223 if (node
== null) continue;
224 node
.updateIgnored();
228 public void accept(SimpleNodeVisitor visitor
) {
229 ((SimpleTree
)myTreeBuilder
.getTree()).accept(myTreeBuilder
, visitor
);
232 public void updateGoals() {
233 for (ProjectNode each
: myProjectToNodeMapping
.values()) {
238 public void select(MavenProject project
) {
239 ProjectNode node
= findNodeFor(project
);
240 if (node
!= null) select(node
);
243 public void select(SimpleNode node
) {
244 myTreeBuilder
.select(node
, null);
247 private ProjectNode
findNodeFor(MavenProject project
) {
248 return myProjectToNodeMapping
.get(project
);
252 ALWAYS
, NEVER
, NORMAL
255 protected Class
<?
extends MavenSimpleNode
>[] getVisibleNodesClasses() {
259 protected boolean showDescriptions() {
263 protected boolean showOnlyBasicPhases() {
264 return myProjectsNavigator
.getShowBasicPhasesOnly();
267 public static <T
extends MavenSimpleNode
> List
<T
> getSelectedNodes(SimpleTree tree
, Class
<T
> nodeClass
) {
268 final List
<T
> filtered
= new ArrayList
<T
>();
269 for (SimpleNode node
: getSelectedNodes(tree
)) {
270 if ((nodeClass
!= null) && (!nodeClass
.isInstance(node
))) {
274 //noinspection unchecked
275 filtered
.add((T
)node
);
280 private static List
<SimpleNode
> getSelectedNodes(SimpleTree tree
) {
281 List
<SimpleNode
> nodes
= new ArrayList
<SimpleNode
>();
282 TreePath
[] treePaths
= tree
.getSelectionPaths();
283 if (treePaths
!= null) {
284 for (TreePath treePath
: treePaths
) {
285 nodes
.add(tree
.getNodeFor(treePath
));
292 public static ProjectNode
getCommonProjectNode(Collection
<?
extends MavenSimpleNode
> nodes
) {
293 ProjectNode parent
= null;
294 for (MavenSimpleNode node
: nodes
) {
295 ProjectNode nextParent
= node
.findParent(ProjectNode
.class);
296 if (parent
== null) {
299 else if (parent
!= nextParent
) {
306 public enum ErrorLevel
{
310 public abstract class MavenSimpleNode
extends CachingSimpleNode
{
311 private MavenSimpleNode myParent
;
312 private ErrorLevel myErrorLevel
= ErrorLevel
.NONE
;
313 private ErrorLevel myTotalErrorLevel
= null;
315 public MavenSimpleNode(MavenSimpleNode parent
) {
316 super(MavenProjectsStructure
.this.myProject
, null);
320 public void setParent(MavenSimpleNode parent
) {
325 public NodeDescriptor
getParentDescriptor() {
329 public <T
extends MavenSimpleNode
> T
findParent(Class
<T
> parentClass
) {
330 MavenSimpleNode node
= this;
332 node
= node
.myParent
;
333 if (node
== null || parentClass
.isInstance(node
)) {
334 //noinspection unchecked
340 public boolean isVisible() {
341 return getDisplayKind() != DisplayKind
.NEVER
;
344 public DisplayKind
getDisplayKind() {
345 Class
[] visibles
= getVisibleNodesClasses();
346 if (visibles
== null) return DisplayKind
.NORMAL
;
348 for (Class each
: visibles
) {
349 if (each
.isInstance(this)) return DisplayKind
.ALWAYS
;
351 return DisplayKind
.NEVER
;
356 protected SimpleNode
[] buildChildren() {
357 List
<?
extends MavenSimpleNode
> children
= doGetChildren();
358 if (children
.isEmpty()) return NO_CHILDREN
;
360 List
<MavenSimpleNode
> result
= new ArrayList
<MavenSimpleNode
>();
361 for (MavenSimpleNode each
: children
) {
362 if (each
.isVisible()) result
.add(each
);
364 return result
.toArray(new MavenSimpleNode
[result
.size()]);
367 protected List
<?
extends MavenSimpleNode
> doGetChildren() {
368 return Collections
.emptyList();
372 public void cleanUpCache() {
373 super.cleanUpCache();
374 myTotalErrorLevel
= null;
377 protected void childrenChanged() {
378 MavenSimpleNode each
= this;
379 while (each
!= null) {
381 each
= (MavenSimpleNode
)each
.getParent();
386 public ErrorLevel
getTotalErrorLevel() {
387 if (myTotalErrorLevel
== null) {
388 myTotalErrorLevel
= calcTotalErrorLevel();
390 return myTotalErrorLevel
;
393 private ErrorLevel
calcTotalErrorLevel() {
394 ErrorLevel childrenErrorLevel
= getChildrenErrorLevel();
395 return childrenErrorLevel
.compareTo(myErrorLevel
) > 0 ? childrenErrorLevel
: myErrorLevel
;
398 public ErrorLevel
getChildrenErrorLevel() {
399 ErrorLevel result
= ErrorLevel
.NONE
;
400 for (SimpleNode each
: getChildren()) {
401 ErrorLevel eachLevel
= ((MavenSimpleNode
)each
).getTotalErrorLevel();
402 if (eachLevel
.compareTo(result
) > 0) result
= eachLevel
;
407 public void setErrorLevel(ErrorLevel level
) {
408 if (myErrorLevel
== level
) return;
409 myErrorLevel
= level
;
414 protected void doUpdate() {
415 setNameAndTooltip(getName(), null);
418 protected void setNameAndTooltip(String name
, @Nullable String tooltip
) {
419 setNameAndTooltip(name
, tooltip
, (String
)null);
422 protected void setNameAndTooltip(String name
, @Nullable String tooltip
, @Nullable String hint
) {
423 setNameAndTooltip(name
, tooltip
, getPlainAttributes());
424 if (showDescriptions() && !StringUtil
.isEmptyOrSpaces(hint
)) {
425 addColoredFragment(" (" + hint
+ ")", SimpleTextAttributes
.GRAY_ATTRIBUTES
);
429 protected void setNameAndTooltip(String name
, @Nullable String tooltip
, SimpleTextAttributes attribs
) {
431 addColoredFragment(name
, prepareAttribs(attribs
));
432 getTemplatePresentation().setTooltip(tooltip
);
435 private SimpleTextAttributes
prepareAttribs(SimpleTextAttributes from
) {
436 ErrorLevel level
= getTotalErrorLevel();
437 Color waveColor
= level
== ErrorLevel
.NONE ?
null : Color
.RED
;
438 int style
= from
.getStyle();
439 if (waveColor
!= null) style
|= SimpleTextAttributes
.STYLE_WAVED
;
440 return new SimpleTextAttributes(from
.getBgColor(), from
.getFgColor(), waveColor
, style
);
445 String
getActionId() {
456 public VirtualFile
getVirtualFile() {
461 public Navigatable
getNavigatable() {
462 VirtualFile file
= getVirtualFile();
463 if (file
== null || !file
.isValid()) return null;
464 return PsiManager
.getInstance(getProject()).findFile(file
);
467 public void handleDoubleClickOrEnter(SimpleTree tree
, InputEvent inputEvent
) {
468 String actionId
= getActionId();
469 if (actionId
!= null) {
470 MavenUIUtil
.executeAction(actionId
, inputEvent
);
475 public abstract class GroupNode
extends MavenSimpleNode
{
476 public GroupNode(MavenSimpleNode parent
) {
481 public boolean isVisible() {
482 if (getDisplayKind() == DisplayKind
.ALWAYS
) return true;
484 for (SimpleNode each
: getChildren()) {
485 if (((MavenSimpleNode
)each
).isVisible()) return true;
490 protected <T
extends MavenSimpleNode
> void insertSorted(List
<T
> list
, T newObject
) {
491 int pos
= Collections
.binarySearch(list
, newObject
, NODE_COMPARATOR
);
492 list
.add(pos
>= 0 ? pos
: -pos
- 1, newObject
);
495 protected void sort(List
<?
extends MavenSimpleNode
> list
) {
496 Collections
.sort(list
, NODE_COMPARATOR
);
500 public abstract class ProjectsGroupNode
extends GroupNode
{
501 private final List
<ProjectNode
> myProjectNodes
= new ArrayList
<ProjectNode
>();
503 public ProjectsGroupNode(MavenSimpleNode parent
) {
505 setIcons(MavenIcons
.CLOSED_MODULES_ICON
, MavenIcons
.OPEN_MODULES_ICON
);
509 protected List
<?
extends MavenSimpleNode
> doGetChildren() {
510 return myProjectNodes
;
514 public List
<ProjectNode
> getProjectNodesInTests() {
515 return myProjectNodes
;
518 protected void add(ProjectNode projectNode
) {
519 projectNode
.setParent(this);
520 insertSorted(myProjectNodes
, projectNode
);
525 public void remove(ProjectNode projectNode
) {
526 projectNode
.setParent(null);
527 myProjectNodes
.remove(projectNode
);
532 public void sortProjects() {
533 sort(myProjectNodes
);
538 public class RootNode
extends ProjectsGroupNode
{
539 private ProfilesNode myProfilesNode
;
543 myProfilesNode
= new ProfilesNode(this);
547 public boolean isVisible() {
552 protected List
<?
extends MavenSimpleNode
> doGetChildren() {
553 return ContainerUtil
.concat(Collections
.singletonList(myProfilesNode
), super.doGetChildren());
556 public void updateProfiles() {
557 myProfilesNode
.updateProfiles();
561 public class ProfilesNode
extends GroupNode
{
562 private List
<ProfileNode
> myProfileNodes
= new ArrayList
<ProfileNode
>();
564 public ProfilesNode(MavenSimpleNode parent
) {
566 setIcons(MavenIcons
.CLOSED_PROFILES_ICON
, MavenIcons
.OPEN_PROFILES_ICON
);
569 protected List
<?
extends MavenSimpleNode
> doGetChildren() {
570 return myProfileNodes
;
574 public String
getName() {
575 return message("view.node.profiles");
578 public void updateProfiles() {
579 Collection
<Pair
<String
,MavenProfileState
>> profiles
= myProjectsManager
.getProfilesWithStates();
581 List
<ProfileNode
> newNodes
= new ArrayList
<ProfileNode
>(profiles
.size());
582 for (Pair
<String
, MavenProfileState
> each
: profiles
) {
583 ProfileNode node
= findOrCreateNodeFor(each
.first
);
584 node
.setState(each
.second
);
588 myProfileNodes
= newNodes
;
589 sort(myProfileNodes
);
593 private ProfileNode
findOrCreateNodeFor(String profileName
) {
594 for (ProfileNode each
: myProfileNodes
) {
595 if (each
.getProfileName().equals(profileName
)) return each
;
597 return new ProfileNode(this, profileName
);
601 public class ProfileNode
extends MavenSimpleNode
{
602 private final String myProfileName
;
603 private MavenProfileState myState
;
605 public ProfileNode(ProfilesNode parent
, String profileName
) {
607 myProfileName
= profileName
;
611 public String
getName() {
612 return myProfileName
;
615 public String
getProfileName() {
616 return myProfileName
;
619 public MavenProfileState
getState() {
623 private void setState(MavenProfileState state
) {
629 protected String
getActionId() {
630 return "Maven.ToggleProfile";
634 public class ProjectNode
extends GroupNode
{
635 private final MavenProject myMavenProject
;
636 private final LifecycleNode myLifecycleNode
;
637 private final PluginsNode myPluginsNode
;
638 private final DependenciesNode myDependenciesNode
;
639 private final ModulesNode myModulesNode
;
641 private String myTooltipCache
;
643 public ProjectNode(MavenProject mavenProject
) {
645 myMavenProject
= mavenProject
;
647 myLifecycleNode
= new LifecycleNode(this);
648 myPluginsNode
= new PluginsNode(this);
649 myDependenciesNode
= new DependenciesNode(this);
650 myModulesNode
= new ModulesNode(this);
652 setUniformIcon(MavenIcons
.MAVEN_PROJECT_ICON
);
656 public MavenProject
getMavenProject() {
657 return myMavenProject
;
660 public ProjectsGroupNode
getGroup() {
661 return (ProjectsGroupNode
)super.getParent();
665 public boolean isVisible() {
666 if (!myProjectsNavigator
.getShowIgnored() && myProjectsManager
.isIgnored(myMavenProject
)) return false;
667 return super.isVisible();
671 protected List
<?
extends MavenSimpleNode
> doGetChildren() {
672 return Arrays
.asList(myLifecycleNode
, myPluginsNode
, myDependenciesNode
, myModulesNode
);
676 public ModulesNode
getModulesNode() {
677 return myModulesNode
;
680 private void updateProject() {
681 setErrorLevel(myMavenProject
.getProblems().isEmpty() ? ErrorLevel
.NONE
: ErrorLevel
.ERROR
);
682 myLifecycleNode
.updateGoalsList();
683 myPluginsNode
.updatePlugins(myMavenProject
);
684 myDependenciesNode
.updateDependencies(myMavenProject
);
686 myTooltipCache
= makeDescription();
688 updateFrom(getParent());
691 public void updateIgnored() {
692 getGroup().childrenChanged();
695 public void updateGoals() {
696 updateFrom(myLifecycleNode
);
697 updateFrom(myPluginsNode
);
701 public String
getName() {
702 return myMavenProject
.getDisplayName();
706 protected void doUpdate() {
707 setNameAndTooltip(getName(), myTooltipCache
);
711 protected SimpleTextAttributes
getPlainAttributes() {
712 if (myProjectsManager
.isIgnored(myMavenProject
)) {
713 return new SimpleTextAttributes(SimpleTextAttributes
.STYLE_PLAIN
, Color
.GRAY
);
715 return super.getPlainAttributes();
718 private String
makeDescription() {
719 StringBuilder desc
= new StringBuilder();
720 desc
.append("<html>");
721 desc
.append("<table>");
724 desc
.append(" <table>");
725 desc
.append(" <tr>");
726 desc
.append(" <td>Project:</td>");
727 desc
.append(" <td nowrap>" + myMavenProject
.getMavenId() + "</td>");
728 desc
.append(" </tr>");
729 desc
.append(" <tr>");
730 desc
.append(" <td>Location:</td>");
731 desc
.append(" <td nowrap>" + myMavenProject
.getPath() + "</td>");
732 desc
.append(" </tr>");
733 desc
.append(" </table>");
734 desc
.append("</td>");
735 desc
.append("</tr>");
736 appendProblems(desc
);
738 desc
.append("</table>");
739 desc
.append("</html>");
740 return desc
.toString();
743 private void appendProblems(StringBuilder desc
) {
744 List
<MavenProjectProblem
> problems
= myMavenProject
.getProblems();
745 if (problems
.isEmpty()) return;
749 desc
.append("<table>");
750 boolean first
= true;
751 for (MavenProjectProblem each
: problems
) {
754 desc
.append("<td valign=top>" + MavenUtil
.formatHtmlImage(ERROR_ICON_URL
) + "</td>");
755 desc
.append("<td valign=top>Problems:</td>");
759 desc
.append("<td colspan=2></td>");
761 desc
.append("<td valign=top>" + wrappedText(each
));
762 desc
.append("</tr>");
764 desc
.append("</table>");
765 desc
.append("</td>");
766 desc
.append("</tr>");
769 private String
wrappedText(MavenProjectProblem each
) {
770 String text
= StringUtil
.replace(each
.getDescription(), new String
[]{"<", ">"}, new String
[]{"<", ">"});
771 StringBuffer result
= new StringBuffer();
773 for (int i
= 0; i
< text
.length(); i
++) {
774 char ch
= text
.charAt(i
);
780 result
.append("<br>");
784 return result
.toString();
788 public VirtualFile
getVirtualFile() {
789 return myMavenProject
.getFile();
794 protected String
getMenuId() {
795 return "Maven.NavigatorProjectMenu";
799 public class ModulesNode
extends ProjectsGroupNode
{
800 public ModulesNode(ProjectNode parent
) {
802 setIcons(MavenIcons
.CLOSED_MODULES_ICON
, MavenIcons
.OPEN_MODULES_ICON
);
806 public String
getName() {
807 return message("view.node.modules");
811 public abstract class GoalsGroupNode
extends GroupNode
{
812 protected final List
<GoalNode
> myGoalNodes
= new ArrayList
<GoalNode
>();
814 public GoalsGroupNode(MavenSimpleNode parent
) {
818 protected List
<?
extends MavenSimpleNode
> doGetChildren() {
823 public abstract class GoalNode
extends MavenSimpleNode
{
824 private final MavenProject myMavenProject
;
825 private final String myGoal
;
826 private final String myDisplayName
;
828 public GoalNode(GoalsGroupNode parent
, String goal
, String displayName
) {
830 myMavenProject
= findParent(ProjectNode
.class).getMavenProject();
832 myDisplayName
= displayName
;
833 setUniformIcon(MavenIcons
.PHASE_ICON
);
836 public String
getProjectPath() {
837 return myMavenProject
.getPath();
840 public String
getGoal() {
845 public String
getName() {
846 return myDisplayName
;
850 protected void doUpdate() {
851 String hint
= StringUtil
.join(Arrays
.asList(myShortcutsManager
.getDescription(myMavenProject
, myGoal
),
852 myTasksManager
.getDescription(myMavenProject
, myGoal
)), ", ");
853 setNameAndTooltip(getName(), null, hint
);
857 protected SimpleTextAttributes
getPlainAttributes() {
858 if (myGoal
.equals(myMavenProject
.getDefaultGoal())) {
859 return new SimpleTextAttributes(SimpleTextAttributes
.STYLE_BOLD
, getColor());
861 return super.getPlainAttributes();
866 protected String
getActionId() {
867 return "Maven.RunBuild";
872 protected String
getMenuId() {
873 return "Maven.BuildMenu";
877 public class LifecycleNode
extends GoalsGroupNode
{
878 public LifecycleNode(ProjectNode parent
) {
881 for (String goal
: PHASES
) {
882 myGoalNodes
.add(new StandardGoalNode(this, goal
));
884 setIcons(MavenIcons
.CLOSED_PHASES_ICON
, MavenIcons
.OPEN_PHASES_ICON
);
888 public String
getName() {
889 return message("view.node.lifecycle");
892 public void updateGoalsList() {
897 public class StandardGoalNode
extends GoalNode
{
898 public StandardGoalNode(GoalsGroupNode parent
, String goal
) {
899 super(parent
, goal
, goal
);
903 public boolean isVisible() {
904 if (showOnlyBasicPhases() && !BASIC_PHASES
.contains(getGoal())) return false;
905 return super.isVisible();
909 public class PluginsNode
extends GroupNode
{
910 private final List
<PluginNode
> myPluginNodes
= new ArrayList
<PluginNode
>();
912 public PluginsNode(ProjectNode parent
) {
914 setIcons(MavenIcons
.CLOSED_PLUGINS_ICON
, MavenIcons
.OPEN_PLUGINS_ICON
);
918 public String
getName() {
919 return message("view.node.plugins");
922 protected List
<?
extends MavenSimpleNode
> doGetChildren() {
923 return myPluginNodes
;
926 public void updatePlugins(MavenProject mavenProject
) {
927 List
<MavenPlugin
> plugins
= mavenProject
.getDeclaredPlugins();
929 for (PluginNode each
: new ArrayList
<PluginNode
>(myPluginNodes
)) {
930 if (plugins
.contains(each
.getPlugin())) {
934 myPluginNodes
.remove(each
);
937 for (MavenPlugin each
: plugins
) {
938 if (!hasNodeFor(each
)) {
939 myPluginNodes
.add(new PluginNode(this, each
));
946 private boolean hasNodeFor(MavenPlugin plugin
) {
947 for (PluginNode each
: myPluginNodes
) {
948 if (each
.getPlugin().getMavenId().equals(plugin
.getMavenId())) {
956 public class PluginNode
extends GoalsGroupNode
{
957 private final MavenPlugin myPlugin
;
958 private MavenPluginInfo myPluginInfo
;
960 public PluginNode(PluginsNode parent
, MavenPlugin plugin
) {
964 setUniformIcon(MavenIcons
.PLUGIN_ICON
);
968 public MavenPlugin
getPlugin() {
973 public String
getName() {
974 return myPluginInfo
== null ? myPlugin
.getDisplayString() : myPluginInfo
.getGoalPrefix();
978 protected void doUpdate() {
979 setNameAndTooltip(getName(), null, myPluginInfo
!= null ? myPlugin
.getDisplayString() : null);
982 public void updatePlugin() {
983 boolean hadPluginInfo
= myPluginInfo
!= null;
985 myPluginInfo
= MavenArtifactUtil
.readPluginInfo(myProjectsManager
.getLocalRepository(), myPlugin
.getMavenId());
987 boolean hasPluginInfo
= myPluginInfo
!= null;
989 setErrorLevel(myPluginInfo
== null ? ErrorLevel
.ERROR
: ErrorLevel
.NONE
);
991 if (hadPluginInfo
== hasPluginInfo
) return;
994 if (myPluginInfo
!= null) {
995 for (MavenPluginInfo
.Mojo mojo
: myPluginInfo
.getMojos()) {
996 myGoalNodes
.add(new PluginGoalNode(this, mojo
.getQualifiedGoal(), mojo
.getDisplayName()));
1005 public boolean isVisible() {
1006 // show regardless absence of children
1007 return super.isVisible() || getDisplayKind() != DisplayKind
.NEVER
;
1011 public class PluginGoalNode
extends GoalNode
{
1012 public PluginGoalNode(PluginNode parent
, String goal
, String displayName
) {
1013 super(parent
, goal
, displayName
);
1014 setUniformIcon(MavenIcons
.PLUGIN_GOAL_ICON
);
1018 public abstract class BaseDependenciesNode
extends GroupNode
{
1019 private List
<DependencyNode
> myChildren
= new ArrayList
<DependencyNode
>();
1021 protected BaseDependenciesNode(MavenSimpleNode parent
) {
1026 protected List
<?
extends MavenSimpleNode
> doGetChildren() {
1030 protected void updateChildren(List
<MavenArtifactNode
> children
, MavenProject mavenProject
) {
1031 List
<DependencyNode
> newNodes
= new ArrayList
<DependencyNode
>(children
.size());
1032 for (MavenArtifactNode each
: children
) {
1033 DependencyNode newNode
= findOrCreateNodeFor(each
, mavenProject
);
1034 newNodes
.add(newNode
);
1035 newNode
.updateChildren(each
.getDependencies(), mavenProject
);
1036 newNode
.updateDependency();
1038 myChildren
= newNodes
;
1042 private DependencyNode
findOrCreateNodeFor(MavenArtifactNode artifact
, MavenProject mavenProject
) {
1043 for (DependencyNode each
: myChildren
) {
1044 if (each
.myArtifact
.equals(artifact
.getArtifact())) return each
;
1046 return new DependencyNode(this, artifact
, mavenProject
);
1050 public class DependenciesNode
extends BaseDependenciesNode
{
1051 public DependenciesNode(ProjectNode parent
) {
1053 setIcons(MavenIcons
.CLOSED_DEPENDENCIES_ICON
, MavenIcons
.OPEN_DEPENDENCIES_ICON
);
1057 public String
getName() {
1058 return message("view.node.dependencies");
1061 public void updateDependencies(MavenProject mavenProject
) {
1062 updateChildren(mavenProject
.getDependenciesNodes(), mavenProject
);
1066 public class DependencyNode
extends BaseDependenciesNode
{
1067 private final MavenArtifact myArtifact
;
1068 private final MavenProject myMavenProject
;
1070 public DependencyNode(MavenSimpleNode parent
, MavenArtifactNode artifactNode
, MavenProject mavenProject
) {
1072 myMavenProject
= mavenProject
;
1073 myArtifact
= artifactNode
.getArtifact();
1074 setUniformIcon(MavenIcons
.DEPENDENCY_ICON
);
1078 public String
getName() {
1079 return myArtifact
.getDisplayStringForLibraryName();
1083 protected void doUpdate() {
1084 String scope
= myArtifact
.getScope();
1085 setNameAndTooltip(getName(), null, MavenConstants
.SCOPE_COMPILE
.equals(scope
) ?
null : scope
);
1088 private void updateDependency() {
1089 setErrorLevel(myArtifact
.isResolved() ? ErrorLevel
.NONE
: ErrorLevel
.ERROR
);
1093 public Navigatable
getNavigatable() {
1094 final Module m
= myProjectsManager
.findModule(myMavenProject
);
1095 if (m
== null) return null;
1096 final OrderEntry e
= MavenRootModelAdapter
.findLibraryEntry(m
, myArtifact
);
1097 if (e
== null) return null;
1098 return new Navigatable() {
1099 public void navigate(boolean requestFocus
) {
1100 ProjectSettingsService
.getInstance(myProject
).openProjectLibrarySettings(new NamedLibraryElement(m
, e
));
1103 public boolean canNavigate() {
1107 public boolean canNavigateToSource() {
1114 public boolean isVisible() {
1115 // show regardless absence of children
1116 return getDisplayKind() != DisplayKind
.NEVER
;