/*
* Copyright 2003-2012 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 jetbrains.mps.idea.core.usages;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorLocation;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.usages.TextChunk;
import com.intellij.usages.Usage;
import com.intellij.usages.UsagePresentation;
import com.intellij.usages.rules.MergeableUsage;
import com.intellij.usages.rules.UsageInModule;
import jetbrains.mps.ide.editor.MPSFileNodeEditor;
import jetbrains.mps.ide.project.ProjectHelper;
import jetbrains.mps.idea.core.usages.rules.UsageByCategory;
import jetbrains.mps.idea.core.usages.rules.UsageInMPS;
import jetbrains.mps.idea.core.usages.rules.UsageInModel;
import jetbrains.mps.idea.core.usages.rules.UsageInRoot;
import org.jetbrains.mps.openapi.model.SNode;import org.jetbrains.mps.openapi.model.SNodeId;import org.jetbrains.mps.openapi.model.SNodeReference;import org.jetbrains.mps.openapi.model.SReference;import org.jetbrains.mps.openapi.model.SModelId;import org.jetbrains.mps.openapi.model.SModel;import org.jetbrains.mps.openapi.model.SModel;import org.jetbrains.mps.openapi.model.SModelReference;import jetbrains.mps.smodel.*;
import jetbrains.mps.util.Computable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.mps.openapi.module.SRepository;
import javax.swing.Icon;
import java.util.ArrayList;
public class NodeUsage extends NodeNavigatable implements Usage, UsagePresentation, UsageInMPS, UsageInModule, MergeableUsage, UsageInRoot, UsageInModel, UsageByCategory, Comparable<NodeUsage> {
private SModelReference myModel;
private TextChunk[] myChunks;
private boolean myIsValid;
private String myParentPresentation;
private String myRole;
private String myCategory;
public NodeUsage(@NotNull SNodeReference node, @NotNull Project project, String category) {
super(node, project);
SRepository repository = ProjectHelper.getProjectRepository(project);
repository.getModelAccess().runReadAction(new Runnable() {
@Override
public void run() {
myModel = myNode.getModelReference();
SNode targetNode = myNode.resolve(repository);
if (targetNode != null) {
myParentPresentation = targetNode.getParent().getPresentation();
myRole = targetNode.getRoleInParent();
}
}
});
myIsValid = isValid();
myChunks = initChunks();
myCategory = category;
}
@NotNull
@Override
public UsagePresentation getPresentation() {
return this;
}
@Override
public boolean isReadOnly() {
return false;
}
@Override
public FileEditorLocation getLocation() {
VirtualFile virtualFile = getFile();
if (virtualFile == null) return null;
FileEditor editor = FileEditorManager.getInstance(myProject).getSelectedEditor(virtualFile);
if (!(editor instanceof MPSFileNodeEditor)) return null;
return editor.getCurrentLocation();
}
@Override
public void selectInEditor() {
}
@Override
public void highlightInEditor() {
}
@NotNull
@Override
public TextChunk[] getText() {
final boolean currentIsValid = isValid();
if (myIsValid != currentIsValid) {
myIsValid = isValid();
myChunks = initChunks();
}
return myChunks;
}
private TextChunk[] initChunks() {
final ArrayList<TextChunk> result = new ArrayList<TextChunk>();
TextAttributes attributes;
if (myIsValid) {
attributes = SimpleTextAttributes.SIMPLE_CELL_ATTRIBUTES.toTextAttributes();
} else {
attributes = SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES.toTextAttributes();
}
result.add(new TextChunk(attributes, myTextPresentation));
result.add(new TextChunk(attributes, " ("));
result.add(new TextChunk(attributes, "role: "));
result.add(new TextChunk(attributes, myRole));
result.add(new TextChunk(attributes, ";"));
result.add(new TextChunk(attributes, " in: "));
result.add(new TextChunk(attributes, myParentPresentation));
result.add(new TextChunk(attributes, ")"));
return result.toArray(new TextChunk[result.size()]);
}
@NotNull
@Override
public String getPlainText() {
return myTextPresentation;
}
@Override
public Icon getIcon() {
return myItemPresentation.getIcon(false);
}
@Override
public String getTooltipText() {
return null;
}
@Override
public Module getModule() {
if (!isValid()) return null;
VirtualFile virtualFile = getFile().getParent();
if (virtualFile == null) return null;
return ModuleUtil.findModuleForFile(virtualFile, myProject);
}
@Override
public boolean merge(MergeableUsage mergeableUsage) {
return mergeableUsage instanceof NodeUsage && myNode.equals(((NodeUsage) mergeableUsage).myNode);
}
@Override
public void reset() {
}
@Override
public boolean isValid() {
SRepository repository = ProjectHelper.getProjectRepository(myProject);
return new ModelAccessHelper(repository.getModelAccess()).runReadAction(new Computable<Boolean>() {
@Override
public Boolean compute() {
SNode node = myNode.resolve(repository);
return node != null && !(node.getModel() == null);
}
});
}
@Override
public VirtualFile getFile() {
return myFile;
}
@Override
public SModel getModel() {
return myModel.resolve(ProjectHelper.getProjectRepository(myProject));
}
@Override
public SNodeReference getRoot() {
return myRootNode;
}
@Override
public String getCategory() {
return myCategory;
}
@Override
public int compareTo(NodeUsage usage) {
VirtualFile myFile = getFile();
VirtualFile hisFile = usage.getFile();
if (!myFile.equals(hisFile)) {
return myFile.getPresentableUrl().compareTo(hisFile.getPresentableUrl());
}
return 0;
}
}