mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
project structure: renderer for project structure elements refactored
This commit is contained in:
@@ -98,10 +98,6 @@ public class ProjectConfigurable extends ProjectStructureElementConfigurable<Pro
|
||||
}
|
||||
});
|
||||
daemonAnalyzer.addListener(new ProjectStructureDaemonAnalyzerListener() {
|
||||
@Override
|
||||
public void usagesCollected(@NotNull ProjectStructureElement containingElement) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void problemsChanged(@NotNull ProjectStructureElement element) {
|
||||
if (element instanceof GeneralProjectSettingsElement) {
|
||||
|
||||
-3
@@ -64,9 +64,6 @@ public class ArtifactsStructureConfigurableContextImpl implements ArtifactsStruc
|
||||
myContext = context;
|
||||
myProject = project;
|
||||
context.getDaemonAnalyzer().addListener(new ProjectStructureDaemonAnalyzerListener() {
|
||||
public void usagesCollected(@NotNull ProjectStructureElement containingElement) {
|
||||
}
|
||||
|
||||
public void problemsChanged(@NotNull ProjectStructureElement element) {
|
||||
if (element instanceof ArtifactProjectStructureElement) {
|
||||
final Artifact originalArtifact = ((ArtifactProjectStructureElement)element).getOriginalArtifact();
|
||||
|
||||
+2
-65
@@ -25,7 +25,6 @@ import com.intellij.openapi.keymap.KeymapManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.options.SearchableConfigurable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectBundle;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.roots.libraries.LibraryTable;
|
||||
@@ -38,8 +37,6 @@ import com.intellij.openapi.util.ActionCallback;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.packaging.artifacts.Artifact;
|
||||
import com.intellij.ui.ColoredTreeCellRenderer;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.ui.TreeSpeedSearch;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.navigation.Place;
|
||||
@@ -47,7 +44,6 @@ import com.intellij.util.Function;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -82,15 +78,7 @@ public abstract class BaseStructureConfigurable extends MasterDetailsComponent i
|
||||
public void init(StructureConfigurableContext context) {
|
||||
myContext = context;
|
||||
myContext.getDaemonAnalyzer().addListener(new ProjectStructureDaemonAnalyzerListener() {
|
||||
public void usagesCollected(@NotNull ProjectStructureElement containingElement) {
|
||||
updateTree();
|
||||
}
|
||||
|
||||
public void problemsChanged(@NotNull ProjectStructureElement element) {
|
||||
updateTree();
|
||||
}
|
||||
|
||||
private void updateTree() {
|
||||
if (!myTree.isShowing()) return;
|
||||
|
||||
myTree.revalidate();
|
||||
@@ -162,57 +150,7 @@ public abstract class BaseStructureConfigurable extends MasterDetailsComponent i
|
||||
}
|
||||
}, true);
|
||||
ToolTipManager.sharedInstance().registerComponent(myTree);
|
||||
myTree.setCellRenderer(new ColoredTreeCellRenderer(){
|
||||
public void customizeCellRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
|
||||
if (value instanceof MyNode) {
|
||||
final MyNode node = (MyNode)value;
|
||||
|
||||
final NamedConfigurable namedConfigurable = node.getConfigurable();
|
||||
if (namedConfigurable == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String displayName = node.getDisplayName();
|
||||
final Icon icon = namedConfigurable.getIcon(expanded);
|
||||
setIcon(icon);
|
||||
setToolTipText(null);
|
||||
setFont(UIUtil.getTreeFont());
|
||||
|
||||
SimpleTextAttributes textAttributes =
|
||||
selected && hasFocus ? SimpleTextAttributes.SELECTED_SIMPLE_CELL_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES;
|
||||
if (node.isDisplayInBold()) {
|
||||
textAttributes = SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES;
|
||||
} else if (namedConfigurable instanceof ProjectStructureElementConfigurable) {
|
||||
final ProjectStructureElement projectStructureElement =
|
||||
((ProjectStructureElementConfigurable)namedConfigurable).getProjectStructureElement();
|
||||
if (projectStructureElement != null) {
|
||||
final ProjectStructureDaemonAnalyzer daemonAnalyzer = myContext.getDaemonAnalyzer();
|
||||
final boolean unused = daemonAnalyzer.isUnused(projectStructureElement);
|
||||
final ProjectStructureProblemsHolderImpl problemsHolder = daemonAnalyzer.getProblemsHolder(projectStructureElement);
|
||||
if (problemsHolder == null) {
|
||||
daemonAnalyzer.queueUpdate(projectStructureElement, true, false);
|
||||
}
|
||||
final ProjectStructureProblemType.Severity level = problemsHolder != null ? problemsHolder.getSeverity() : null;
|
||||
final boolean invalid = level != null;
|
||||
if (unused || invalid) {
|
||||
Color fg = unused
|
||||
? UIUtil.getInactiveTextColor()
|
||||
: selected && hasFocus ? UIUtil.getTreeSelectionForeground() : UIUtil.getTreeForeground();
|
||||
textAttributes = new SimpleTextAttributes(invalid ? SimpleTextAttributes.STYLE_WAVED : SimpleTextAttributes.STYLE_PLAIN, fg,
|
||||
level == ProjectStructureProblemType.Severity.ERROR ? Color.RED : Color.GRAY);
|
||||
String text = problemsHolder != null ? problemsHolder.composeTooltipMessage() : "";
|
||||
if (unused) {
|
||||
text += ProjectBundle.message("project.roots.tooltip.unused", displayName);
|
||||
}
|
||||
setToolTipText(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
append(displayName, textAttributes);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
myTree.setCellRenderer(new ProjectStructureElementRenderer(myContext));
|
||||
}
|
||||
|
||||
public void disposeUIResources() {
|
||||
@@ -312,7 +250,7 @@ public abstract class BaseStructureConfigurable extends MasterDetailsComponent i
|
||||
loadTree();
|
||||
}
|
||||
for (ProjectStructureElement element : getProjectStructureElements()) {
|
||||
myContext.getDaemonAnalyzer().queueUpdate(element, false, true);
|
||||
myContext.getDaemonAnalyzer().queueUpdate(element);
|
||||
}
|
||||
|
||||
super.reset();
|
||||
@@ -502,5 +440,4 @@ public abstract class BaseStructureConfigurable extends MasterDetailsComponent i
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* 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.intellij.openapi.roots.ui.configuration.projectRoot;
|
||||
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureDaemonAnalyzer;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemType;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemsHolderImpl;
|
||||
import com.intellij.openapi.ui.MasterDetailsComponent;
|
||||
import com.intellij.openapi.ui.NamedConfigurable;
|
||||
import com.intellij.ui.ColoredTreeCellRenderer;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class ProjectStructureElementRenderer extends ColoredTreeCellRenderer {
|
||||
private StructureConfigurableContext myContext;
|
||||
|
||||
public ProjectStructureElementRenderer(StructureConfigurableContext context) {
|
||||
myContext = context;
|
||||
}
|
||||
|
||||
public void customizeCellRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
|
||||
if (value instanceof MasterDetailsComponent.MyNode) {
|
||||
final MasterDetailsComponent.MyNode node = (MasterDetailsComponent.MyNode)value;
|
||||
|
||||
final NamedConfigurable namedConfigurable = node.getConfigurable();
|
||||
if (namedConfigurable == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String displayName = node.getDisplayName();
|
||||
final Icon icon = namedConfigurable.getIcon(expanded);
|
||||
setIcon(icon);
|
||||
setToolTipText(null);
|
||||
setFont(UIUtil.getTreeFont());
|
||||
|
||||
SimpleTextAttributes textAttributes =
|
||||
selected && hasFocus ? SimpleTextAttributes.SELECTED_SIMPLE_CELL_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES;
|
||||
if (node.isDisplayInBold()) {
|
||||
textAttributes = SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES;
|
||||
}
|
||||
else if (namedConfigurable instanceof ProjectStructureElementConfigurable) {
|
||||
final ProjectStructureElement projectStructureElement =
|
||||
((ProjectStructureElementConfigurable)namedConfigurable).getProjectStructureElement();
|
||||
if (projectStructureElement != null) {
|
||||
final ProjectStructureDaemonAnalyzer daemonAnalyzer = myContext.getDaemonAnalyzer();
|
||||
final ProjectStructureProblemsHolderImpl problemsHolder = daemonAnalyzer.getProblemsHolder(projectStructureElement);
|
||||
if (problemsHolder != null && problemsHolder.containsProblems()) {
|
||||
final boolean isUnused = problemsHolder.containsProblems(ProjectStructureProblemType.Severity.UNUSED);
|
||||
final boolean haveWarnings = problemsHolder.containsProblems(ProjectStructureProblemType.Severity.WARNING);
|
||||
final boolean haveErrors = problemsHolder.containsProblems(ProjectStructureProblemType.Severity.ERROR);
|
||||
Color foreground = isUnused ? UIUtil.getInactiveTextColor() : null;
|
||||
final int style = haveWarnings || haveErrors ? SimpleTextAttributes.STYLE_WAVED : -1;
|
||||
final Color waveColor = haveErrors ? Color.RED : haveWarnings ? Color.GRAY : null;
|
||||
textAttributes = textAttributes.derive(style, foreground, null, waveColor);
|
||||
setToolTipText(problemsHolder.composeTooltipMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
append(displayName, textAttributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -111,7 +111,7 @@ public class LibraryProjectStructureElement extends ProjectStructureElement {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof LibraryProjectStructureElement)) return false;
|
||||
|
||||
return getSourceOrThis().equals(((LibraryProjectStructureElement)o).getSourceOrThis());
|
||||
return getSourceOrThis() == (((LibraryProjectStructureElement)o).getSourceOrThis());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -125,7 +125,7 @@ public class LibraryProjectStructureElement extends ProjectStructureElement {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getSourceOrThis().hashCode();
|
||||
return System.identityHashCode(getSourceOrThis());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -138,7 +138,7 @@ public class LibraryProjectStructureElement extends ProjectStructureElement {
|
||||
public ProjectStructureProblemDescription createUnusedElementWarning() {
|
||||
final List<ConfigurationErrorQuickFix> fixes = Arrays.asList(new AddLibraryToDependenciesFix(), new RemoveLibraryFix());
|
||||
return new ProjectStructureProblemDescription(getPresentableName() + " is not used", null, createPlace(), fixes,
|
||||
ProjectStructureProblemType.warning("unused-library"));
|
||||
ProjectStructureProblemType.unused("unused-library"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
-4
@@ -39,10 +39,6 @@ public class ProjectConfigurationProblems {
|
||||
myAnalyzer = analyzer;
|
||||
myContext = context;
|
||||
analyzer.addListener(new ProjectStructureDaemonAnalyzerListener() {
|
||||
@Override
|
||||
public void usagesCollected(@NotNull ProjectStructureElement containingElement) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void problemsChanged(@NotNull ProjectStructureElement element) {
|
||||
updateErrors(element);
|
||||
|
||||
+4
-14
@@ -102,7 +102,6 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
|
||||
LOG.debug("updating usages for " + element);
|
||||
}
|
||||
updateUsages(element, usages);
|
||||
myDispatcher.getMulticaster().usagesCollected(element);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -124,7 +123,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
|
||||
queueUpdate(element, true, true);
|
||||
}
|
||||
|
||||
public void queueUpdate(@NotNull final ProjectStructureElement element, final boolean check, final boolean collectUsages) {
|
||||
private void queueUpdate(@NotNull final ProjectStructureElement element, final boolean check, final boolean collectUsages) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("start " + (check ? "checking " : "") + (collectUsages ? "collecting usages " : "") + "for " + element);
|
||||
}
|
||||
@@ -184,17 +183,6 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isUnused(ProjectStructureElement element) {
|
||||
if (!element.shouldShowWarningIfUnused()) {
|
||||
return false;
|
||||
}
|
||||
if (!myElementWithNotCalculatedUsages.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
final Collection<ProjectStructureElementUsage> usages = mySourceElement2Usages.get(element);
|
||||
return usages == null || usages.isEmpty();
|
||||
}
|
||||
|
||||
private void removeUsagesInElement(ProjectStructureElement element) {
|
||||
final Collection<ProjectStructureElementUsage> usages = myContainingElement2Usages.removeAll(element);
|
||||
if (usages != null) {
|
||||
@@ -225,7 +213,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
|
||||
public void queueUpdateForAllElementsWithErrors() {
|
||||
List<ProjectStructureElement> toUpdate = new ArrayList<ProjectStructureElement>();
|
||||
for (Map.Entry<ProjectStructureElement, ProjectStructureProblemsHolderImpl> entry : myProblemHolders.entrySet()) {
|
||||
if (entry.getValue().containProblems()) {
|
||||
if (entry.getValue().containsProblems()) {
|
||||
toUpdate.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
@@ -274,6 +262,8 @@ public class ProjectStructureDaemonAnalyzer implements Disposable {
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
myWarningsAboutUnused.clear();
|
||||
myElementsToShowWarningIfUnused.clear();
|
||||
mySourceElement2Usages.clear();
|
||||
myContainingElement2Usages.clear();
|
||||
myElementWithNotCalculatedUsages.clear();
|
||||
|
||||
-3
@@ -23,8 +23,5 @@ import java.util.EventListener;
|
||||
* @author nik
|
||||
*/
|
||||
public interface ProjectStructureDaemonAnalyzerListener extends EventListener {
|
||||
|
||||
void usagesCollected(@NotNull ProjectStructureElement containingElement);
|
||||
|
||||
void problemsChanged(@NotNull ProjectStructureElement element);
|
||||
}
|
||||
|
||||
+5
-1
@@ -21,7 +21,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
* @author nik
|
||||
*/
|
||||
public class ProjectStructureProblemType {
|
||||
public enum Severity { ERROR, WARNING }
|
||||
public enum Severity { ERROR, WARNING, UNUSED }
|
||||
|
||||
private final String myId;
|
||||
private final Severity mySeverity;
|
||||
@@ -39,6 +39,10 @@ public class ProjectStructureProblemType {
|
||||
return new ProjectStructureProblemType(id, Severity.WARNING);
|
||||
}
|
||||
|
||||
public static ProjectStructureProblemType unused(@NotNull String id) {
|
||||
return new ProjectStructureProblemType(id, Severity.UNUSED);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getId() {
|
||||
return myId;
|
||||
|
||||
+14
-16
@@ -1,8 +1,8 @@
|
||||
package com.intellij.openapi.roots.ui.configuration.projectRoot.daemon;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.StringBuilderSpinAllocator;
|
||||
import com.intellij.xml.util.XmlStringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -30,19 +30,6 @@ public class ProjectStructureProblemsHolderImpl implements ProjectStructureProbl
|
||||
myProblemDescriptions.add(description);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ProjectStructureProblemType.Severity getSeverity() {
|
||||
if (myProblemDescriptions == null || myProblemDescriptions.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
for (ProjectStructureProblemDescription description : myProblemDescriptions) {
|
||||
if (description.getSeverity() == ProjectStructureProblemType.Severity.ERROR) {
|
||||
return ProjectStructureProblemType.Severity.ERROR;
|
||||
}
|
||||
}
|
||||
return ProjectStructureProblemType.Severity.WARNING;
|
||||
}
|
||||
|
||||
public String composeTooltipMessage() {
|
||||
final StringBuilder buf = StringBuilderSpinAllocator.alloc();
|
||||
try {
|
||||
@@ -50,7 +37,7 @@ public class ProjectStructureProblemsHolderImpl implements ProjectStructureProbl
|
||||
if (myProblemDescriptions != null) {
|
||||
int problems = 0;
|
||||
for (ProjectStructureProblemDescription problemDescription : myProblemDescriptions) {
|
||||
buf.append(StringUtil.escapeXml(problemDescription.getMessage())).append("<br>");
|
||||
buf.append(XmlStringUtil.escapeString(problemDescription.getMessage())).append("<br>");
|
||||
problems++;
|
||||
if (problems >= 10 && myProblemDescriptions.size() > 12) {
|
||||
buf.append(myProblemDescriptions.size() - problems).append(" more problems...<br>");
|
||||
@@ -66,10 +53,21 @@ public class ProjectStructureProblemsHolderImpl implements ProjectStructureProbl
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containProblems() {
|
||||
public boolean containsProblems() {
|
||||
return myProblemDescriptions != null && !myProblemDescriptions.isEmpty();
|
||||
}
|
||||
|
||||
public boolean containsProblems(final ProjectStructureProblemType.Severity severity) {
|
||||
if (myProblemDescriptions != null) {
|
||||
for (ProjectStructureProblemDescription description : myProblemDescriptions) {
|
||||
if (description.getSeverity() == severity) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void removeProblem(@NotNull ProjectStructureProblemDescription description) {
|
||||
if (myProblemDescriptions != null) {
|
||||
myProblemDescriptions.remove(description);
|
||||
|
||||
Reference in New Issue
Block a user