Merge branch 'master' of git@git.labs.intellij.net:idea/community

This commit is contained in:
Kirill Kalishev
2011-08-08 16:06:47 +04:00
42 changed files with 1618 additions and 172 deletions
@@ -50,7 +50,8 @@ import com.intellij.execution.configurations.CommandLineState;
import com.intellij.execution.configurations.RemoteConnection;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.filters.ExceptionFilter;
import com.intellij.execution.filters.ExceptionFilters;
import com.intellij.execution.filters.Filter;
import com.intellij.execution.filters.TextConsoleBuilder;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
@@ -1669,7 +1670,10 @@ public abstract class DebugProcessImpl implements DebugProcess {
if (state instanceof CommandLineState) {
final TextConsoleBuilder consoleBuilder = ((CommandLineState)state).getConsoleBuilder();
if (consoleBuilder != null) {
consoleBuilder.addFilter(new ExceptionFilter(session.getSearchScope()));
List<Filter> filters = ExceptionFilters.getFilters(session.getSearchScope());
for (Filter filter : filters) {
consoleBuilder.addFilter(filter);
}
}
}
myExecutionResult = state.execute(executor, runner);
@@ -33,7 +33,8 @@ import com.intellij.debugger.ui.impl.watch.*;
import com.intellij.execution.*;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.filters.ExceptionFilter;
import com.intellij.execution.filters.ExceptionFilters;
import com.intellij.execution.filters.Filter;
import com.intellij.execution.filters.TextConsoleBuilder;
import com.intellij.execution.filters.TextConsoleBuilderFactory;
import com.intellij.execution.runners.ExecutionEnvironment;
@@ -498,7 +499,10 @@ public class DebuggerSessionTab extends DebuggerSessionTabBase implements Dispos
public void addThreadDump(List<ThreadState> threads) {
final Project project = getProject();
final TextConsoleBuilder consoleBuilder = TextConsoleBuilderFactory.getInstance().createBuilder(project);
consoleBuilder.addFilter(new ExceptionFilter(myDebuggerSession.getSearchScope()));
List<Filter> filters = ExceptionFilters.getFilters(myDebuggerSession.getSearchScope());
for (Filter filter : filters) {
consoleBuilder.addFilter(filter);
}
final ConsoleView consoleView = consoleBuilder.getConsole();
final DefaultActionGroup toolbarActions = new DefaultActionGroup();
final ThreadDumpPanel panel = new ThreadDumpPanel(project, consoleView, toolbarActions, threads);
@@ -24,12 +24,16 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class DefaultConsoleFiltersProvider implements ConsoleFilterProviderEx {
public Filter[] getDefaultFilters(@NotNull Project project) {
return new Filter[]{new ExceptionFilter(project), new YourkitFilter(project)};
return getDefaultFilters(project, GlobalSearchScope.allScope(project));
}
public Filter[] getDefaultFilters(@NotNull Project project, @NotNull GlobalSearchScope scope) {
return new Filter[]{new ExceptionFilter(scope), new YourkitFilter(project)};
List<Filter> filters = ExceptionFilters.getFilters(scope);
filters.add(new YourkitFilter(project));
return filters.toArray(new Filter[filters.size()]);
}
}
@@ -0,0 +1,31 @@
/*
* 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.execution.filters;
import com.intellij.psi.search.GlobalSearchScope;
/**
* Created by IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 8/8/11
* Time: 12:11 PM
*/
public class ExceptionBaseFilterFactory implements ExceptionFilterFactory {
@Override
public Filter create(GlobalSearchScope searchScope) {
return new ExceptionFilter(searchScope);
}
}
@@ -15,135 +15,20 @@
*/
package com.intellij.execution.filters;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.Trinity;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
public class ExceptionFilter implements Filter, DumbAware {
private final Project myProject;
@NonNls private static final String AT = "at";
private static final String AT_PREFIX = AT + " ";
private static final String STANDALONE_AT = " " + AT + " ";
private static final TextAttributes HYPERLINK_ATTRIBUTES = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(CodeInsightColors.HYPERLINK_ATTRIBUTES);
private final GlobalSearchScope mySearchScope;
public ExceptionFilter(@NotNull final Project project) {
myProject = project;
mySearchScope = GlobalSearchScope.allScope(myProject);
}
private final GlobalSearchScope myScope;
public ExceptionFilter(@NotNull final GlobalSearchScope scope) {
myProject = scope.getProject();
mySearchScope = scope;
}
@Nullable
static Trinity<String, String, TextRange> parseExceptionLine(final String line) {
int atIndex;
if (line.startsWith(AT_PREFIX)){
atIndex = 0;
}
else{
atIndex = line.indexOf(STANDALONE_AT);
if (atIndex < 0) {
atIndex = line.indexOf(AT_PREFIX);
}
if (atIndex < 0) return null;
}
final int lparenthIndex = line.indexOf('(', atIndex);
if (lparenthIndex < 0) return null;
final int lastDotIndex = line.lastIndexOf('.', lparenthIndex);
if (lastDotIndex < 0 || lastDotIndex < atIndex) return null;
String className = line.substring(atIndex + AT.length() + 1, lastDotIndex).trim();
String methodName = line.substring(lastDotIndex + 1, lparenthIndex).trim();
final int rparenthIndex = line.indexOf(')', lparenthIndex);
if (rparenthIndex < 0) return null;
return Trinity.create(className, methodName, new TextRange(lparenthIndex, rparenthIndex));
myScope = scope;
}
public Result applyFilter(final String line, final int textEndOffset) {
final Trinity<String, String, TextRange> info = parseExceptionLine(line);
if (info == null) {
return null;
}
String className = info.first;
final int dollarIndex = className.indexOf('$');
if (dollarIndex >= 0){
className = className.substring(0, dollarIndex);
}
final int lparenthIndex = info.third.getStartOffset();
final int rparenthIndex = info.third.getEndOffset();
final String fileAndLine = line.substring(lparenthIndex + 1, rparenthIndex).trim();
final int colonIndex = fileAndLine.lastIndexOf(':');
if (colonIndex < 0) return null;
final String lineString = fileAndLine.substring(colonIndex + 1);
try{
final int lineNumber = Integer.parseInt(lineString);
final PsiManager manager = PsiManager.getInstance(myProject);
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(manager.getProject());
PsiClass aClass = psiFacade.findClass(className, mySearchScope);
if (aClass == null) {
aClass = psiFacade.findClass(className, GlobalSearchScope.allScope(myProject));
if (aClass == null) {//try to find class according to all dollars in package name
aClass = psiFacade.findClass(info.first, GlobalSearchScope.allScope(myProject));
}
if (aClass == null) return null;
}
final PsiFile file = (PsiFile) aClass.getContainingFile().getNavigationElement();
if (file == null) return null;
/*
IDEADEV-4976: Some scramblers put something like SourceFile mock instead of real class name.
final String filePath = fileAndLine.substring(0, colonIndex).replace('/', File.separatorChar);
final int slashIndex = filePath.lastIndexOf(File.separatorChar);
final String shortFileName = slashIndex < 0 ? filePath : filePath.substring(slashIndex + 1);
if (!file.getName().equalsIgnoreCase(shortFileName)) return null;
*/
final int textStartOffset = textEndOffset - line.length();
final int highlightStartOffset = textStartOffset + lparenthIndex + 1;
final int highlightEndOffset = textStartOffset + rparenthIndex;
VirtualFile virtualFile = file.getVirtualFile();
final OpenFileHyperlinkInfo linkInfo = new OpenFileHyperlinkInfo(myProject, virtualFile, lineNumber - 1);
TextAttributes attributes = HYPERLINK_ATTRIBUTES.clone();
if (!ProjectRootManager.getInstance(myProject).getFileIndex().isInContent(virtualFile)) {
Color color = UIUtil.getInactiveTextColor();
attributes.setForegroundColor(color);
attributes.setEffectColor(color);
}
return new Result(highlightStartOffset, highlightEndOffset, linkInfo, attributes);
}
catch(NumberFormatException e){
return null;
}
ExceptionWorker worker = new ExceptionWorker(myScope.getProject(), myScope);
worker.execute(line, textEndOffset);
return worker.getResult();
}
}
}
@@ -0,0 +1,31 @@
/*
* 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.execution.filters;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.psi.search.GlobalSearchScope;
/**
* Created by IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 8/5/11
* Time: 7:46 PM
*/
public interface ExceptionFilterFactory {
ExtensionPointName<ExceptionFilterFactory> EP_NAME = ExtensionPointName.create("com.intellij.exceptionFilter");
Filter create(final GlobalSearchScope searchScope);
}
@@ -0,0 +1,41 @@
/*
* 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.execution.filters;
import com.intellij.psi.search.GlobalSearchScope;
import java.util.ArrayList;
import java.util.List;
/**
* Created by IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 8/5/11
* Time: 7:54 PM
*/
public class ExceptionFilters {
private ExceptionFilters() {
}
public static List<Filter> getFilters(final GlobalSearchScope searchScope) {
List<Filter> filters = new ArrayList<Filter>();
ExceptionFilterFactory[] extensions = ExceptionFilterFactory.EP_NAME.getExtensions();
for (ExceptionFilterFactory extension : extensions) {
filters.add(extension.create(searchScope));
}
return filters;
}
}
@@ -0,0 +1,278 @@
/*
* 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.vcs.contentAnnotation;
import com.intellij.execution.filters.ExceptionWorker;
import com.intellij.execution.filters.Filter;
import com.intellij.execution.filters.FilterMixin;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diff.DiffColors;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.localVcs.UpToDateLineNumberProvider;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.Trinity;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.impl.UpToDateLineNumberProviderImpl;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.Consumer;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.Nullable;
import java.util.*;
/**
* Created by IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 8/5/11
* Time: 8:39 PM
*/
public class VcsContentAnnotationExceptionFilter implements Filter, FilterMixin {
private final Project myProject;
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.contentAnnotation.VcsContentAnnotationExceptionFilter");
private final GlobalSearchScope myScope;
public VcsContentAnnotationExceptionFilter(GlobalSearchScope scope) {
myScope = scope;
myProject = scope.getProject();
}
private static class MyAdditionalHighlight extends AdditionalHighlight {
private MyAdditionalHighlight(int start, int end) {
super(start, end);
}
@Override
public TextAttributes getTextAttributes(@Nullable TextAttributes source) {
EditorColorsScheme globalScheme = EditorColorsManager.getInstance().getGlobalScheme();
final TextAttributes changedColor = globalScheme.getAttributes(DiffColors.DIFF_MODIFIED);
if (source == null) {
TextAttributes atts =
globalScheme.getAttributes(CodeInsightColors.CLASS_NAME_ATTRIBUTES).clone();
atts.setBackgroundColor(changedColor.getBackgroundColor());
return atts;
}
TextAttributes clone = source.clone();
clone.setBackgroundColor(changedColor.getBackgroundColor());
return clone;
}
}
@Override
public void applyHeavyFilter(final Document copiedFragment,
int startOffset,
int startLineNumber,
Consumer<AdditionalHighlight> consumer) {
VcsContentAnnotation vcsContentAnnotation = VcsContentAnnotationImpl.getInstance(myProject);
final LocalChangesCorrector localChangesCorrector = new LocalChangesCorrector(myProject);
Trinity<PsiClass, PsiFile, String> previousLineResult = null;
for (int i = 0; i < copiedFragment.getLineCount(); i++) {
final int lineStartOffset = copiedFragment.getLineStartOffset(i);
final int lineEndOffset = copiedFragment.getLineEndOffset(i);
final ExceptionWorker worker = new ExceptionWorker(myProject, myScope);
final String[] lineText = new String[1];
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
lineText[0] = copiedFragment.getText(new TextRange(lineStartOffset, lineEndOffset));
worker.execute(lineText[0], lineEndOffset);
}
});
if (worker.getResult() != null) {
VirtualFile vf = worker.getFile().getVirtualFile();
if (localChangesCorrector.isFileAlreadyIdentifiedAsChanged(vf) || ChangeListManager.isFileChanged(myProject, vf) ||
vcsContentAnnotation.fileRecentlyChanged(vf)) {
final Document document = getDocumentForFile(worker);
if (document == null) return;
int startFileOffset = worker.getInfo().getThird().getStartOffset();
int idx = lineText[0].indexOf(':', startFileOffset);
int endIdx = idx == -1 ? worker.getInfo().getThird().getEndOffset() : idx;
consumer.consume(new MyAdditionalHighlight(startOffset + lineStartOffset + startFileOffset + 1, startOffset + lineStartOffset + endIdx));
// also check method
final List<TextRange> ranges = findMethodRange(worker, document, previousLineResult);
if (ranges != null) {
boolean methodChanged = false;
for (TextRange range : ranges) {
if (localChangesCorrector.isRangeChangedLocally(vf, document, range)) {
methodChanged = true;
break;
}
final TextRange correctedRange = localChangesCorrector.getCorrectedRange(vf, document, range);
if (vcsContentAnnotation.intervalRecentlyChanged(vf, correctedRange)) {
methodChanged = true;
break;
}
}
if (methodChanged) {
consumer.consume(new MyAdditionalHighlight(startOffset + lineStartOffset + worker.getInfo().getSecond().getStartOffset(),
startOffset + lineStartOffset + worker.getInfo().getSecond().getEndOffset()));
}
}
}
}
previousLineResult = worker.getResult() == null ? null :
new Trinity<PsiClass, PsiFile, String>(worker.getPsiClass(), worker.getFile(), worker.getMethod());
}
}
private static class LocalChangesCorrector {
private final Map<VirtualFile, UpToDateLineNumberProvider> myRecentlyChanged;
private final Project myProject;
private LocalChangesCorrector(final Project project) {
myProject = project;
myRecentlyChanged = new HashMap<VirtualFile, UpToDateLineNumberProvider>();
}
public boolean isFileAlreadyIdentifiedAsChanged(final VirtualFile vf) {
return myRecentlyChanged.containsKey(vf);
}
public boolean isRangeChangedLocally(final VirtualFile vf, final Document document, final TextRange range) {
final UpToDateLineNumberProvider provider = getProvider(vf, document);
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
@Override
public Boolean compute() {
return provider.isRangeChanged(range.getStartOffset(), range.getEndOffset());
}
});
}
public TextRange getCorrectedRange(final VirtualFile vf, final Document document, final TextRange range) {
final UpToDateLineNumberProvider provider = getProvider(vf, document);
if (provider == null) return range;
return ApplicationManager.getApplication().runReadAction(new Computable<TextRange>() {
@Override
public TextRange compute() {
return new TextRange(provider.getLineNumber(range.getStartOffset()), provider.getLineNumber(range.getEndOffset()));
}
});
}
private UpToDateLineNumberProvider getProvider(VirtualFile vf, Document document) {
UpToDateLineNumberProvider provider = myRecentlyChanged.get(vf);
if (provider == null) {
provider = new UpToDateLineNumberProviderImpl(document, myProject);
myRecentlyChanged.put(vf, provider);
}
return provider;
}
}
private Document getDocumentForFile(final ExceptionWorker worker) {
return ApplicationManager.getApplication().runReadAction(new Computable<Document>() {
@Override
public Document compute() {
final Document document = FileDocumentManager.getInstance().getDocument(worker.getFile().getVirtualFile());
if (document == null) {
LOG.info("can not get document for file: " + worker.getFile().getVirtualFile());
return null;
}
return document;
}
});
}
/* final UpToDateLineNumberProvider getUpToDateLineNumber = new UpToDateLineNumberProviderImpl(editor.getDocument(), project, upToDateContent);
/**/
// line numbers
private List<TextRange> findMethodRange(final ExceptionWorker worker, final Document document, final Trinity<PsiClass, PsiFile, String> previousLineResult) {
return ApplicationManager.getApplication().runReadAction(new Computable<List<TextRange>>() {
@Override
public List<TextRange> compute() {
List<TextRange> ranges = getTextRangeForMethod(worker, previousLineResult);
if (ranges == null) return null;
final List<TextRange> result = new ArrayList<TextRange>();
for (TextRange range : ranges) {
result.add(new TextRange(document.getLineNumber(range.getStartOffset()),
document.getLineNumber(range.getEndOffset())));
}
return result;
}
});
}
// null - check all
@Nullable
private List<PsiMethod> selectMethod(final PsiMethod[] methods, final Trinity<PsiClass, PsiFile, String> previousLineResult) {
if (previousLineResult == null || previousLineResult.getThird() == null) return null;
final List<PsiMethod> result = new SmartList<PsiMethod>();
for (final PsiMethod method : methods) {
method.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitCallExpression(PsiCallExpression callExpression) {
final PsiMethod resolved = callExpression.resolveMethod();
if (resolved != null) {
if (resolved.getName().equals(previousLineResult.getThird())) {
result.add(method);
}
}
}
});
}
return result;
}
private List<TextRange> getTextRangeForMethod(final ExceptionWorker worker, Trinity<PsiClass, PsiFile, String> previousLineResult) {
String method = worker.getMethod();
PsiClass psiClass = worker.getPsiClass();
PsiMethod[] methods;
if (method.contains("<init>")) {
// constructor
methods = psiClass.getConstructors();
} else if (method.contains("$")) {
// access$100
return null;
} else {
methods = psiClass.findMethodsByName(method, false);
}
if (methods.length > 0) {
if (methods.length == 1) {
final TextRange range = methods[0].getTextRange();
return Collections.singletonList(range);
} else {
List<PsiMethod> selectedMethods = selectMethod(methods, previousLineResult);
final List<PsiMethod> toIterate = selectedMethods == null ? Arrays.asList(methods) : selectedMethods;
final List<TextRange> result = new ArrayList<TextRange>();
for (PsiMethod psiMethod : toIterate) {
result.add(psiMethod.getTextRange());
}
return result;
}
}
return null;
}
@Override
public Result applyFilter(String line, int entireLength) {
return null;
}
}
@@ -0,0 +1,33 @@
/*
* 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.vcs.contentAnnotation;
import com.intellij.execution.filters.ExceptionFilterFactory;
import com.intellij.execution.filters.Filter;
import com.intellij.psi.search.GlobalSearchScope;
/**
* Created by IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 8/5/11
* Time: 8:03 PM
*/
public class VcsContentAnnotationExceptionFilterFactory implements ExceptionFilterFactory {
@Override
public Filter create(GlobalSearchScope searchScope) {
return new VcsContentAnnotationExceptionFilter(searchScope);
}
}
@@ -89,7 +89,8 @@ public class ThreadDumpPanel extends JPanel {
});
toolbarActions.add(new CopyToClipboardAction(threadDump, project));
toolbarActions.add(new SortThreadsAction());
add(ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, toolbarActions,false).getComponent(), BorderLayout.WEST);
//toolbarActions.add(new ShowRecentlyChanged());
add(ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, toolbarActions, false).getComponent(), BorderLayout.WEST);
final Splitter splitter = new Splitter(false, 0.3f);
splitter.setFirstComponent(ScrollPaneFactory.createScrollPane(myThreadList));
@@ -0,0 +1,198 @@
/*
* 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.execution.filters;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.Trinity;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
/**
* Created by IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 8/5/11
* Time: 8:36 PM
* To change this template use File | Settings | File Templates.
*/
public class ExceptionWorker {
@NonNls private static final String AT = "at";
private static final String AT_PREFIX = AT + " ";
private static final String STANDALONE_AT = " " + AT + " ";
private static final TextAttributes HYPERLINK_ATTRIBUTES = EditorColorsManager
.getInstance().getGlobalScheme().getAttributes(CodeInsightColors.HYPERLINK_ATTRIBUTES);
private final Project myProject;
private final GlobalSearchScope mySearchScope;
private Filter.Result myResult;
private PsiClass myClass;
private PsiFile myFile;
private String myMethod;
private Trinity<TextRange,TextRange,TextRange> myInfo;
public ExceptionWorker(Project project, final GlobalSearchScope searchScope) {
myProject = project;
mySearchScope = searchScope;
}
public void execute(final String line, final int textEndOffset) {
myInfo = parseExceptionLine(line);
if (myInfo == null) {
return;
}
myMethod = myInfo.getSecond().substring(line);
String className = myInfo.first.substring(line).trim();
final int dollarIndex = className.indexOf('$');
if (dollarIndex >= 0){
className = className.substring(0, dollarIndex);
}
final int lparenthIndex = myInfo.third.getStartOffset();
final int rparenthIndex = myInfo.third.getEndOffset();
final String fileAndLine = line.substring(lparenthIndex + 1, rparenthIndex).trim();
final int colonIndex = fileAndLine.lastIndexOf(':');
if (colonIndex < 0) return;
final String lineString = fileAndLine.substring(colonIndex + 1);
try{
final int lineNumber = Integer.parseInt(lineString);
final PsiManager manager = PsiManager.getInstance(myProject);
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(manager.getProject());
myClass = psiFacade.findClass(className, mySearchScope);
if (myClass == null) {
myClass = psiFacade.findClass(className, GlobalSearchScope.allScope(myProject));
if (myClass == null) {//try to find class according to all dollars in package name
myClass = psiFacade.findClass(className, GlobalSearchScope.allScope(myProject));
}
if (myClass == null) return;
}
myFile = (PsiFile) myClass.getContainingFile().getNavigationElement();
if (myFile == null) return;
/*
IDEADEV-4976: Some scramblers put something like SourceFile mock instead of real class name.
final String filePath = fileAndLine.substring(0, colonIndex).replace('/', File.separatorChar);
final int slashIndex = filePath.lastIndexOf(File.separatorChar);
final String shortFileName = slashIndex < 0 ? filePath : filePath.substring(slashIndex + 1);
if (!file.getName().equalsIgnoreCase(shortFileName)) return null;
*/
final int textStartOffset = textEndOffset - line.length();
final int highlightStartOffset = textStartOffset + lparenthIndex + 1;
final int highlightEndOffset = textStartOffset + rparenthIndex;
VirtualFile virtualFile = myFile.getVirtualFile();
final OpenFileHyperlinkInfo linkInfo = new OpenFileHyperlinkInfo(myProject, virtualFile, lineNumber - 1);
TextAttributes attributes = HYPERLINK_ATTRIBUTES.clone();
if (!ProjectRootManager.getInstance(myProject).getFileIndex().isInContent(virtualFile)) {
Color color = UIUtil.getInactiveTextColor();
attributes.setForegroundColor(color);
attributes.setEffectColor(color);
}
myResult = new Filter.Result(highlightStartOffset, highlightEndOffset, linkInfo, attributes);
}
catch(NumberFormatException e){
//
}
}
public Filter.Result getResult() {
return myResult;
}
public PsiClass getPsiClass() {
return myClass;
}
public String getMethod() {
return myMethod;
}
public PsiFile getFile() {
return myFile;
}
public Trinity<TextRange, TextRange, TextRange> getInfo() {
return myInfo;
}
@Nullable
static Trinity<TextRange, TextRange, TextRange> parseExceptionLine(final String line) {
int atIndex;
if (line.startsWith(AT_PREFIX)){
atIndex = 0;
}
else{
atIndex = line.indexOf(STANDALONE_AT);
if (atIndex < 0) {
atIndex = line.indexOf(AT_PREFIX);
}
if (atIndex < 0) return null;
}
final int lparenthIndex = line.indexOf('(', atIndex);
if (lparenthIndex < 0) return null;
final int lastDotIndex = line.lastIndexOf('.', lparenthIndex);
if (lastDotIndex < 0 || lastDotIndex < atIndex) return null;
final int rparenthIndex = line.indexOf(')', lparenthIndex);
if (rparenthIndex < 0) return null;
// class, method, link
return Trinity.create(adjustedRange(line, atIndex + AT.length() + 1, lastDotIndex),
adjustedRange(line, lastDotIndex + 1, lparenthIndex), new TextRange(lparenthIndex, rparenthIndex));
}
private static TextRange adjustedRange(final String line, final int start, final int end) {
String sub = line.substring(start, end);
return new TextRange(start, end - spacesEnd(sub));
}
private static int spacesStart(final String s) {
int cnt = 0;
for (int i = 0; i < s.length(); i++) {
final char c = s.charAt(i);
if (! Character.isSpaceChar(c)) return cnt;
++ cnt;
}
return 0;
}
private static int spacesEnd(final String s) {
int cnt = 0;
for (int i = s.length() - 1; i >= 0; i--) {
final char c = s.charAt(i);
if (! Character.isSpaceChar(c)) return cnt;
++ cnt;
}
return 0;
}
}
@@ -15,15 +15,18 @@
*/
package com.intellij.execution.filters;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class CompositeFilter implements Filter {
public class CompositeFilter implements Filter, FilterMixin {
private final List<Filter> myFilters = new ArrayList<Filter>();
private boolean myIsAnyHeavy;
private final DumbService myDumbService;
public CompositeFilter(Project project) {
@@ -48,11 +51,34 @@ public class CompositeFilter implements Filter {
return null;
}
@Override
public void applyHeavyFilter(Document copiedFragment,
int startOffset,
int startLineNumber,
Consumer<AdditionalHighlight> consumer) {
final boolean dumb = myDumbService.isDumb();
List<Filter> filters = myFilters;
int count = filters.size();
//noinspection ForLoopReplaceableByForEach
for (int i = 0; i < count; i++) {
Filter filter = filters.get(i);
if (! (filter instanceof FilterMixin)) continue;
if (!dumb || DumbService.isDumbAware(filter)) {
((FilterMixin) filter).applyHeavyFilter(copiedFragment, startOffset, startLineNumber, consumer);
}
}
}
public boolean isEmpty() {
return myFilters.isEmpty();
}
public boolean isAnyHeavy() {
return myIsAnyHeavy;
}
public void addFilter(final Filter filter) {
myFilters.add(filter);
myIsAnyHeavy |= filter instanceof FilterMixin;
}
}
}
@@ -44,6 +44,7 @@ public interface Filter {
/**
* Filters line by creating an instance of {@link Result}.
*
*
* @param line
* The line to be filtered. Note that the line must contain a line
* separator at the end.
@@ -0,0 +1,52 @@
/*
* 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.execution.filters;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 8/3/11
* Time: 4:50 PM
*/
public interface FilterMixin {
@Nullable
void applyHeavyFilter(Document copiedFragment, int startOffset, int startLineNumber, Consumer<AdditionalHighlight> consumer);
abstract class AdditionalHighlight {
private final int myStart;
private final int myEnd;
public AdditionalHighlight(int start, int end) {
myStart = start;
myEnd = end;
}
public int getStart() {
return myStart;
}
public int getEnd() {
return myEnd;
}
public abstract TextAttributes getTextAttributes(@Nullable final TextAttributes source);
}
}
@@ -41,11 +41,11 @@ import com.intellij.openapi.editor.actions.ToggleUseSoftWrapsToolbarAction;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.event.*;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.ex.FoldingModelEx;
import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
import com.intellij.openapi.editor.highlighter.HighlighterClient;
import com.intellij.openapi.editor.highlighter.HighlighterIterator;
import com.intellij.openapi.editor.impl.DocumentImpl;
import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces;
import com.intellij.openapi.editor.markup.HighlighterLayer;
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
@@ -60,10 +60,7 @@ import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.LineTokenizer;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
@@ -91,7 +88,7 @@ import java.util.*;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;
public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableConsoleView, DataProvider, OccurenceNavigator {
public class ConsoleViewImpl implements ConsoleView, ObservableConsoleView, DataProvider, OccurenceNavigator {
@NonNls private static final String CONSOLE_VIEW_POPUP_MENU = "ConsoleView.PopupMenu";
private static final Logger LOG = Logger.getInstance("#com.intellij.execution.impl.ConsoleViewImpl");
@@ -115,12 +112,17 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
private Computable<ModalityState> myStateForUpdate;
private final Alarm mySpareTimeAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, this);
@Nullable
private final Alarm myHeavyAlarm;
private final CopyOnWriteArraySet<ChangeListener> myListeners = new CopyOnWriteArraySet<ChangeListener>();
private final ArrayList<AnAction> customActions = new ArrayList<AnAction>();
private final ConsoleBuffer myBuffer = new ConsoleBuffer();
private boolean myUpdateFoldingsEnabled = true;
private EditorHyperlinkSupport myHyperlinks;
private MyDiffContainer myJLayeredPane;
private JPanel myMainPanel;
private final Runnable myFinishProgress;
@TestOnly
public Editor getEditor() {
@@ -272,7 +274,6 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
protected ConsoleViewImpl(final Project project, GlobalSearchScope searchScope, boolean viewer, FileType fileType,
@NotNull final ConsoleState initialState) {
super(new BorderLayout());
isViewer = viewer;
myState = initialState;
myPsiDisposedCheck = new DisposedPsiManagerCheck(project);
@@ -289,8 +290,19 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
myPredefinedMessageFilter.addFilter(filter);
}
}
if (myPredefinedMessageFilter.isAnyHeavy()) {
myHeavyAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD, this);
} else {
myHeavyAlarm = null;
}
Disposer.register(project, this);
myFinishProgress = new Runnable() {
@Override
public void run() {
myJLayeredPane.finishUpdating();
}
};
}
public void attachToProcess(final ProcessHandler processHandler) {
@@ -368,17 +380,27 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
}
},
100,
ModalityState.stateForComponent(this)
ModalityState.stateForComponent(myJLayeredPane)
);
}
}
public void addToolbar(JComponent component, String constraint) {
myMainPanel.add(component, constraint);
}
public JComponent getComponent() {
if (myMainPanel == null) {
myMainPanel = new JPanel(new BorderLayout());
myJLayeredPane = new MyDiffContainer(myMainPanel, "Checking recent changes...");
}
if (myEditor == null) {
myEditor = createEditor();
myHyperlinks = new EditorHyperlinkSupport(myEditor, myProject);
requestFlushImmediately();
add(createCenterComponent(), BorderLayout.CENTER);
myMainPanel.add(createCenterComponent(), BorderLayout.CENTER);
myEditor.getDocument().addDocumentListener(new DocumentAdapter() {
public void documentChanged(DocumentEvent e) {
@@ -412,7 +434,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
}
});
}
return this;
return myJLayeredPane;
}
protected JComponent createCenterComponent() {
@@ -436,6 +458,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
myEditor = null;
myHyperlinks = null;
}
myJLayeredPane.dispose();
}
protected void disposeEditor() {
@@ -476,7 +499,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
}
private ModalityState getStateForUpdate() {
return myStateForUpdate != null ? myStateForUpdate.compute() : ModalityState.stateForComponent(this);
return myStateForUpdate != null ? myStateForUpdate.compute() : ModalityState.stateForComponent(myJLayeredPane);
}
private void requestFlushImmediately() {
@@ -789,6 +812,43 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
if (canHighlightHyperlinks) {
myHyperlinks.highlightHyperlinks(myCustomFilter, myPredefinedMessageFilter, line1, endLine);
}
if (myPredefinedMessageFilter.isAnyHeavy()) {
final int startLine = Math.max(0, line1);
final Document document = getEditor().getDocument();
final Document documentCopy = new DocumentImpl(true);
final int startOffset = document.getLineStartOffset(startLine);
documentCopy.setText(new String(document.getText(new TextRange(startOffset, document.getLineEndOffset(endLine)))));
documentCopy.setReadOnly(true);
myJLayeredPane.startUpdating();
myHeavyAlarm.addRequest(new Runnable() {
@Override
public void run() {
myPredefinedMessageFilter.applyHeavyFilter(documentCopy, startOffset, startLine, new Consumer<FilterMixin.AdditionalHighlight>() {
@Override
public void consume(final FilterMixin.AdditionalHighlight additionalHighlight) {
SwingUtilities.invokeLater(
new Runnable() {
@Override
public void run() {
myFlushAlarm.addRequest(new Runnable() {
@Override
public void run() {
myHyperlinks.adjustHighlighters(Collections.singletonList(additionalHighlight));
}
}, 0);
}
});
}
});
if (myHeavyAlarm.getActiveRequestCount() == 0) {
SwingUtilities.invokeLater(myFinishProgress);
}
}
}, 0);
}
if (myUpdateFoldingsEnabled) {
updateFoldings(line1, endLine, true);
}
@@ -1066,7 +1126,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
s = (String)content.getTransferData(DataFlavor.stringFlavor);
}
catch (Exception e) {
consoleView.getToolkit().beep();
consoleView.getComponent().getToolkit().beep();
}
if (s == null) return;
Editor editor = consoleView.myEditor;
@@ -1279,6 +1339,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
consoleActions[1] = nextAction;
consoleActions[2] = switchSoftWrapsAction;
consoleActions[3] = autoScrollToTheEndAction;
//consoleActions[4] = new ShowRecentlyChanged();
for (int i = 0; i < customActions.size(); ++i) {
consoleActions[i + 4] = customActions.get(i);
}
@@ -0,0 +1,96 @@
/*
* 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.execution.impl;
import com.intellij.openapi.Disposable;
import com.intellij.util.ui.AbstractLayoutManager;
import com.intellij.util.ui.AnimatedIcon;
import com.intellij.util.ui.AsyncProcessIcon;
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
import java.awt.*;
/**
* Created by IntelliJ IDEA.
* @author amakeev
* @author Irina.Chernushina
* Date: 8/8/11
* Time: 3:13 PM
*/
public class MyDiffContainer extends JLayeredPane implements Disposable {
private AnimatedIcon myIcon = new AsyncProcessIcon(this.getClass().getName());
private JComponent myContent;
private JComponent myLoadingPanel;
private final JLabel myJLabel;
public MyDiffContainer(JComponent content, final String text) {
setLayout(new MyOverlayLayout());
myContent = content;
myLoadingPanel = new JPanel(new MyPanelLayout());
myLoadingPanel.setOpaque(false);
myLoadingPanel.add(myIcon);
myJLabel = new JLabel(text);
myJLabel.setForeground(UIUtil.getInactiveTextColor());
myLoadingPanel.add(myJLabel);
add(myContent);
add(myLoadingPanel, JLayeredPane.POPUP_LAYER);
finishUpdating();
}
public void dispose() {
myIcon.dispose();
}
public void startUpdating() {
myLoadingPanel.setVisible(true);
myIcon.resume();
}
public void finishUpdating() {
myIcon.suspend();
myLoadingPanel.setVisible(false);
}
private class MyOverlayLayout extends AbstractLayoutManager {
public void layoutContainer(Container parent) {
myContent.setBounds(0, 0, getWidth(), getHeight());
myLoadingPanel.setBounds(0, 0, getWidth(), getHeight());
}
public Dimension preferredLayoutSize(Container parent) {
return myContent.getPreferredSize();
}
}
private class MyPanelLayout extends AbstractLayoutManager {
public void layoutContainer(Container parent) {
Dimension size = myIcon.getPreferredSize();
Dimension preferredSize = myJLabel.getPreferredSize();
int width = getWidth();
int offset = width - size.width - 15 - preferredSize.width;
myIcon.setBounds(offset, 0, size.width, size.height);
myJLabel.setBounds(offset + size.width + 3, 0, preferredSize.width, size.height);
}
public Dimension preferredLayoutSize(Container parent) {
return myContent.getPreferredSize();
}
}
}
@@ -0,0 +1,61 @@
/*
* 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.unscramble;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.configurable.VcsContentAnnotationConfigurable;
/**
* Created by IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 8/4/11
* Time: 2:29 PM
* To change this template use File | Settings | File Templates.
*/
public class ShowRecentlyChanged extends DumbAwareAction {
public ShowRecentlyChanged() {
super("Show recently changed", "Show recently changed", IconLoader.getIcon("/general/copy.png"));
}
@Override
public void actionPerformed(AnActionEvent e) {
if (! enabled(e)) return;
Project project = PlatformDataKeys.PROJECT.getData(e.getDataContext());
VcsContentAnnotationConfigurable configurable = new VcsContentAnnotationConfigurable(project);
ShowSettingsUtil.getInstance().editConfigurable(project, configurable);
// todo recalculate highlight
}
private boolean enabled(AnActionEvent e) {
Project project = PlatformDataKeys.PROJECT.getData(e.getDataContext());
if (project == null) return false;
ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(project);
if (! vcsManager.hasActiveVcss()) return false;
return true;
}
@Override
public void update(AnActionEvent e) {
e.getPresentation().setEnabled(enabled(e));
}
}
@@ -258,16 +258,4 @@ public class LoadingDecorator {
frame.setBounds(300, 300, 300, 300);
frame.show();
}
private static class MyLayeredPane extends JLayeredPane {
@Override
public void doLayout() {
super.doLayout();
for (int i = 0; i < getComponentCount(); i++) {
final Component each = getComponent(i);
each.setBounds(0, 0, getWidth(), getHeight());
}
}
}
}
@@ -0,0 +1,41 @@
/*
* 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.ui;
import javax.swing.*;
import java.awt.*;
/**
* Created by IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 8/4/11
* Time: 3:59 PM
* To change this template use File | Settings | File Templates.
*/
public class MyLayeredPane extends JLayeredPane {
@Override
public void doLayout() {
super.doLayout();
for (int i = 0; i < getComponentCount(); i++) {
final Component each = getComponent(i);
if (each instanceof Icon) {
each.setBounds(0, 0, each.getWidth(), each.getHeight());
} else {
each.setBounds(0, 0, getWidth(), getHeight());
}
}
}
}
@@ -45,6 +45,7 @@ import java.util.Map;
*/
public class SimpleColoredComponent extends JComponent implements Accessible {
private static final Logger LOG = Logger.getInstance("#com.intellij.ui.SimpleColoredComponent");
public static final Color STYLE_SEARCH_MATCH_BACKGROUND = new Color(250, 250, 250, 140);
private final ArrayList<String> myFragments;
private final ArrayList<SimpleTextAttributes> myAttributes;
@@ -439,7 +440,7 @@ public class SimpleColoredComponent extends JComponent implements Accessible {
if (!attributes.isSearchMatch()) {
if (shouldDrawMacShadow()) {
g.setColor(new Color(250, 250, 250, 140));
g.setColor(STYLE_SEARCH_MATCH_BACKGROUND);
g.drawString(fragment, xOffset, textBaseline + 1);
}
@@ -16,6 +16,7 @@
package com.intellij.execution.impl;
import com.intellij.execution.filters.Filter;
import com.intellij.execution.filters.FilterMixin;
import com.intellij.execution.filters.HyperlinkInfo;
import com.intellij.ide.OccurenceNavigator;
import com.intellij.openapi.editor.Document;
@@ -33,7 +34,9 @@ import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.pom.Navigatable;
import com.intellij.util.BeforeAfter;
import com.intellij.util.Consumer;
import com.intellij.util.SmartList;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -50,14 +53,18 @@ import java.util.List;
public class EditorHyperlinkSupport {
public static final Key<TextAttributes> OLD_HYPERLINK_TEXT_ATTRIBUTES = Key.create("OLD_HYPERLINK_TEXT_ATTRIBUTES");
private static final int HYPERLINK_LAYER = HighlighterLayer.SELECTION - 123;
private static final int HIGHLIGHT_LAYER = HighlighterLayer.SELECTION - 111;
private static final int NO_INDEX = Integer.MIN_VALUE;
private final Editor myEditor;
private final Map<RangeHighlighter, HyperlinkInfo> myHighlighterToMessageInfoMap = new HashMap<RangeHighlighter, HyperlinkInfo>();
private int myLastIndex = NO_INDEX;
private final Consumer<BeforeAfter<Filter.Result>> myRefresher;
private final List<RangeHighlighter> myHighlighters;
public EditorHyperlinkSupport(@NotNull final Editor editor, @NotNull final Project project) {
myEditor = editor;
myHighlighters = new SmartList<RangeHighlighter>();
editor.addEditorMouseListener(new EditorMouseAdapter() {
public void mouseReleased(final EditorMouseEvent e) {
@@ -86,10 +93,78 @@ public class EditorHyperlinkSupport {
}
}
);
myRefresher = new Consumer<BeforeAfter<Filter.Result>>() {
@Override
public void consume(BeforeAfter<Filter.Result> resultBeforeAfter) {
if (resultBeforeAfter.getBefore() == null) return;
final RangeHighlighter hyperlinkRange = findHyperlinkRange(resultBeforeAfter.getBefore().hyperlinkInfo);
if (hyperlinkRange != null) {
myHighlighterToMessageInfoMap.remove(hyperlinkRange);
} else {
final Iterator<RangeHighlighter> iterator = myHighlighters.iterator();
while (iterator.hasNext()) {
final RangeHighlighter highlighter = iterator.next();
if (highlighter.isValid() && containsOffset(resultBeforeAfter.getBefore().highlightStartOffset, highlighter)) {
iterator.remove();
break;
}
}
}
if (resultBeforeAfter.getAfter() != null) {
if (resultBeforeAfter.getAfter().hyperlinkInfo != null) {
addHyperlink(resultBeforeAfter.getAfter().highlightStartOffset, resultBeforeAfter.getAfter().highlightEndOffset,
resultBeforeAfter.getAfter().highlightAttributes, resultBeforeAfter.getAfter().hyperlinkInfo);
} else if (resultBeforeAfter.getAfter().highlightAttributes != null) {
addHighlighter(resultBeforeAfter.getAfter().highlightStartOffset, resultBeforeAfter.getAfter().highlightEndOffset,
resultBeforeAfter.getAfter().highlightAttributes);
}
}
}
};
}
public void adjustHighlighters(final List<FilterMixin.AdditionalHighlight> highlights) {
for (FilterMixin.AdditionalHighlight highlight : highlights) {
RangeHighlighter found = null;
for (RangeHighlighter rangeHighlighter : myHighlighterToMessageInfoMap.keySet()) {
if (rangeHighlighter.getStartOffset() <= highlight.getStart() && rangeHighlighter.getEndOffset() >= highlight.getEnd()) {
found = rangeHighlighter;
break;
}
}
if (found != null) {
TextAttributes textAttributes = highlight.getTextAttributes(found.getTextAttributes());
final HyperlinkInfo hyperlinkInfo = myHighlighterToMessageInfoMap.remove(found);
if (found.getStartOffset() != highlight.getStart()) {
addHyperlink(found.getStartOffset(), highlight.getEnd(), found.getTextAttributes(), hyperlinkInfo);
}
if (found.getEndOffset() != highlight.getEnd()) {
addHyperlink(highlight.getEnd(), found.getEndOffset(), found.getTextAttributes(), hyperlinkInfo);
}
addHyperlink(highlight.getStart(), highlight.getEnd(), textAttributes, hyperlinkInfo);
myEditor.getMarkupModel().removeHighlighter(found);
return;
}
final Iterator<RangeHighlighter> iterator = myHighlighters.iterator();
while (iterator.hasNext()) {
final RangeHighlighter highlighter = iterator.next();
if (highlighter.getStartOffset() == highlight.getStart() && highlighter.getEndOffset() == highlight.getEnd()) {
iterator.remove();
final TextAttributes textAttributes = highlight.getTextAttributes(highlighter.getTextAttributes());
addHighlighter(highlight.getStart(), highlight.getEnd(), textAttributes);
return;
}
}
final TextAttributes textAttributes = highlight.getTextAttributes(null);
addHighlighter(highlight.getStart(), highlight.getEnd(), textAttributes);
}
}
public void clearHyperlinks() {
myHighlighterToMessageInfoMap.clear();
myHighlighters.clear();
myLastIndex = NO_INDEX;
}
@@ -171,12 +246,25 @@ public class EditorHyperlinkSupport {
if (result == null) {
result = predefinedMessageFilter.applyFilter(text, endOffset);
}
if (result != null && result.hyperlinkInfo != null) {
addHyperlink(result.highlightStartOffset, result.highlightEndOffset, result.highlightAttributes, result.hyperlinkInfo);
if (result != null) {
if (result.hyperlinkInfo != null) {
addHyperlink(result.highlightStartOffset, result.highlightEndOffset, result.highlightAttributes, result.hyperlinkInfo);
} else if (result.highlightAttributes != null) {
addHighlighter(result.highlightStartOffset, result.highlightEndOffset, result.highlightAttributes);
}
}
}
}
private void addHighlighter(int highlightStartOffset, int highlightEndOffset, TextAttributes highlightAttributes) {
final RangeHighlighter highlighter = myEditor.getMarkupModel().addRangeHighlighter(highlightStartOffset,
highlightEndOffset,
HIGHLIGHT_LAYER,
highlightAttributes,
HighlighterTargetArea.EXACT_RANGE);
myHighlighters.add(highlighter);
}
private static TextAttributes getHyperlinkAttributes() {
return EditorColorsManager.getInstance().getGlobalScheme().getAttributes(CodeInsightColors.HYPERLINK_ATTRIBUTES);
}
@@ -220,6 +308,7 @@ public class EditorHyperlinkSupport {
}, i, ranges.size());
}
// todo fix link followed here!
private static void linkFollowed(Editor editor, Collection<RangeHighlighter> ranges, final RangeHighlighter link) {
MarkupModelEx markupModel = (MarkupModelEx)editor.getMarkupModel();
for (RangeHighlighter range : ranges) {
@@ -237,6 +326,7 @@ public class EditorHyperlinkSupport {
attributes.setEffectType(oldAttributes.getEffectType());
attributes.setEffectColor(oldAttributes.getEffectColor());
attributes.setForegroundColor(oldAttributes.getForegroundColor());
attributes.setBackgroundColor(oldAttributes.getBackgroundColor());
markupModel.setRangeHighlighterAttributes(range, attributes);
}
}
@@ -384,19 +384,20 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
if (clip.height == 0) return;
final Rectangle componentBounds = c.getBounds();
final TextRange docRange = TextRange.create(0, getEditor().getDocument().getTextLength());
if (myCachedTrack == null || myCachedTrack.getHeight() != componentBounds.getHeight()) {
myCachedTrack = new BufferedImage(componentBounds.width, componentBounds.height, BufferedImage.TYPE_INT_ARGB);
myDirtyRange = TextRange.create(0, getEditor().getDocument().getTextLength());
myDirtyRange = docRange;
paintTrackBasement(myCachedTrack.getGraphics(), new Rectangle(0, 0, componentBounds.width, componentBounds.height));
}
if (myDirtyRange != null) {
final Graphics2D imageGraphics = myCachedTrack.createGraphics();
((ApplicationImpl)ApplicationManager.getApplication()).editorPaintStart();
try {
myDirtyRange = myDirtyRange.intersection(docRange);
repaint(imageGraphics, componentBounds.width, ERROR_ICON_WIDTH - 1, myDirtyRange.getStartOffset(), myDirtyRange.getEndOffset());
myDirtyRange = null;
}
@@ -119,5 +119,6 @@
<extensionPoint name="xmlRpcHandler" beanClass="com.intellij.ide.XmlRpcHandlerBean"/>
<extensionPoint name="editorHighlighterProvider" beanClass="com.intellij.openapi.fileTypes.FileTypeExtensionPoint"/>
<extensionPoint name="fileDocumentManagerListener" interface="com.intellij.openapi.fileEditor.FileDocumentManagerListener"/>
<extensionPoint name="fileDocumentManagerListener" interface="com.intellij.openapi.fileEditor.FileDocumentManagerListener"/>
<extensionPoint name="exceptionFilter" interface="com.intellij.execution.filters.ExceptionFilterFactory"/>
</extensionPoints>
@@ -226,4 +226,7 @@
<projectService serviceInterface="com.intellij.openapi.wm.impl.ProjectFrameBounds"
serviceImplementation="com.intellij.openapi.wm.impl.ProjectFrameBounds"/>
<exceptionFilter implementation="com.intellij.execution.filters.ExceptionBaseFilterFactory"/>
<exceptionFilter implementation="com.intellij.openapi.vcs.contentAnnotation.VcsContentAnnotationExceptionFilterFactory"/>
</extensions>
@@ -106,5 +106,10 @@
<component><interface-class>com.intellij.openapi.vcs.impl.VcsBaseContentProvider</interface-class>
<implementation-class>com.intellij.openapi.vcs.impl.VcsFileStatusProvider</implementation-class>
</component>
<component><interface-class>com.intellij.openapi.vcs.contentAnnotation.VcsContentAnnotationSettings</interface-class>
<implementation-class>com.intellij.openapi.vcs.contentAnnotation.VcsContentAnnotationSettings</implementation-class>
</component>
<component><interface-class>com.intellij.openapi.vcs.contentAnnotation.VcsContentAnnotation</interface-class>
<implementation-class>com.intellij.openapi.vcs.contentAnnotation.VcsContentAnnotationImpl</implementation-class></component>
</project-components>
</components>
@@ -19,4 +19,6 @@ public interface UpToDateLineNumberProvider {
int ABSENT_LINE_NUMBER = -1;
int getLineNumber(int currentNumber);
boolean isLineChanged(int currentNumber);
boolean isRangeChanged(final int start, final int end);
}
@@ -0,0 +1,43 @@
/*
* 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.vcs;
import com.intellij.ui.SimpleTextAttributes;
/**
* Created by IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 8/3/11
* Time: 12:56 PM
* To change this template use File | Settings | File Templates.
*/
public class RichTextItem {
private final String myText;
private final SimpleTextAttributes myTextAttributes;
public RichTextItem(String text, SimpleTextAttributes textAttributes) {
myText = text;
myTextAttributes = textAttributes;
}
public String getText() {
return myText;
}
public SimpleTextAttributes getTextAttributes() {
return myTextAttributes;
}
}
@@ -19,6 +19,7 @@ import com.intellij.openapi.vcs.history.VcsFileRevision;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import org.jetbrains.annotations.Nullable;
import java.util.Date;
import java.util.List;
/**
@@ -81,6 +82,9 @@ public interface FileAnnotation {
@Nullable
VcsRevisionNumber getLineRevisionNumber(int lineNumber);
@Nullable
Date getLineDate(int lineNumber);
/**
* Get revision number for the line.
*/
@@ -150,4 +150,12 @@ public abstract class ChangeListManager implements ChangeListModification {
public abstract void letGo();
public abstract String isFreezed();
public abstract boolean isFreezedWithNotification(@Nullable String modalTitle);
public static boolean isFileChanged(final Project project, final VirtualFile vf) {
FileStatus status = getInstance(project).getStatus(vf);
if (status == null || FileStatus.NOT_CHANGED.equals(status) || FileStatus.UNKNOWN.equals(status) || FileStatus.IGNORED.equals(status)) {
return false;
}
return true;
}
}
@@ -0,0 +1,67 @@
/*
* 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.vcs.contentAnnotation;
import com.intellij.openapi.util.Getter;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vcs.RichTextItem;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* Created by IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 8/3/11
* Time: 12:50 PM
*/
public interface VcsContentAnnotation {
boolean fileRecentlyChanged(final VirtualFile vf);
boolean intervalRecentlyChanged(VirtualFile file, final TextRange lineInterval);
@Nullable
Details annotateLine(final VirtualFile vf, final Getter<TextRange> enclosingRange, final int lineNumber);
class Details {
private final boolean myLineChanged;
// meaningful enclosing structure
private final boolean myMethodChanged;
private final boolean myFileChanged;
@Nullable
private final List<RichTextItem> myDetails;
public Details(boolean lineChanged, boolean methodChanged, boolean fileChanged, List<RichTextItem> details) {
myLineChanged = lineChanged;
myMethodChanged = methodChanged;
myFileChanged = fileChanged;
myDetails = details;
}
public boolean isLineChanged() {
return myLineChanged;
}
public boolean isMethodChanged() {
return myMethodChanged;
}
public boolean isFileChanged() {
return myFileChanged;
}
}
}
@@ -0,0 +1,109 @@
/*
* 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.vcs.contentAnnotation;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Getter;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.annotate.FileAnnotation;
import com.intellij.openapi.vcs.diff.DiffMixin;
import com.intellij.openapi.vcs.history.VcsRevisionDescription;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.Nullable;
import java.util.Date;
/**
* Created by IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 8/3/11
* Time: 1:04 PM
*/
public class VcsContentAnnotationImpl implements VcsContentAnnotation {
private final Project myProject;
private final VcsContentAnnotationSettings mySettings;
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.contentAnnotation.VcsContentAnnotationImpl");
public static VcsContentAnnotation getInstance(final Project project) {
return ServiceManager.getService(project, VcsContentAnnotation.class);
}
public VcsContentAnnotationImpl(Project project, VcsContentAnnotationSettings settings) {
myProject = project;
mySettings = settings;
}
@Override
public boolean fileRecentlyChanged(VirtualFile vf) {
final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject);
final AbstractVcs vcs = vcsManager.getVcsFor(vf);
if (vcs == null) return false;
if (vcs.getDiffProvider() instanceof DiffMixin) {
final VcsRevisionDescription description = ((DiffMixin)vcs.getDiffProvider()).getCurrentRevisionDescription(vf);
final Date date = description.getRevisionDate();
return isRecent(date);
}
return false;
}
private boolean isRecent(Date date) {
return date.getTime() > (System.currentTimeMillis() - mySettings.getLimit());
}
@Override
public boolean intervalRecentlyChanged(VirtualFile file, TextRange lineInterval) {
final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject);
final AbstractVcs vcs = vcsManager.getVcsFor(file);
if (vcs == null) return false;
final FileAnnotation fileAnnotation;
try {
fileAnnotation = vcs.getCachingAnnotationProvider().annotate(file);
}
catch (VcsException e) {
LOG.info(e);
return false;
}
for (int i = lineInterval.getStartOffset(); i <= lineInterval.getEndOffset(); i++) {
Date lineDate = fileAnnotation.getLineDate(i);
if (lineDate != null && isRecent(lineDate)) return true;
}
return false;
}
@Nullable
@Override
public Details annotateLine(final VirtualFile vf, final Getter<TextRange> enclosingRange, final int lineNumber) {
final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject);
final AbstractVcs vcs = vcsManager.getVcsFor(vf);
if (vcs == null) return null;
if (vcs.getDiffProvider() instanceof DiffMixin) {
boolean fileRecent = false;
final VcsRevisionDescription description = ((DiffMixin)vcs.getDiffProvider()).getCurrentRevisionDescription(vf);
final Date date = description.getRevisionDate();
if (isRecent(date)) {
fileRecent = true;
enclosingRange.get();
}
return new Details(false, false, fileRecent, null);
}
return null;
}
}
@@ -0,0 +1,81 @@
/*
* 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.vcs.contentAnnotation;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.project.Project;
/**
* Created by IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 8/3/11
* Time: 1:13 PM
*/
@State(
name = "VcsContentAnnotationSettings",
storages = {@Storage( file = "$WORKSPACE_FILE$")})
public class VcsContentAnnotationSettings implements PersistentStateComponent<VcsContentAnnotationSettings.State> {
// approx
public static final int ourMaxDays = 31;
public final static long ourAbsoluteLimit = ourMaxDays * 24 * 60 * 60 * 1000L;
private State myState = new State();
{
myState.myLimit = ourAbsoluteLimit;
}
public static VcsContentAnnotationSettings getInstance(final Project project) {
return ServiceManager.getService(project, VcsContentAnnotationSettings.class);
}
public static class State {
public boolean myShow = true;
public long myLimit;
}
@Override
public State getState() {
return myState;
}
@Override
public void loadState(State state) {
myState = state;
}
public long getLimit() {
return myState.myLimit;
}
public long getLimitDays() {
return myState.myLimit / (24 * 60 * 60 * 1000L);
}
public void setLimit(long limit) {
myState.myLimit = limit * 24 * 60 * 60 * 1000L;
}
public boolean isShow() {
return myState.myShow;
}
public void setShow(final boolean value) {
myState.myShow = value;
}
}
@@ -188,7 +188,7 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware, Ann
final AbstractVcs vcs) {
final String upToDateContent = fileAnnotation.getAnnotatedContent();
final UpToDateLineNumberProvider getUpToDateLineNumber = new UpToDateLineNumberProviderImpl(editor.getDocument(), project, upToDateContent);
final UpToDateLineNumberProvider getUpToDateLineNumber = new UpToDateLineNumberProviderImpl(editor.getDocument(), project);
editor.getGutter().closeAllAnnotations();
// be careful, not proxies but original items are put there (since only their presence not behaviour is important)
@@ -0,0 +1,106 @@
/*
* 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.vcs.configurable;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vcs.contentAnnotation.VcsContentAnnotationSettings;
import org.jetbrains.annotations.Nls;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Created by IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 8/4/11
* Time: 2:05 PM
*/
public class VcsContentAnnotationConfigurable implements Configurable {
private final Project myProject;
private JCheckBox myHighlightRecentlyChanged;
private JSpinner myHighlightInterval;
public VcsContentAnnotationConfigurable(Project project) {
myProject = project;
}
@Nls
@Override
public String getDisplayName() {
return "Show recently changed";
}
@Override
public Icon getIcon() {
return null;
}
@Override
public String getHelpTopic() {
return null;
}
@Override
public JComponent createComponent() {
JPanel wrapper = new JPanel(new FlowLayout(FlowLayout.LEFT));
myHighlightRecentlyChanged = new JCheckBox("Show changed in last");
myHighlightRecentlyChanged.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
myHighlightInterval = new JSpinner(new SpinnerNumberModel(1, 1, VcsContentAnnotationSettings.ourMaxDays, 1));
wrapper.add(myHighlightRecentlyChanged);
wrapper.add(myHighlightInterval);
wrapper.add(new JLabel("days"));
myHighlightRecentlyChanged.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
myHighlightInterval.setEnabled(myHighlightRecentlyChanged.isSelected());
}
});
return wrapper;
}
@Override
public boolean isModified() {
VcsContentAnnotationSettings settings = VcsContentAnnotationSettings.getInstance(myProject);
if (myHighlightRecentlyChanged.isSelected() != settings.isShow()) return true;
if (! Comparing.equal(myHighlightInterval.getValue(), settings.getLimitDays())) return true;
return false;
}
@Override
public void apply() throws ConfigurationException {
VcsContentAnnotationSettings settings = VcsContentAnnotationSettings.getInstance(myProject);
settings.setShow(myHighlightRecentlyChanged.isSelected());
settings.setLimit(((Number) myHighlightInterval.getValue()).intValue());
}
@Override
public void reset() {
VcsContentAnnotationSettings settings = VcsContentAnnotationSettings.getInstance(myProject);
myHighlightRecentlyChanged.setSelected(settings.isShow());
myHighlightInterval.setValue(settings.getLimitDays());
myHighlightInterval.setEnabled(myHighlightRecentlyChanged.isSelected());
}
@Override
public void disposeUIResources() {
}
}
@@ -18,6 +18,7 @@ package com.intellij.openapi.vcs.configurable;
import com.intellij.CommonBundle;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.AbstractVcs;
@@ -134,6 +135,7 @@ public class VcsDirectoryConfigurationPanel extends PanelWithButtons implements
private JButton myEditButton;
private JButton myRemoveButton;
private final Map<String, VcsDescriptor> myAllVcss;
private VcsContentAnnotationConfigurable myRecentlyChangedConfigurable;
private final boolean myIsDisabled;
public VcsDirectoryConfigurationPanel(final Project project) {
@@ -147,6 +149,7 @@ public class VcsDirectoryConfigurationPanel extends PanelWithButtons implements
}
myDirectoryMappingTable = new TableView<VcsDirectoryMapping>();
initPanel();
initializeModel();
final JComboBox comboBox = myVcsComboBox.getComboBox();
@@ -172,7 +175,6 @@ public class VcsDirectoryConfigurationPanel extends PanelWithButtons implements
updateButtons();
}
});
initPanel();
updateButtons();
if (myIsDisabled) {
myDirectoryMappingTable.setEnabled(false);
@@ -187,6 +189,8 @@ public class VcsDirectoryConfigurationPanel extends PanelWithButtons implements
}
myModel = new ListTableModel<VcsDirectoryMapping>(new ColumnInfo[]{DIRECTORY, VCS_SETTING}, mappings, 0);
myDirectoryMappingTable.setModel(myModel);
myRecentlyChangedConfigurable.reset();
}
private void updateButtons() {
@@ -273,19 +277,26 @@ public class VcsDirectoryConfigurationPanel extends PanelWithButtons implements
}
protected JComponent createMainComponent() {
return ScrollPaneFactory.createScrollPane(myDirectoryMappingTable);
JPanel panel = new JPanel(new BorderLayout());
final JScrollPane scroll = ScrollPaneFactory.createScrollPane(myDirectoryMappingTable);
panel.add(scroll, BorderLayout.CENTER);
myRecentlyChangedConfigurable = new VcsContentAnnotationConfigurable(myProject);
panel.add(myRecentlyChangedConfigurable.createComponent(), BorderLayout.SOUTH);
return panel;
}
public void reset() {
initializeModel();
}
public void apply() {
public void apply() throws ConfigurationException {
myVcsManager.setDirectoryMappings(myModel.getItems());
myRecentlyChangedConfigurable.apply();
initializeModel();
}
public boolean isModified() {
if (myRecentlyChangedConfigurable.isModified()) return true;
return !myModel.getItems().equals(myVcsManager.getDirectoryMappings());
}
@@ -29,21 +29,55 @@ import java.util.List;
public class UpToDateLineNumberProviderImpl implements UpToDateLineNumberProvider {
private final Document myDocument;
private final Project myProject;
private final String myUpToDateContent;
private final LineStatusTrackerManagerI myLineStatusTrackerManagerI;
public UpToDateLineNumberProviderImpl(Document document, Project project, String upToDateContent) {
public UpToDateLineNumberProviderImpl(Document document, Project project) {
myDocument = document;
myProject = project;
myUpToDateContent = upToDateContent;
myLineStatusTrackerManagerI = LineStatusTrackerManager.getInstance(myProject);
}
public int getLineNumber(int currentNumber) {
LineStatusTracker tracker = LineStatusTrackerManager.getInstance(myProject).getLineStatusTracker(myDocument);
LineStatusTracker tracker = myLineStatusTrackerManagerI.getLineStatusTracker(myDocument);
if (tracker == null) {
return currentNumber;
}
return calcLineNumber(tracker, currentNumber);
}
public boolean isRangeChanged(final int start, final int end) {
LineStatusTracker tracker = LineStatusTrackerManager.getInstance(myProject).getLineStatusTracker(myDocument);
if (tracker == null) {
return false;
}
for (Range range : tracker.getRanges()) {
if (lineInRange(range, start) || lineInRange(range, end)) {
return true;
}
if (range.getOffset1() > start) {
return range.getOffset1() < end;
}
}
return false;
}
private static boolean lineInRange(final Range range, final int currentNumber) {
return range.getOffset1() <= currentNumber && range.getOffset2() >= currentNumber;
}
@Override
public boolean isLineChanged(int currentNumber) {
LineStatusTracker tracker = LineStatusTrackerManager.getInstance(myProject).getLineStatusTracker(myDocument);
if (tracker == null) {
return false;
}
for (Range range : tracker.getRanges()) {
if (range.getOffset1() <= currentNumber && range.getOffset2() >= currentNumber) {
return true;
}
}
return false;
}
private boolean endsWithSeparator(final CharSequence string) {
if ((string == null) || (string.length() == 0)) {
@@ -155,6 +155,14 @@ public class CvsFileAnnotation implements FileAnnotation{
return null;
}
@Override
public Date getLineDate(int lineNumber) {
if (lineNumber < 0 || lineNumber >= myAnnotations.length) {
return null;
}
return myAnnotations[lineNumber].getDate();
}
public VcsRevisionNumber originalRevision(int lineNumber) {
return getLineRevisionNumber(lineNumber);
}
-1
View File
@@ -118,7 +118,6 @@
serviceImplementation="git4idea.DialogManager"/>
<projectService serviceInterface="git4idea.history.wholeTree.GitLogSettings"
serviceImplementation="git4idea.history.wholeTree.GitLogSettings"/>
<applicationService
serviceInterface="git4idea.config.GitVcsApplicationSettings"
serviceImplementation="git4idea.config.GitVcsApplicationSettings"/>
@@ -237,13 +237,26 @@ public class GitFileAnnotation implements FileAnnotation {
* {@inheritDoc}
*/
public VcsRevisionNumber getLineRevisionNumber(final int lineNumber) {
if (myLines.size() <= lineNumber || lineNumber < 0 || myLines.get(lineNumber) == null) {
if (lineNumberCheck(lineNumber)) {
return null;
}
final LineInfo lineInfo = myLines.get(lineNumber);
return lineInfo == null ? null : lineInfo.getRevision();
}
private boolean lineNumberCheck(int lineNumber) {
return myLines.size() <= lineNumber || lineNumber < 0 || myLines.get(lineNumber) == null;
}
@Override
public Date getLineDate(int lineNumber) {
if (lineNumberCheck(lineNumber)) {
return null;
}
final LineInfo lineInfo = myLines.get(lineNumber);
return lineInfo == null ? null : lineInfo.getDate();
}
/**
* Get revision number for the line.
*/
@@ -287,7 +300,7 @@ public class GitFileAnnotation implements FileAnnotation {
}
public String getValue(int lineNumber) {
if (myLines.size() <= lineNumber || lineNumber < 0 || myLines.get(lineNumber) == null) {
if (lineNumberCheck(lineNumber)) {
return "";
}
else {
@@ -22,6 +22,7 @@ import org.apache.commons.lang.StringUtils;
import org.zmlx.hg4idea.HgFile;
import org.zmlx.hg4idea.HgFileRevision;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
@@ -99,6 +100,16 @@ public class HgAnnotation implements FileAnnotation {
return annotationLine.getVcsRevisionNumber();
}
@Override
public Date getLineDate(int lineNumber) {
if (lineNumber >= lines.size() || lineNumber < 0) {
return null;
}
//lines.get(lineNumber).get(HgAnnotation.FIELD.DATE)
// todo : parse date
return null;
}
public List<VcsFileRevision> getRevisions() {
List<VcsFileRevision> result = new LinkedList<VcsFileRevision>();
result.addAll(vcsFileRevisions);
@@ -27,6 +27,7 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.ui.content.Content;
import com.intellij.ui.content.ContentFactory;
import com.intellij.ui.content.MessageView;
@@ -34,6 +35,7 @@ import org.jetbrains.idea.maven.execution.MavenRunnerParameters;
import org.jetbrains.idea.maven.execution.MavenRunnerSettings;
import org.jetbrains.idea.maven.utils.MavenUtil;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
public class MavenConsoleImpl extends MavenConsole {
@@ -73,10 +75,11 @@ public class MavenConsoleImpl extends MavenConsole {
public static TextConsoleBuilder createConsoleBuilder(Project project) {
TextConsoleBuilder builder = TextConsoleBuilderFactory.getInstance().createBuilder(project);
Filter[] filters = {new ExceptionFilter(project), new RegexpFilter(project, CONSOLE_FILTER_REGEXP)};
List<Filter> filters = ExceptionFilters.getFilters(GlobalSearchScope.allScope(project));
for (Filter filter : filters) {
builder.addFilter(filter);
}
builder.addFilter(new RegexpFilter(project, CONSOLE_FILTER_REGEXP));
return builder;
}
@@ -246,6 +246,16 @@ public class SvnFileAnnotation implements FileAnnotation {
return null;
}
@Override
public Date getLineDate(int lineNumber) {
if (myInfos.size() <= lineNumber || lineNumber < 0) {
return null;
}
final LineInfo info = myInfos.get(lineNumber);
if (info == null) return null;
return info.getDate();
}
public List<VcsFileRevision> getRevisions() {
final List<VcsFileRevision> result = new ArrayList<VcsFileRevision>(myRevisionMap.values());
Collections.sort(result, new Comparator<VcsFileRevision>() {