blob: eaed20f2960d9f4571d9edaa7c25628efd751857 [file] [log] [blame]
/*
* Copyright 2000-2014 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.fileEditor.impl;
import com.intellij.ide.PowerSaveMode;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.impl.text.TextEditorPsiDataProvider;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.problems.WolfTheProblemSolver;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.ui.ColorUtil;
import com.intellij.ui.docking.DockManager;
import com.intellij.util.messages.MessageBus;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
/**
* @author yole
*/
public class PsiAwareFileEditorManagerImpl extends FileEditorManagerImpl {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.fileEditor.impl.text.PsiAwareFileEditorManagerImpl");
private final PsiManager myPsiManager;
private final WolfTheProblemSolver myProblemSolver;
/**
* Updates icons for open files when project roots change
*/
private final MyPsiTreeChangeListener myPsiTreeChangeListener;
private final WolfTheProblemSolver.ProblemListener myProblemListener;
public PsiAwareFileEditorManagerImpl(final Project project,
final PsiManager psiManager,
final WolfTheProblemSolver problemSolver,
DockManager dockManager,
MessageBus messageBus,
EditorHistoryManager editorHistoryManager) {
super(project, dockManager, editorHistoryManager);
myPsiManager = psiManager;
myProblemSolver = problemSolver;
myPsiTreeChangeListener = new MyPsiTreeChangeListener();
myProblemListener = new MyProblemListener();
registerExtraEditorDataProvider(new TextEditorPsiDataProvider(), null);
// reinit syntax highlighter for Groovy. In power save mode keywords are highlighted by GroovySyntaxHighlighter insteadof
// GrKeywordAndDeclarationHighlighter. So we need to drop caches for token types attributes in LayeredLexerEditorHighlighter
messageBus.connect().subscribe(PowerSaveMode.TOPIC, new PowerSaveMode.Listener() {
@Override
public void powerSaveStateChanged() {
for (Editor editor : EditorFactory.getInstance().getAllEditors()) {
((EditorEx)editor).reinitSettings();
}
}
});
}
@Override
public void projectOpened() {
super.projectOpened(); //To change body of overridden methods use File | Settings | File Templates.
myPsiManager.addPsiTreeChangeListener(myPsiTreeChangeListener);
myProblemSolver.addProblemListener(myProblemListener);
}
@Override
public Color getFileColor(@NotNull final VirtualFile file) {
Color color = super.getFileColor(file);
if (myProblemSolver.isProblemFile(file)) {
return ColorUtil.toAlpha(color, WaverGraphicsDecorator.WAVE_ALPHA_KEY);
}
return color;
}
@Override
public boolean isProblem(@NotNull final VirtualFile file) {
return myProblemSolver.isProblemFile(file);
}
@NotNull
@Override
public String getFileTooltipText(@NotNull final VirtualFile file) {
final StringBuilder tooltipText = new StringBuilder();
final Module module = ModuleUtilCore.findModuleForFile(file, getProject());
if (module != null) {
tooltipText.append("[");
tooltipText.append(module.getName());
tooltipText.append("] ");
}
tooltipText.append(FileUtil.getLocationRelativeToUserHome(file.getPresentableUrl()));
return tooltipText.toString();
}
@Override
protected Editor getOpenedEditor(@NotNull final Editor editor, final boolean focusEditor) {
PsiDocumentManager documentManager = PsiDocumentManager.getInstance(getProject());
Document document = editor.getDocument();
PsiFile psiFile = documentManager.getPsiFile(document);
if (!focusEditor || documentManager.isUncommited(document)) {
return editor;
}
return InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(editor, psiFile);
}
/**
* Updates attribute of open files when roots change
*/
private final class MyPsiTreeChangeListener extends PsiTreeChangeAdapter {
@Override
public void propertyChanged(@NotNull final PsiTreeChangeEvent e) {
if (PsiTreeChangeEvent.PROP_ROOTS.equals(e.getPropertyName())) {
ApplicationManager.getApplication().assertIsDispatchThread();
final VirtualFile[] openFiles = getOpenFiles();
for (int i = openFiles.length - 1; i >= 0; i--) {
final VirtualFile file = openFiles[i];
LOG.assertTrue(file != null);
updateFileIcon(file);
}
}
}
@Override
public void childAdded(@NotNull PsiTreeChangeEvent event) {
doChange(event);
}
@Override
public void childRemoved(@NotNull PsiTreeChangeEvent event) {
doChange(event);
}
@Override
public void childReplaced(@NotNull PsiTreeChangeEvent event) {
doChange(event);
}
@Override
public void childMoved(@NotNull PsiTreeChangeEvent event) {
doChange(event);
}
@Override
public void childrenChanged(@NotNull PsiTreeChangeEvent event) {
doChange(event);
}
private void doChange(final PsiTreeChangeEvent event) {
final PsiFile psiFile = event.getFile();
if (psiFile == null) return;
VirtualFile file = psiFile.getVirtualFile();
if (file == null) return;
FileEditor[] editors = getAllEditors(file);
if (editors.length == 0) return;
final VirtualFile currentFile = getCurrentFile();
if (currentFile != null && Comparing.equal(psiFile.getVirtualFile(), currentFile)) {
updateFileIcon(currentFile);
}
}
}
private class MyProblemListener extends WolfTheProblemSolver.ProblemListener {
@Override
public void problemsAppeared(@NotNull final VirtualFile file) {
updateFile(file);
}
@Override
public void problemsDisappeared(@NotNull VirtualFile file) {
updateFile(file);
}
@Override
public void problemsChanged(@NotNull VirtualFile file) {
updateFile(file);
}
private void updateFile(@NotNull VirtualFile file) {
queueUpdateFile(file);
}
}
}