Merge remote-tracking branch 'origin/master' into develar/is

This commit is contained in:
Vladimir Krivosheev
2016-06-24 15:36:12 +02:00
111 changed files with 1518 additions and 1355 deletions
@@ -58,7 +58,7 @@ public class ConstructorInsertHandler implements InsertHandler<LookupElementDeco
boolean isAbstract = psiClass.hasModifierProperty(PsiModifier.ABSTRACT);
if (Lookup.REPLACE_SELECT_CHAR == context.getCompletionChar()) {
if (Lookup.REPLACE_SELECT_CHAR == context.getCompletionChar() && context.getOffsetMap().containsOffset(PARAM_LIST_START)) {
final int plStart = context.getOffset(PARAM_LIST_START);
final int plEnd = context.getOffset(PARAM_LIST_END);
if (plStart >= 0 && plEnd >= 0) {
@@ -1,109 +0,0 @@
/*
* Copyright 2000-2009 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.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.controlFlow.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.BitUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author ven
*/
public class RemoveRedundantElseAction extends PsiElementBaseIntentionAction {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.RemoveRedundantElseAction");
@Override
@NotNull
public String getText() {
return QuickFixBundle.message("remove.redundant.else.fix");
}
@Override
@NotNull
public String getFamilyName() {
return QuickFixBundle.message("remove.redundant.else.fix");
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
if (element instanceof PsiKeyword &&
element.getParent() instanceof PsiIfStatement &&
PsiKeyword.ELSE.equals(element.getText())) {
PsiIfStatement ifStatement = (PsiIfStatement)element.getParent();
if (ifStatement.getElseBranch() == null) return false;
PsiStatement thenBranch = ifStatement.getThenBranch();
if (thenBranch == null) return false;
PsiElement block = PsiTreeUtil.getParentOfType(ifStatement, PsiCodeBlock.class);
if (block != null) {
while (cantCompleteNormally(thenBranch, block)) {
thenBranch = getPrevThenBranch(thenBranch);
if (thenBranch == null) return true;
}
return false;
}
}
return false;
}
@Nullable
private static PsiStatement getPrevThenBranch(@NotNull PsiElement thenBranch) {
final PsiElement ifStatement = thenBranch.getParent();
final PsiElement parent = ifStatement.getParent();
if (parent instanceof PsiIfStatement && ((PsiIfStatement)parent).getElseBranch() == ifStatement) {
return ((PsiIfStatement)parent).getThenBranch();
}
return null;
}
private static boolean cantCompleteNormally(@NotNull PsiStatement thenBranch, PsiElement block) {
try {
ControlFlow controlFlow = ControlFlowFactory.getInstance(thenBranch.getProject()).getControlFlow(block, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance());
int startOffset = controlFlow.getStartOffset(thenBranch);
int endOffset = controlFlow.getEndOffset(thenBranch);
return startOffset != -1 && endOffset != -1 && !BitUtil.isSet(ControlFlowUtil.getCompletionReasons(controlFlow, startOffset, endOffset), ControlFlowUtil.NORMAL_COMPLETION_REASON);
}
catch (AnalysisCanceledException e) {
return false;
}
}
@Override
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return;
PsiIfStatement ifStatement = (PsiIfStatement)element.getParent();
LOG.assertTrue(ifStatement != null && ifStatement.getElseBranch() != null);
PsiStatement elseBranch = ifStatement.getElseBranch();
if (elseBranch instanceof PsiBlockStatement) {
PsiElement[] statements = ((PsiBlockStatement)elseBranch).getCodeBlock().getStatements();
if (statements.length > 0) {
ifStatement.getParent().addRangeAfter(statements[0], statements[statements.length-1], ifStatement);
}
} else {
ifStatement.getParent().addAfter(elseBranch, ifStatement);
}
ifStatement.getElseBranch().delete();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2016 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.
@@ -13,44 +13,43 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.daemon.quickFix;
package com.intellij.codeInspection.lambda;
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
import com.intellij.codeInspection.BaseJavaBatchLocalInspectionTool;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
/**
* User: anna
*/
public class RedundantLambdaParameterTypeIntention extends PsiElementBaseIntentionAction {
public static final Logger LOG = Logger.getInstance("#" + RedundantLambdaParameterTypeIntention.class.getName());
public class RedundantLambdaParameterTypeInspection extends BaseJavaBatchLocalInspectionTool {
public static final Logger LOG = Logger.getInstance("#" + RedundantLambdaParameterTypeInspection.class.getName());
@NotNull
@Override
public String getFamilyName() {
return "Remove redundant types";
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
return new JavaElementVisitor() {
@Override
public void visitParameterList(PsiParameterList parameterList) {
super.visitParameterList(parameterList);
if (isApplicable(parameterList)) {
holder.registerProblem(parameterList, "Remove redundant types", new LambdaParametersFix());
}
}
};
}
@NotNull
@Override
public String getText() {
return getFamilyName();
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
final PsiParameterList parameterList = PsiTreeUtil.getParentOfType(element, PsiParameterList.class);
if (parameterList == null) return false;
private static boolean isApplicable(@NotNull PsiParameterList parameterList) {
final PsiElement parent = parameterList.getParent();
if (!(parent instanceof PsiLambdaExpression)) return false;
final PsiLambdaExpression expression = (PsiLambdaExpression)parent;
@@ -73,9 +72,9 @@ public class RedundantLambdaParameterTypeIntention extends PsiElementBaseIntenti
final PsiTypeParameter[] typeParameters = method.getTypeParameters();
final PsiExpression[] arguments = ((PsiExpressionList)lambdaParent).getExpressions();
final JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(project);
final JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(parameterList.getProject());
arguments[idx] = javaPsiFacade.getElementFactory().createExpressionFromText(
"(" + StringUtil.join(expression.getParameterList().getParameters(), parameter -> parameter.getName(), ", ") + ") -> {}", expression);
"(" + StringUtil.join(expression.getParameterList().getParameters(), PsiParameter::getName, ", ") + ") -> {}", expression);
final PsiParameter[] methodParams = method.getParameterList().getParameters();
final PsiSubstitutor substitutor = javaPsiFacade.getResolveHelper()
.inferTypeArguments(typeParameters, methodParams, arguments, ((MethodCandidateInfo)resolveResult).getSiteSubstitutor(),
@@ -85,8 +84,7 @@ public class RedundantLambdaParameterTypeIntention extends PsiElementBaseIntenti
final PsiType psiType = substitutor.substitute(parameter);
if (psiType == null || dependsOnTypeParams(psiType, expression, parameter)) return false;
}
final PsiType paramType;
if (idx < methodParams.length) {
paramType = methodParams[idx].getType();
@@ -107,12 +105,6 @@ public class RedundantLambdaParameterTypeIntention extends PsiElementBaseIntenti
return false;
}
@Override
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(element, PsiLambdaExpression.class);
removeTypes(lambdaExpression);
}
private static void removeTypes(PsiLambdaExpression lambdaExpression) {
if (lambdaExpression != null) {
final PsiParameter[] parameters = lambdaExpression.getParameterList().getParameters();
@@ -121,7 +113,7 @@ public class RedundantLambdaParameterTypeIntention extends PsiElementBaseIntenti
text = parameters[0].getName();
}
else {
text = "(" + StringUtil.join(parameters, parameter -> parameter.getName(), ", ") + ")";
text = "(" + StringUtil.join(parameters, PsiParameter::getName, ", ") + ")";
}
final PsiLambdaExpression expression = (PsiLambdaExpression)JavaPsiFacade.getElementFactory(lambdaExpression.getProject())
.createExpressionFromText(text + "->{}", lambdaExpression);
@@ -135,4 +127,29 @@ public class RedundantLambdaParameterTypeIntention extends PsiElementBaseIntenti
return LambdaUtil.depends(type, new LambdaUtil.TypeParamsChecker(expr, PsiUtil
.resolveGenericsClassInType(LambdaUtil.getFunctionalInterfaceType(expr, false)).getElement()), param2Check);
}
private static class LambdaParametersFix implements LocalQuickFix {
@Nls
@NotNull
@Override
public String getName() {
return getFamilyName();
}
@Nls
@NotNull
@Override
public String getFamilyName() {
return "Remove redundant types";
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
final PsiElement parent = element.getParent();
if (parent instanceof PsiLambdaExpression) {
removeTypes((PsiLambdaExpression)parent);
}
}
}
}
@@ -19,13 +19,11 @@ import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.VirtualFileWithId;
import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
import com.intellij.psi.search.DelegatingGlobalSearchScope;
import com.intellij.psi.search.EverythingGlobalScope;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.stubsHierarchy.HierarchyService;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
@@ -33,17 +31,18 @@ import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.util.CachedValueBase;
import com.intellij.util.indexing.FileBasedIndex;
import com.intellij.util.indexing.FileBasedIndexImpl;
import org.jetbrains.annotations.NotNull;
import java.util.BitSet;
public class HierarchyServiceImpl extends HierarchyService {
private static final SingleClassHierarchy EMPTY_HIERARCHY = new SingleClassHierarchy(Symbol.ClassSymbol.EMPTY_ARRAY);
private final Project myProject;
private final ProjectFileIndex myFileIndex;
private final CachedValue<SingleClassHierarchy> myHierarchy;
public HierarchyServiceImpl(Project project) {
myProject = project;
myFileIndex = ProjectFileIndex.SERVICE.getInstance(project);
myHierarchy = CachedValuesManager.getManager(project).createCachedValue(
() -> CachedValueProvider.Result.create(buildHierarchy(), PsiModificationTracker.MODIFICATION_COUNT),
false);
@@ -69,38 +68,56 @@ public class HierarchyServiceImpl extends HierarchyService {
private SingleClassHierarchy buildHierarchy() {
Symbols symbols = new Symbols();
StubEnter stubEnter = new StubEnter(symbols);
IdSets idSets = IdSets.getIdSets(myProject);
loadUnits(false, symbols.myNameEnvironment, stubEnter);
loadUnits(idSets.libraryFiles, StubHierarchyIndex.BINARY_FILES, symbols.myNameEnvironment, stubEnter);
stubEnter.connect1();
loadUnits(true, symbols.myNameEnvironment, stubEnter);
loadUnits(idSets.sourceFiles, StubHierarchyIndex.SOURCE_FILES, symbols.myNameEnvironment, stubEnter);
stubEnter.connect2();
return symbols.createHierarchy();
}
private void loadUnits(boolean sourceMode, NameEnvironment names, StubEnter stubEnter) {
GlobalSearchScope scope = new DelegatingGlobalSearchScope(new EverythingGlobalScope(myProject)) {
@Override
public boolean contains(@NotNull VirtualFile file) {
return sourceMode ? myFileIndex.isInSourceContent(file) : myFileIndex.isInLibraryClasses(file);
}
};
private void loadUnits(BitSet files, int indexKey, NameEnvironment names, StubEnter stubEnter) {
ProgressIndicator indicator = ProgressIndicatorProvider.getGlobalProgressIndicator();
FileBasedIndex index = FileBasedIndex.getInstance();
for (String packageName : index.getAllKeys(StubHierarchyIndex.INDEX_ID, myProject)) {
QualifiedName pkg = StringUtil.isEmpty(packageName) ? null : names.fromString(packageName, true);
index.processValues(StubHierarchyIndex.INDEX_ID, packageName, null, new FileBasedIndex.ValueProcessor<IndexTree.Unit>() {
int count = 0;
@Override
public boolean process(VirtualFile file, IndexTree.Unit unit) {
if (indicator != null && ++count % 128 == 0) indicator.checkCanceled();
stubEnter.unitEnter(Translator.internNames(names, unit, ((VirtualFileWithId)file).getId(), pkg));
return true;
FileBasedIndexImpl index = (FileBasedIndexImpl)FileBasedIndex.getInstance();
index.processAllValues(StubHierarchyIndex.INDEX_ID, indexKey, myProject, new FileBasedIndexImpl.IdValueProcessor<IndexTree.Unit>() {
int count = 0;
@Override
public boolean process(int fileId, IndexTree.Unit unit) {
if (indicator != null && ++count % 128 == 0) indicator.checkCanceled();
if (files.get(fileId)) {
QualifiedName pkg = StringUtil.isEmpty(unit.myPackageId) ? null : names.fromString(unit.myPackageId, true);
stubEnter.unitEnter(Translator.internNames(names, unit, fileId, pkg));
}
}, scope);
}
return true;
}
});
}
private static class IdSets {
final BitSet sourceFiles = new BitSet();
final BitSet libraryFiles = new BitSet();
static IdSets getIdSets(@NotNull Project project) {
return CachedValuesManager.getManager(project).getCachedValue(project, () -> {
IdSets answer = new IdSets();
ProjectFileIndex index = ProjectFileIndex.SERVICE.getInstance(project);
FileBasedIndex.getInstance().iterateIndexableFiles(file -> {
if (!file.isDirectory() && file instanceof VirtualFileWithId) {
if (index.isInSourceContent(file)) {
answer.sourceFiles.set(((VirtualFileWithId) file).getId());
}
else if (index.isInLibraryClasses(file)) {
answer.libraryFiles.set(((VirtualFileWithId) file).getId());
}
}
return true;
}, project, ProgressIndicatorProvider.getGlobalProgressIndicator());
return CachedValueProvider.Result.create(answer, ProjectRootManager.getInstance(project), VirtualFileManager.VFS_STRUCTURE_MODIFICATIONS);
});
}
}
}
@@ -18,7 +18,6 @@ package com.intellij.psi.stubsHierarchy.impl;
import com.intellij.ide.highlighter.JavaClassFileType;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiNameHelper;
@@ -39,7 +38,10 @@ import com.intellij.util.indexing.FileContent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class JavaStubIndexer extends StubHierarchyIndexer {
@@ -61,7 +63,7 @@ public class JavaStubIndexer extends StubHierarchyIndexer {
@Nullable
@Override
public List<Pair<String, Unit>> indexFile(@NotNull FileContent content) {
public Unit indexFile(@NotNull FileContent content) {
Stub stubTree = StubTreeBuilder.buildStubTree(content);
if (!(stubTree instanceof PsiJavaFileStub)) return null;
@@ -87,7 +89,7 @@ public class JavaStubIndexer extends StubHierarchyIndexer {
ClassDecl[] classes = classList.isEmpty() ? ClassDecl.EMPTY_ARRAY : classList.toArray(new ClassDecl[classList.size()]);
Import[] imports = importList.isEmpty() ? Import.EMPTY_ARRAY : importList.toArray(new Import[importList.size()]);
byte type = javaFileStub.isCompiled() ? IndexTree.BYTECODE : IndexTree.JAVA;
return Collections.singletonList(Pair.create(javaFileStub.getPackageName(), new Unit(type, imports, classes)));
return new Unit(javaFileStub.getPackageName(), type, imports, classes);
}
@Nullable
@@ -18,47 +18,42 @@ package com.intellij.psi.stubsHierarchy.impl;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
import com.intellij.psi.impl.java.stubs.index.JavaUnitDescriptor;
import com.intellij.psi.stubsHierarchy.StubHierarchyIndexer;
import com.intellij.util.indexing.*;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.EnumeratorStringDescriptor;
import com.intellij.util.io.EnumeratorIntegerDescriptor;
import com.intellij.util.io.KeyDescriptor;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.Arrays;
import java.util.Collections;
/**
* @author peter
*/
public class StubHierarchyIndex extends FileBasedIndexExtension<String, IndexTree.Unit> implements PsiDependentIndex {
static final ID<String, IndexTree.Unit> INDEX_ID = ID.create("jvm.hierarchy");
public class StubHierarchyIndex extends FileBasedIndexExtension<Integer, IndexTree.Unit> implements PsiDependentIndex {
public static final int BINARY_FILES = 0;
public static final int SOURCE_FILES = 1;
static final ID<Integer, IndexTree.Unit> INDEX_ID = ID.create("jvm.hierarchy");
private static final StubHierarchyIndexer[] ourIndexers = StubHierarchyIndexer.EP_NAME.getExtensions();
@NotNull
@Override
public ID<String, IndexTree.Unit> getName() {
public ID<Integer, IndexTree.Unit> getName() {
return INDEX_ID;
}
@NotNull
@Override
public DataIndexer<String, IndexTree.Unit, FileContent> getIndexer() {
public DataIndexer<Integer, IndexTree.Unit, FileContent> getIndexer() {
return inputData -> {
for (StubHierarchyIndexer indexer : ourIndexers) {
List<Pair<String, IndexTree.Unit>> pairs = indexer.handlesFile(inputData.getFile()) ? indexer.indexFile(inputData) : null;
if (pairs != null && !pairs.isEmpty()) {
Map<String, IndexTree.Unit> answer = new HashMap<>();
for (Pair<String, IndexTree.Unit> entry : pairs) {
if (entry.second.myDecls.length > 0) {
answer.put(StringUtil.notNullize(entry.first), entry.second);
}
}
return answer;
IndexTree.Unit unit = indexer.handlesFile(inputData.getFile()) ? indexer.indexFile(inputData) : null;
if (unit != null && unit.myDecls.length > 0) {
return Collections.singletonMap(inputData.getFile().getFileType().isBinary() ? BINARY_FILES : SOURCE_FILES, unit);
}
}
return Collections.emptyMap();
@@ -67,8 +62,8 @@ public class StubHierarchyIndex extends FileBasedIndexExtension<String, IndexTre
@NotNull
@Override
public KeyDescriptor<String> getKeyDescriptor() {
return EnumeratorStringDescriptor.INSTANCE;
public KeyDescriptor<Integer> getKeyDescriptor() {
return EnumeratorIntegerDescriptor.INSTANCE;
}
@NotNull
@@ -79,7 +74,7 @@ public class StubHierarchyIndex extends FileBasedIndexExtension<String, IndexTre
@Override
public int getVersion() {
return IndexTree.STUB_HIERARCHY_ENABLED ? 2 + Arrays.stream(ourIndexers).mapToInt(StubHierarchyIndexer::getVersion).sum() : 0;
return IndexTree.STUB_HIERARCHY_ENABLED ? 3 + Arrays.stream(ourIndexers).mapToInt(StubHierarchyIndexer::getVersion).sum() : 0;
}
@NotNull
@@ -29,6 +29,7 @@ public class JavaUnitDescriptor implements DataExternalizer<IndexTree.Unit> {
@Override
public void save(@NotNull DataOutput out, IndexTree.Unit value) throws IOException {
out.writeUTF(value.myPackageId);
out.writeByte(value.myUnitType);
if (value.myUnitType != IndexTree.BYTECODE) {
DataInputOutputUtil.writeINT(out, value.imports.length);
@@ -75,6 +76,7 @@ public class JavaUnitDescriptor implements DataExternalizer<IndexTree.Unit> {
@Override
public IndexTree.Unit read(@NotNull DataInput in) throws IOException {
String pid = in.readUTF();
byte type = in.readByte();
IndexTree.Import[] imports = IndexTree.Import.EMPTY_ARRAY;
if (type != IndexTree.BYTECODE) {
@@ -87,7 +89,7 @@ public class JavaUnitDescriptor implements DataExternalizer<IndexTree.Unit> {
for (int i = 0; i < classes.length; i++) {
classes[i] = readClassDecl(in);
}
return new IndexTree.Unit(type, imports, classes);
return new IndexTree.Unit(pid, type, imports, classes);
}
private IndexTree.ClassDecl readClassDecl(DataInput in) throws IOException {
@@ -16,15 +16,12 @@
package com.intellij.psi.stubsHierarchy;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
import com.intellij.util.indexing.FileContent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author peter
*/
@@ -37,7 +34,7 @@ public abstract class StubHierarchyIndexer {
* @return a list of pairs <packageName, compilation unit> for a specified file content
*/
@Nullable
public abstract List<Pair<String, IndexTree.Unit>> indexFile(@NotNull FileContent content);
public abstract IndexTree.Unit indexFile(@NotNull FileContent content);
public abstract boolean handlesFile(@NotNull VirtualFile file);
@@ -15,11 +15,15 @@
*/
package com.intellij.psi.util;
import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.containers.HashSet;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.LinkedHashSet;
import java.util.List;
@@ -111,6 +115,7 @@ public class PsiSuperMethodUtil {
public static Map<MethodSignature, Set<PsiMethod>> collectOverrideEquivalents(@NotNull PsiClass aClass) {
final Map<MethodSignature, Set<PsiMethod>> overrideEquivalent =
new THashMap<MethodSignature, Set<PsiMethod>>(MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY);
final GlobalSearchScope resolveScope = aClass.getResolveScope();
PsiClass[] supers = aClass.getSupers();
for (int i = 0; i < supers.length; i++) {
PsiClass superClass = supers[i];
@@ -122,10 +127,12 @@ public class PsiSuperMethodUtil {
if (subType) continue;
final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, aClass, PsiSubstitutor.EMPTY);
for (HierarchicalMethodSignature hms : superClass.getVisibleSignatures()) {
final PsiMethod method = hms.getMethod();
PsiMethod method = hms.getMethod();
if (MethodSignatureUtil.findMethodBySignature(aClass, method.getSignature(superClassSubstitutor), false) != null) continue;
final PsiClass containingClass = method.getContainingClass();
final PsiClass containingClass = mapClass(method.getContainingClass(), resolveScope);
if (containingClass == null) continue;
method = containingClass.findMethodBySignature(method, false);
if (method == null) continue;
final PsiSubstitutor containingClassSubstitutor = TypeConversionUtil.getClassSubstitutor(containingClass, aClass, PsiSubstitutor.EMPTY);
if (containingClassSubstitutor == null) continue;
final PsiSubstitutor finalSubstitutor =
@@ -141,4 +148,30 @@ public class PsiSuperMethodUtil {
}
return overrideEquivalent;
}
@Nullable
public static PsiClass mapClass(PsiClass psiClass, final GlobalSearchScope resolveScope) {
if (psiClass == null) return null;
String qualifiedName = psiClass.getQualifiedName();
if (qualifiedName == null) {
return psiClass;
}
PsiFile file = psiClass.getContainingFile();
if (file == null || !file.getViewProvider().isPhysical()) {
return psiClass;
}
final VirtualFile vFile = file.getVirtualFile();
if (vFile == null) {
return psiClass;
}
final FileIndexFacade index = FileIndexFacade.getInstance(file.getProject());
if (!index.isInSource(vFile) && !index.isInLibrarySource(vFile) && !index.isInLibraryClasses(vFile)) {
return psiClass;
}
return JavaPsiFacade.getInstance(psiClass.getProject()).findClass(qualifiedName, resolveScope);
}
}
@@ -15,11 +15,10 @@
*/
package com.intellij.psi.impl;
import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiSuperMethodUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
@@ -56,7 +55,7 @@ class TypeCorrector extends PsiTypeMapper {
final PsiClassType.ClassResolveResult classResolveResult = classType.resolveGenerics();
final PsiClass psiClass = classResolveResult.getElement();
if (psiClass != null && classResolveResult.getSubstitutor() == PsiSubstitutor.EMPTY) {
final PsiClass mappedClass = mapClass(psiClass);
final PsiClass mappedClass = PsiSuperMethodUtil.mapClass(psiClass, myResolveScope);
if (mappedClass == null || mappedClass == psiClass) return (T) classType;
}
}
@@ -79,7 +78,7 @@ class TypeCorrector extends PsiTypeMapper {
PsiUtilCore.ensureValid(psiClass);
final PsiClass mappedClass = mapClass(psiClass);
final PsiClass mappedClass = PsiSuperMethodUtil.mapClass(psiClass, myResolveScope);
if (mappedClass == null) return classType;
PsiClassType mappedType = new PsiCorrectedClassType(classType.getLanguageLevel(),
@@ -89,31 +88,6 @@ class TypeCorrector extends PsiTypeMapper {
return mappedType;
}
@Nullable
private PsiClass mapClass(@NotNull PsiClass psiClass) {
String qualifiedName = psiClass.getQualifiedName();
if (qualifiedName == null) {
return psiClass;
}
PsiFile file = psiClass.getContainingFile();
if (file == null || !file.getViewProvider().isPhysical()) {
return psiClass;
}
final VirtualFile vFile = file.getVirtualFile();
if (vFile == null) {
return psiClass;
}
final FileIndexFacade index = FileIndexFacade.getInstance(file.getProject());
if (!index.isInSource(vFile) && !index.isInLibrarySource(vFile) && !index.isInLibraryClasses(vFile)) {
return psiClass;
}
return JavaPsiFacade.getInstance(psiClass.getProject()).findClass(qualifiedName, myResolveScope);
}
@NotNull
private PsiSubstitutor mapSubstitutor(PsiClass originalClass, PsiClass mappedClass, PsiSubstitutor substitutor) {
PsiTypeParameter[] typeParameters = mappedClass.getTypeParameters();
@@ -17,6 +17,9 @@ package com.intellij.psi.impl.java.stubs.hierarchy;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
@@ -37,11 +40,13 @@ public class IndexTree {
public static final byte GROOVY = 2;
public static class Unit {
@NotNull public final String myPackageId;
public final byte myUnitType;
public final Import[] imports;
public final ClassDecl[] myDecls;
public Unit(byte unitType, Import[] imports, ClassDecl[] decls) {
public Unit(@Nullable String packageId, byte unitType, Import[] imports, ClassDecl[] decls) {
this.myPackageId = StringUtil.notNullize(packageId);
this.myUnitType = unitType;
this.imports = imports;
this.myDecls = decls;
@@ -54,6 +59,8 @@ public class IndexTree {
Unit unit = (Unit)o;
if (myUnitType != unit.myUnitType) return false;
if (!myPackageId.equals(unit.myPackageId)) return false;
if (!Arrays.equals(imports, unit.imports)) return false;
if (!Arrays.equals(myDecls, unit.myDecls)) return false;
@@ -62,7 +69,14 @@ public class IndexTree {
@Override
public int hashCode() {
return Arrays.hashCode(myDecls);
int hash = myUnitType * 31 + myPackageId.hashCode();
for (ClassDecl decl : myDecls) {
String name = decl.myName;
if (name != null) {
return hash * 31 + name.hashCode();
}
}
return hash;
}
}
@@ -237,9 +237,7 @@ public class PsiMethodCallExpressionImpl extends ExpressionPsiElement implements
PsiType ret,
JavaResolveResult result,
LanguageLevel languageLevel) {
PsiSubstitutor substitutor = result instanceof MethodCandidateInfo && !PsiPolyExpressionUtil.isMethodCallTypeDependsOnInference(call, method)
? ((MethodCandidateInfo)result).getSiteSubstitutor()
: result.getSubstitutor();
PsiSubstitutor substitutor = result.getSubstitutor();
PsiType substitutedReturnType = substitutor.substitute(ret);
if (substitutedReturnType == null) {
return TypeConversionUtil.erasure(ret);
@@ -1,13 +0,0 @@
// "Remove redundant 'else'" "true"
class a {
void foo() {
int a = 0;
int b = 0;
if (a != b) {
return;
}
a = b;
a++;
}
}
@@ -1,14 +0,0 @@
// "Remove redundant 'else'" "true"
class a {
void foo() {
int a = 0;
int b = 0;
if (a != b) {
return;
} e<caret>lse {
a = b;
}
a++;
}
}
@@ -1,15 +0,0 @@
// "Remove redundant 'else'" "false"
import java.io.IOException;
class a {
void foo(boolean condition) throws IOException{
if (condition) {
tMethod();
}
e<caret>lse {
System.out.println("else");
}
}
void tMethod() throws IOException {}
}
@@ -1,17 +0,0 @@
// "Remove redundant 'else'" "false"
class a {
void foo() {
int a = 0;
int b = 0;
if (a != b) {
a = 10;
} else if (a + 1 == b) {
return;
}
e<caret>lse {
a = b;
}
a++;
}
}
@@ -0,0 +1,4 @@
package p;
interface I {
default void foo();
}
@@ -0,0 +1,3 @@
package p;
public abstract class A implements I {}
@@ -0,0 +1,4 @@
package p;
interface I {
default void foo();
}
@@ -0,0 +1,8 @@
package p;
class EmptyValueIterator extends A implements ValueIterator {
}
interface ValueIterator extends I {}
@@ -0,0 +1,7 @@
import java.util.stream.Stream;
class InChain {
public static void main(String[] args) {
Stream.of("a").map((String<caret> s) -> s + "1").forEach(System.out::println);
}
}
@@ -0,0 +1,7 @@
import java.util.stream.Stream;
class InChain {
public static void main(String[] args) {
Stream.of("a").map(s -> s + "1").forEach(System.out::println);
}
}
@@ -18,7 +18,6 @@ package com.intellij.codeInsight;
import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.pom.java.LanguageLevel;
@@ -26,7 +25,6 @@ import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
import com.intellij.testFramework.fixtures.*;
import com.intellij.util.Consumer;
public class MultipleJdksHighlightingTest extends UsefulTestCase {
@@ -197,6 +195,16 @@ public class MultipleJdksHighlightingTest extends UsefulTestCase {
myFixture.checkHighlighting();
}
public void testUnrelatedDefaultsFromDifferentJdkVersions() throws Exception {
ModuleRootModificationUtil.addDependency(myJava8Module, myJava7Module);
myFixture.copyFileToProject("java7/p/I.java");
myFixture.copyFileToProject("java8/p/I.java");
final String testName = getTestName(false);
myFixture.configureByFiles("java8/p/" + testName + ".java", "java7/p/" + testName + ".java");
myFixture.checkHighlighting();
}
private void doTestWithoutLibrary() {
final String name = getTestName(false);
myFixture.configureByFiles("java7/p/" + name + ".java", "java8/p/" + name + ".java");
@@ -1,33 +0,0 @@
/*
* Copyright 2000-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 com.intellij.codeInsight.daemon.quickFix;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.testFramework.IdeaTestUtil;
public class RedundantLambdaParameterTypeIntentionTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType";
}
@Override
protected Sdk getProjectJDK() {
return IdeaTestUtil.getMockJdk18();
}
}
@@ -1,32 +0,0 @@
/*
* Copyright 2000-2010 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.codeInsight.daemon.quickFix;
/**
* User: anna
* Date: Aug 30, 2010
*/
public class RemoveRedundantElseActionTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse";
}
}
@@ -0,0 +1,112 @@
/*
* Copyright 2000-2016 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:public void testwww() {}.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.codeInspection;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.lambda.RedundantLambdaParameterTypeInspection;
import com.intellij.idea.Bombed;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import java.util.Calendar;
import java.util.List;
public class RedundantLambdaParameterTypeInspectionTest extends LightCodeInsightFixtureTestCase {
private RedundantLambdaParameterTypeInspection myInspection = new RedundantLambdaParameterTypeInspection();
private String myIntentionName = "Remove redundant types";
@Override
protected String getBasePath() {
return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInspection/redundantLambdaParameterType";
}
@Override
protected void setUp() throws Exception {
super.setUp();
ModuleRootModificationUtil.setModuleSdk(myModule, IdeaTestUtil.getMockJdk18());
myFixture.enableInspections(myInspection);
}
@Override
protected void tearDown() throws Exception {
try {
myFixture.disableInspections(myInspection);
}
finally {
super.tearDown();
}
}
public void testAssignment() {
doTest();
}
public void testAssignmentNoParams() {
assertIntentionNotAvailable();
}
public void testAssignmentNoTypes() {
assertIntentionNotAvailable();
}
public void testAtVarargPlace() {
assertIntentionNotAvailable();
}
public void testCallNoTypeArgs() {
assertIntentionNotAvailable();
}
public void testCallNoTypeArgs1() {
assertIntentionNotAvailable();
}
public void testCallWithTypeArgs() {
doTest();
}
public void testInferredFromOtherArgs() {
doTest();
}
public void testNoSelfTypeParam() {
doTest();
}
public void testTypeParam() {
assertIntentionNotAvailable();
}
@Bombed(month = Calendar.AUGUST, day = 1, user = "Pavel Dolgov")
public void testInChain() {
doTest();
}
private void doTest() {
myFixture.configureByFiles(getTestName(false) + ".java");
final IntentionAction singleIntention = myFixture.findSingleIntention(myIntentionName);
myFixture.launchAction(singleIntention);
myFixture.checkResultByFile(getTestName(false) + ".java", getTestName(false) + "_after.java", true);
}
private void assertIntentionNotAvailable() {
myFixture.configureByFiles(getTestName(false) + ".java");
final List<IntentionAction> intentionActions = myFixture.filterAvailableIntentions(myIntentionName);
assertEmpty(myIntentionName + " is not expected", intentionActions);
}
}
@@ -58,10 +58,7 @@ import org.junit.Assert;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
@PlatformTestCase.WrapInCommand
@@ -915,4 +912,20 @@ public class SmartPsiElementPointersTest extends CodeInsightTestCase {
assertEquals(psiClass.getNameIdentifier().getTextRange(), TextRange.create(range));
}
public void testManySmartPointersCreationDeletionPerformance() throws Exception {
String text = StringUtil.repeatSymbol(' ', 100000);
PsiFile file = createFile("a.txt", text);
PlatformTestUtil.startPerformanceTest("", 2000, () -> {
List<SmartPsiFileRange> pointers = new ArrayList<>();
for (int i = 0; i < text.length() - 1; i++) {
pointers.add(getPointerManager().createSmartPsiFileRangePointer(file, new TextRange(i, i + 1)));
}
Collections.shuffle(pointers);
for (SmartPsiFileRange pointer : pointers) {
getPointerManager().removePointer(pointer);
}
}).cpuBound().assertTiming();
}
}
@@ -29,7 +29,7 @@ import com.intellij.psi.*;
import com.intellij.psi.impl.PsiDocumentManagerBase;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.reference.SoftReference;
import com.intellij.util.ArrayUtil;
import com.intellij.util.CommonProcessors;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -68,7 +68,7 @@ public class SmartPointerManagerImpl extends SmartPointerManager {
FilePointersList pointers = reference.file.getUserData(reference.key);
if (pointers != null) {
pointers.remove(reference);
pointers.removeReference(reference);
}
}
}
@@ -160,12 +160,13 @@ public class SmartPointerManagerImpl extends SmartPointerManager {
SmartPointerElementInfo info = pointer.getElementInfo();
if (!(info instanceof SelfElementInfo)) return;
PointerReference reference = new PointerReference(pointer, containingFile, POINTERS_KEY);
while (true) {
FilePointersList pointers = getPointers(containingFile);
if (pointers == null) {
pointers = containingFile.putUserDataIfAbsent(POINTERS_KEY, new FilePointersList());
}
if (pointers.add(new PointerReference(pointer, containingFile, ourQueue, POINTERS_KEY))) {
if (pointers.add(reference)) {
if (((SelfElementInfo)info).hasRange()) {
pointers.markerCache.rangeChanged();
}
@@ -193,8 +194,10 @@ public class SmartPointerManagerImpl extends SmartPointerManager {
if (containingFile == null) return;
VirtualFile vFile = containingFile.getViewProvider().getVirtualFile();
FilePointersList pointers = getPointers(vFile);
if (pointers == null) return;
pointers.remove(pointer);
PointerReference reference = ((SmartPsiElementPointerImpl)pointer).pointerReference;
if (pointers != null && reference != null) {
pointers.removeReference(reference);
}
}
}
@@ -264,17 +267,18 @@ public class SmartPointerManagerImpl extends SmartPointerManager {
return myPsiDocManager;
}
private static class PointerReference extends WeakReference<SmartPsiElementPointerImpl> {
static class PointerReference extends WeakReference<SmartPsiElementPointerImpl> {
@NotNull private final VirtualFile file;
@NotNull private final Key<FilePointersList> key;
private int index = -2;
private PointerReference(@NotNull SmartPsiElementPointerImpl<?> pointer,
@NotNull VirtualFile containingFile,
@NotNull ReferenceQueue<SmartPsiElementPointerImpl> queue,
@NotNull Key<FilePointersList> key) {
super(pointer, queue);
super(pointer, ourQueue);
file = containingFile;
this.key = key;
pointer.pointerReference = this;
}
}
@@ -292,104 +296,98 @@ public class SmartPointerManagerImpl extends SmartPointerManager {
}
if (nextAvailableIndex >= references.length || nextAvailableIndex > size*2) { // overflow or too many dead refs
int newCapacity = nextAvailableIndex >= references.length ? references.length * 3/2 +1 : size * 3/2+1;
PointerReference[] newReferences = new PointerReference[newCapacity];
int newCapacity = (nextAvailableIndex >= references.length ? references.length : size) * 3 / 2 + 1;
final PointerReference[] newReferences = new PointerReference[newCapacity];
int o = 0;
for (PointerReference oldRef : references) {
if (SoftReference.dereference(oldRef) != null) {
newReferences[o++] = oldRef;
final int[] o = {0};
processAlivePointers(new Processor<SmartPsiElementPointerImpl>() {
@Override
public boolean process(SmartPsiElementPointerImpl pointer) {
storePointerReference(newReferences, o[0]++, pointer.pointerReference);
return true;
}
}
});
references = newReferences;
size = nextAvailableIndex = o;
size = nextAvailableIndex = o[0];
}
references[nextAvailableIndex++] = reference;
assert references[nextAvailableIndex] == null : references[nextAvailableIndex];
storePointerReference(references, nextAvailableIndex++, reference);
size++;
mySorted = false;
return true;
}
private synchronized void remove(@NotNull PointerReference reference) {
int index = ArrayUtil.indexOf(references, reference, 0, nextAvailableIndex);
if (index != -1) {
removeReference(reference, index);
}
}
private synchronized void removeReference(@NotNull PointerReference reference) {
int index = reference.index;
if (index < 0) return;
private synchronized void remove(@NotNull SmartPsiElementPointer smartPointer) {
for (int i = 0; i < nextAvailableIndex; i++) {
PointerReference reference = references[i];
if (reference != null && reference.get() == smartPointer) {
removeReference(reference, i);
return;
}
}
}
private void removeReference(@NotNull PointerReference reference, int index) {
assert references[index] == reference : "At " + index + " expected " + reference + ", found " + references[index];
references[index].index = -1;
references[index] = null;
if (--size == 0) {
reference.file.replace(reference.key, this, null);
}
}
boolean processAlivePointers(@NotNull Processor<SmartPsiElementPointerImpl> processor) {
synchronized boolean processAlivePointers(@NotNull Processor<SmartPsiElementPointerImpl> processor) {
for (int i = 0; i < nextAvailableIndex; i++) {
SmartPsiElementPointerImpl pointer = SoftReference.dereference(references[i]);
if (pointer != null && !processor.process(pointer)) {
PointerReference ref = references[i];
if (ref == null) continue;
SmartPsiElementPointerImpl pointer = ref.get();
if (pointer == null) {
removeReference(ref);
continue;
}
if (!processor.process(pointer)) {
return false;
}
}
return true;
}
synchronized List<SelfElementInfo> getSortedInfos() {
private void ensureSorted() {
if (!mySorted) {
List<SmartPsiElementPointerImpl> hardRefs = ContainerUtil.newArrayListWithCapacity(size);
for (int i = 0; i < nextAvailableIndex; i++) {
PointerReference reference = references[i];
if (reference == null) continue;
List<SmartPsiElementPointerImpl> pointers = new ArrayList<SmartPsiElementPointerImpl>();
processAlivePointers(new CommonProcessors.CollectProcessor<SmartPsiElementPointerImpl>(pointers));
assert size == pointers.size();
SmartPsiElementPointerImpl pointer = reference.get();
if (pointer != null) {
hardRefs.add(pointer);
}
else {
removeReference(reference, i);
if (size == 0) {
return Collections.emptyList();
}
}
}
assert size == hardRefs.size();
Arrays.sort(references, 0, nextAvailableIndex, new Comparator<PointerReference>() {
Collections.sort(pointers, new Comparator<SmartPsiElementPointerImpl>() {
@Override
public int compare(PointerReference o1, PointerReference o2) {
SmartPsiElementPointerImpl p1 = SoftReference.dereference(o1);
SmartPsiElementPointerImpl p2 = SoftReference.dereference(o2);
if (p1 == null || p2 == null) {
return p1 != null ? -1 : p2 != null ? 1 : 0; // null references to the end
}
public int compare(SmartPsiElementPointerImpl p1, SmartPsiElementPointerImpl p2) {
return MarkerCache.INFO_COMPARATOR.compare((SelfElementInfo)p1.getElementInfo(), (SelfElementInfo)p2.getElementInfo());
}
});
nextAvailableIndex = hardRefs.size();
for (int i = 0; i < pointers.size(); i++) {
storePointerReference(references, i, pointers.get(i).pointerReference);
}
Arrays.fill(references, pointers.size(), nextAvailableIndex, null);
nextAvailableIndex = pointers.size();
mySorted = true;
}
}
List<SelfElementInfo> infos = ContainerUtil.newArrayListWithCapacity(size);
for (int i = 0; i < nextAvailableIndex; i++) {
Reference<SmartPsiElementPointerImpl> reference = references[i];
SmartPsiElementPointerImpl pointer = SoftReference.dereference(reference);
if (pointer != null) {
private static void storePointerReference(PointerReference[] references, int index, PointerReference ref) {
references[index] = ref;
ref.index = index;
}
synchronized List<SelfElementInfo> getSortedInfos() {
ensureSorted();
final List<SelfElementInfo> infos = ContainerUtil.newArrayListWithCapacity(size);
processAlivePointers(new Processor<SmartPsiElementPointerImpl>() {
@Override
public boolean process(SmartPsiElementPointerImpl pointer) {
SelfElementInfo info = (SelfElementInfo)pointer.getElementInfo();
if (!info.hasRange()) break;
if (!info.hasRange()) return false;
infos.add(info);
return true;
}
}
});
return infos;
}
@@ -46,6 +46,7 @@ class SmartPsiElementPointerImpl<E extends PsiElement> implements SmartPointerEx
private final SmartPointerElementInfo myElementInfo;
private final Class<? extends PsiElement> myElementClass;
private byte myReferenceCount = 1;
@Nullable SmartPointerManagerImpl.PointerReference pointerReference;
SmartPsiElementPointerImpl(@NotNull Project project, @NotNull E element, @Nullable PsiFile containingFile, boolean forInjected) {
this(element, createElementInfo(project, element, containingFile, forInjected), element.getClass());
@@ -54,9 +54,7 @@ import java.util.Set;
* A: There are two ways. The easier and preferred one is to provide constructor in your contributor and register completion providers there:
* {@link #extend(CompletionType, ElementPattern, CompletionProvider)}.<br>
* A more generic way is to override default {@link #fillCompletionVariants(CompletionParameters, CompletionResultSet)} implementation
* and provide your own. It's easier to debug, but harder to write. Remember, that completion variant collection is done in a dedicated thread
* WITHOUT read action, so you'll have to manually invoke {@link com.intellij.openapi.application.Application#runReadAction(Runnable)} each time
* you access PSI. Don't spend long time inside read action, since this will prevent user from selecting lookup element or cancelling completion.<p>
* and provide your own. It's easier to debug, but harder to write.<p>
*
* Q: What does the {@link CompletionParameters#getPosition()} return?<br>
* A: When completion is invoked, the file being edited is first copied (the original file can be accessed from {@link com.intellij.psi.PsiFile#getOriginalFile()}
@@ -19,10 +19,10 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -48,10 +48,10 @@ public class OffsetMap implements Disposable {
public int getOffset(OffsetKey key) {
synchronized (myMap) {
final RangeMarker marker = myMap.get(key);
if (marker == null) return -1;
if (marker == null) throw new IllegalArgumentException("Offset " + key + " is not registered");
if (!marker.isValid()) {
removeOffset(key);
return -1;
throw new IllegalStateException("Offset " + key + " is invalid: " + marker);
}
final int endOffset = marker.getEndOffset();
@@ -62,6 +62,11 @@ public class OffsetMap implements Disposable {
}
}
public boolean containsOffset(OffsetKey key) {
final RangeMarker marker = myMap.get(key);
return marker != null && marker.isValid();
}
/**
* Register key-offset binding. Offset will change together with {@link Document} editing operations
* unless an operation replaces completely the offset vicinity.
@@ -108,7 +113,7 @@ public class OffsetMap implements Disposable {
synchronized (myMap) {
ProgressManager.checkCanceled();
assert !myDisposed;
return new ArrayList<OffsetKey>(myMap.keySet());
return ContainerUtil.filter(myMap.keySet(), this::containsOffset);
}
}
@@ -566,10 +566,9 @@ public class CodeCompletionHandlerBase {
final Editor editor = indicator.getEditor();
final int caretOffset = indicator.getCaret().getOffset();
int idEndOffset = indicator.getIdentifierEndOffset();
if (idEndOffset < 0) {
idEndOffset = CompletionInitializationContext.calcDefaultIdentifierEnd(editor, caretOffset);
}
final int idEndOffset = indicator.getOffsetMap().containsOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET) ?
indicator.getIdentifierEndOffset() :
CompletionInitializationContext.calcDefaultIdentifierEnd(editor, caretOffset);
final int idEndOffsetDelta = idEndOffset - caretOffset;
CompletionAssertions.WatchingInsertionContext context;
@@ -18,6 +18,8 @@ package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.util.Key;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.ui.StringComboboxEditor;
@@ -28,7 +30,9 @@ import javax.swing.*;
/**
* @author peter
*/
public class ComboEditorCompletionContributor extends CompletionContributor{
public class ComboEditorCompletionContributor extends CompletionContributor implements DumbAware {
public static final Key<Boolean> CONTINUE_RUN_COMPLETION = Key.create("CONTINUE_RUN_COMPLETION");
@Override
public void fillCompletionVariants(@NotNull final CompletionParameters parameters, @NotNull final CompletionResultSet result) {
@@ -60,7 +64,9 @@ public class ComboEditorCompletionContributor extends CompletionContributor{
}), count-i));
}
}
result.stopHere();
if (!Boolean.TRUE.equals(document.getUserData(CONTINUE_RUN_COMPLETION))) {
result.stopHere();
}
}
}
}
@@ -462,6 +462,10 @@ public class CompletionLookupArranger extends LookupArranger {
return;
}
if (!context.getOffsetMap().containsOffset(CompletionInitializationContext.START_OFFSET)) {
return;
}
final Document document = context.getDocument();
int startOffset = context.getStartOffset();
int tailOffset = context.getEditor().getCaretModel().getOffset();
@@ -550,7 +554,9 @@ public class CompletionLookupArranger extends LookupArranger {
public void addSparedChars(CompletionProgressIndicator indicator, LookupElement item, InsertionContext context, char completionChar) {
String textInserted;
if (context.getStartOffset() >= 0 && context.getTailOffset() >= context.getStartOffset()) {
if (context.getOffsetMap().containsOffset(CompletionInitializationContext.START_OFFSET) &&
context.getOffsetMap().containsOffset(InsertionContext.TAIL_OFFSET) &&
context.getTailOffset() >= context.getStartOffset()) {
textInserted = context.getDocument().getImmutableCharSequence().subSequence(context.getStartOffset(), context.getTailOffset()).toString();
} else {
textInserted = item.getLookupString();
@@ -35,18 +35,17 @@ import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.DumbAwareRunnable;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import gnu.trove.THashMap;
@@ -57,7 +56,10 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -506,10 +508,18 @@ class PassExecutorService implements Disposable {
pass.applyInformationToEditor();
}
}
catch (RuntimeException e) {
catch (ProcessCanceledException e) {
log(updateProgress, pass, "Error " + e);
throw e;
}
catch (RuntimeException e) {
Document document = pass.getDocument();
VirtualFile file = document == null ? null : FileDocumentManager.getInstance().getFile(document);
FileType fileType = file == null ? null : file.getFileType();
String message = "Exception while applying information to " + fileEditor + "("+fileType+")";
log(updateProgress, pass, message + e);
throw new RuntimeException(message, e);
}
if (threadsToStartCountdown.decrementAndGet() == 0) {
log(updateProgress, pass, "Stopping ");
updateProgress.stopIfRunning();
@@ -767,13 +767,15 @@ public class FileBasedIndexImpl extends FileBasedIndex {
}
}
processValuesImpl(indexId, dataKey, true, restrictToFile, new ValueProcessor<V>() {
@Override
public boolean process(final VirtualFile file, final V value) {
values.add(value);
return true;
}
}, filter, null);
ValueProcessor<V> processor = (file, value) -> {
values.add(value);
return true;
};
if (restrictToFile != null) {
processValuesInOneFile(indexId, dataKey, restrictToFile, processor, filter);
} else {
processValuesInScope(indexId, dataKey, true, filter, null, processor);
}
return values;
}
@@ -783,13 +785,10 @@ public class FileBasedIndexImpl extends FileBasedIndex {
@NotNull K dataKey,
@NotNull final GlobalSearchScope filter) {
final Set<VirtualFile> files = new THashSet<VirtualFile>();
processValuesImpl(indexId, dataKey, false, null, new ValueProcessor<V>() {
@Override
public boolean process(final VirtualFile file, final V value) {
files.add(file);
return true;
}
}, filter, null);
processValuesInScope(indexId, dataKey, false, filter, null, (file, value) -> {
files.add(file);
return true;
});
return files;
}
@@ -807,7 +806,40 @@ public class FileBasedIndexImpl extends FileBasedIndex {
@NotNull ValueProcessor<V> processor,
@NotNull GlobalSearchScope filter,
@Nullable IdFilter idFilter) {
return processValuesImpl(indexId, dataKey, false, inFile, processor, filter, idFilter);
return inFile != null
? processValuesInOneFile(indexId, dataKey, inFile, processor, filter)
: processValuesInScope(indexId, dataKey, false, filter, idFilter, processor);
}
public interface IdValueProcessor<V> {
/**
* @param fileId the id of the file that the value came from
* @param value a value to process
* @return false if no further processing is needed, true otherwise
*/
boolean process(int fileId, V value);
}
/**
* Process values for a given index key together with their containing file ids. Note that project is supplied
* only to ensure that all the indices in that project are up to date; there's no guarantee that the processed file ids belong
* to this project.
*/
public <K, V> boolean processAllValues(@NotNull ID<K, V> indexId,
@NotNull K key,
@NotNull Project project,
@NotNull IdValueProcessor<V> processor) {
return processValueIterator(indexId, key, null, GlobalSearchScope.allScope(project), valueIt -> {
while (valueIt.hasNext()) {
V value = valueIt.next();
for (ValueContainer.IntIterator inputIdsIterator = valueIt.getInputIdsIterator(); inputIdsIterator.hasNext(); ) {
if (!processor.process(inputIdsIterator.next(), value)) {
return false;
}
}
}
return true;
});
}
@Nullable
@@ -854,54 +886,61 @@ public class FileBasedIndexImpl extends FileBasedIndex {
return null;
}
private <K, V> boolean processValuesImpl(@NotNull final ID<K, V> indexId, @NotNull final K dataKey, final boolean ensureValueProcessedOnce,
@Nullable final VirtualFile restrictToFile, @NotNull final ValueProcessor<V> processor,
@NotNull final GlobalSearchScope scope, @Nullable final IdFilter idFilter) {
ThrowableConvertor<UpdatableIndex<K, V, FileContent>, Boolean, StorageException> keyProcessor =
index -> {
final ValueContainer<V> container = index.getData(dataKey);
private <K, V> boolean processValuesInOneFile(@NotNull ID<K, V> indexId,
@NotNull K dataKey,
@NotNull VirtualFile restrictToFile,
@NotNull ValueProcessor<V> processor, @NotNull GlobalSearchScope scope) {
if (!(restrictToFile instanceof VirtualFileWithId)) return true;
boolean shouldContinue = true;
int restrictedFileId = getFileId(restrictToFile);
return processValueIterator(indexId, dataKey, restrictToFile, scope, valueIt -> {
while (valueIt.hasNext()) {
V value = valueIt.next();
if (valueIt.getValueAssociationPredicate().contains(restrictedFileId) && !processor.process(restrictToFile, value)) {
return false;
}
}
return true;
});
}
if (restrictToFile != null) {
if (restrictToFile instanceof VirtualFileWithId) {
final int restrictedFileId = getFileId(restrictToFile);
for (final ValueContainer.ValueIterator<V> valueIt = container.getValueIterator(); valueIt.hasNext(); ) {
final V value = valueIt.next();
if (valueIt.getValueAssociationPredicate().contains(restrictedFileId)) {
shouldContinue = processor.process(restrictToFile, value);
if (!shouldContinue) {
break;
}
}
private <K, V> boolean processValuesInScope(@NotNull ID<K, V> indexId,
@NotNull K dataKey,
boolean ensureValueProcessedOnce,
@NotNull GlobalSearchScope scope,
@Nullable IdFilter idFilter,
@NotNull ValueProcessor<V> processor) {
PersistentFS fs = (PersistentFS)ManagingFS.getInstance();
IdFilter filter = idFilter != null ? idFilter : projectIndexableFiles(scope.getProject());
return processValueIterator(indexId, dataKey, null, scope, valueIt -> {
while (valueIt.hasNext()) {
final V value = valueIt.next();
for (final ValueContainer.IntIterator inputIdsIterator = valueIt.getInputIdsIterator(); inputIdsIterator.hasNext(); ) {
final int id = inputIdsIterator.next();
if (filter != null && !filter.containsFileId(id)) continue;
VirtualFile file = IndexInfrastructure.findFileByIdIfCached(fs, id);
if (file != null && scope.accept(file)) {
if (!processor.process(file, value)) {
return false;
}
if (ensureValueProcessedOnce) {
break; // continue with the next value
}
}
}
else {
final PersistentFS fs = (PersistentFS)ManagingFS.getInstance();
final IdFilter filter = idFilter != null ? idFilter : projectIndexableFiles(scope.getProject());
VALUES_LOOP:
for (final ValueContainer.ValueIterator<V> valueIt = container.getValueIterator(); valueIt.hasNext(); ) {
final V value = valueIt.next();
for (final ValueContainer.IntIterator inputIdsIterator = valueIt.getInputIdsIterator(); inputIdsIterator.hasNext(); ) {
final int id = inputIdsIterator.next();
if (filter != null && !filter.containsFileId(id)) continue;
VirtualFile file = IndexInfrastructure.findFileByIdIfCached(fs, id);
if (file != null && scope.accept(file)) {
shouldContinue = processor.process(file, value);
if (!shouldContinue) {
break VALUES_LOOP;
}
if (ensureValueProcessedOnce) {
break; // continue with the next value
}
}
}
}
}
return shouldContinue;
};
final Boolean result = processExceptions(indexId, restrictToFile, scope, keyProcessor);
}
return true;
});
}
private <K, V> boolean processValueIterator(@NotNull ID<K, V> indexId,
@NotNull K dataKey,
@Nullable VirtualFile restrictToFile,
@NotNull GlobalSearchScope scope,
@NotNull Processor<ValueContainer.ValueIterator<V>> valueProcessor) {
final Boolean result = processExceptions(indexId, restrictToFile, scope,
index -> valueProcessor.process(index.getData(dataKey).getValueIterator()));
return result == null || result.booleanValue();
}
@@ -21,7 +21,6 @@ import com.intellij.util.SmartList;
import com.intellij.util.containers.EmptyIterator;
import com.intellij.util.indexing.containers.ChangeBufferingList;
import com.intellij.util.indexing.containers.IdSet;
import com.intellij.util.indexing.containers.SortedFileIdSetIterator;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.DataInputOutputUtil;
import gnu.trove.THashMap;
@@ -447,11 +446,8 @@ class ValueContainerImpl<Value> extends UpdatableValueContainer<Value> implement
} else {
// serialize positive file ids with delta encoding
ChangeBufferingList originalInput = (ChangeBufferingList)fileSetObject;
IntIterator intIterator = originalInput.rawIntIterator();
if (!intIterator.hasAscendingOrder()) {
// remove possible dupes
intIterator = SortedFileIdSetIterator.getTransientIterator(intIterator);
}
IntIterator intIterator = originalInput.sortedIntIterator();
if (DebugAssertions.DEBUG) DebugAssertions.assertTrue(intIterator.hasAscendingOrder());
if (intIterator.size() == 1) {
DataInputOutputUtil.writeINT(out, intIterator.next());
@@ -19,6 +19,8 @@ import com.intellij.util.indexing.DebugAssertions;
import com.intellij.util.indexing.ValueContainer;
import gnu.trove.TIntProcedure;
import java.util.Arrays;
import static com.intellij.util.indexing.DebugAssertions.EXTRA_SANITY_CHECKS;
/**
@@ -122,7 +124,6 @@ public class ChangeBufferingList implements Cloneable {
if (randomAccessContainer == null) {
int someElementsNumberEstimation = length;
int[] minMax = calcMinMax(changes, length);
// todo we can check these lengths instead of only relying upon reaching MAX_FILES
//int lengthOfBitSet = IdBitSet.sizeInBytes(minMax[1], minMax[0]);
@@ -131,7 +132,7 @@ public class ChangeBufferingList implements Cloneable {
if (someElementsNumberEstimation < MAX_FILES) {
if (!hasRemovals) {
if (mayHaveDupes) {
mergeChangesRemovingDupes();
removingDupesAndSort();
}
idSet = new SortedIdSet(currentChanges, length);
@@ -144,7 +145,7 @@ public class ChangeBufferingList implements Cloneable {
idSet = new IdBitSet(changes, length, 0);
copyChanges = false;
} else {
idSet = new IdBitSet(minMax, 0);
idSet = new IdBitSet(calcMinMax(changes, length), 0);
}
} else if (checkSet != null) {
idSet = (RandomAccessIntContainer)randomAccessContainer.clone();
@@ -186,15 +187,40 @@ public class ChangeBufferingList implements Cloneable {
}
}
private void mergeChangesRemovingDupes() { // duplicated ids can be present for some index due to cancellation of indexing for next index
int[] currentChanges = changes;
ValueContainer.IntIterator sorted = SortedFileIdSetIterator.getTransientIterator(new ChangesIterator(currentChanges, length));
int lastIndex = 0;
while(sorted.hasNext()) {
currentChanges[lastIndex++] = sorted.next();
}
private void removingDupesAndSort() { // duplicated ids can be present for some index due to cancellation of indexing for next index
final int[] currentChanges = changes;
final int intLength = length;
length = (short)lastIndex;
if (intLength < 250) { // Plain sorting in Arrays works without allocations for small number of elements (see DualPivotQuicksort.QUICKSORT_THRESHOLD)
Arrays.sort(currentChanges, 0, intLength);
boolean hasDupes = false;
for(int i = 0, max = intLength - 1; i < max; ++i) {
if (currentChanges[i] == currentChanges[i + 1]) {
hasDupes = true;
break;
}
}
if (hasDupes) {
int ptr = 0;
for(int i = 1; i < intLength; ++i) {
if (currentChanges[i] != currentChanges[ptr]) {
currentChanges[++ptr] = currentChanges[i];
}
}
length = (short)(ptr + 1);
}
} else {
ValueContainer.IntIterator sorted =
SortedFileIdSetIterator.getTransientIterator(new ChangesIterator(currentChanges, length, false));
int lastIndex = 0;
while (sorted.hasNext()) {
currentChanges[lastIndex++] = sorted.next();
}
length = (short)lastIndex;
}
mayHaveDupes = false;
}
@@ -262,21 +288,22 @@ public class ChangeBufferingList implements Cloneable {
if (currentChanges != null) {
if (mayHaveDupes) {
synchronized (currentChanges) {
if (mayHaveDupes) mergeChangesRemovingDupes();
if (mayHaveDupes) removingDupesAndSort();
}
}
return new ChangesIterator(currentChanges, length);
return new ChangesIterator(currentChanges, length, true);
}
}
return getRandomAccessContainer().intIterator();
}
public ValueContainer.IntIterator rawIntIterator() {
RandomAccessIntContainer intContainer = randomAccessContainer;
if (intContainer == null && !hasRemovals) {
return new ChangesIterator(changes, length); // dupes are possible
public ValueContainer.IntIterator sortedIntIterator() {
ValueContainer.IntIterator intIterator = intIterator();
if (!intIterator.hasAscendingOrder()) {
intIterator = SortedFileIdSetIterator.getTransientIterator(intIterator);
}
return getRandomAccessContainer().intIterator();
return intIterator;
}
public IdSet getCheckSet() {
@@ -287,10 +314,12 @@ public class ChangeBufferingList implements Cloneable {
private int cursor;
private final int length;
private final int[] changes;
private final boolean sorted;
ChangesIterator(int[] _changes, int _length) {
ChangesIterator(int[] _changes, int _length, boolean _sorted) {
changes = _changes;
length = _length;
sorted = _sorted;
}
@Override
@@ -312,12 +341,12 @@ public class ChangeBufferingList implements Cloneable {
@Override
public boolean hasAscendingOrder() {
return false;
return sorted;
}
@Override
public ValueContainer.IntIterator createCopyInInitialState() {
return new ChangesIterator(changes, length);
return new ChangesIterator(changes, length, sorted);
}
}
}
@@ -50,7 +50,7 @@ public class TextEditorLocation implements FileEditorLocation {
}
@Override
public int compareTo(FileEditorLocation fileEditorLocation) {
public int compareTo(@NotNull FileEditorLocation fileEditorLocation) {
TextEditorLocation otherLocation = (TextEditorLocation)fileEditorLocation;
if (myEditor != otherLocation.myEditor) {
LOG.error("Different editors: " + myEditor + "; and " + otherLocation.myEditor);
@@ -29,7 +29,7 @@ import java.awt.event.InputEvent;
public interface ToolWindow extends BusyObject {
Key<Boolean> SHOW_CONTENT_ICON = new Key<Boolean>("ContentIcon");
Key<Boolean> SHOW_CONTENT_ICON = new Key<>("ContentIcon");
/**
* @exception IllegalStateException if tool window isn't installed.
@@ -74,7 +74,7 @@ public interface ToolWindow extends BusyObject {
/**
* @exception IllegalStateException if tool window isn't installed.
*/
void setAnchor(ToolWindowAnchor anchor, @Nullable Runnable runnable);
void setAnchor(@NotNull ToolWindowAnchor anchor, @Nullable Runnable runnable);
/**
* @exception IllegalStateException if tool window isn't installed.
@@ -104,7 +104,7 @@ public interface ToolWindow extends BusyObject {
/**
* @exception IllegalStateException if tool window isn't installed.
*/
void setType(ToolWindowType type, @Nullable Runnable runnable);
void setType(@NotNull ToolWindowType type, @Nullable Runnable runnable);
/**
* @return window icon. Returns <code>null</code> if window has no icon.
@@ -17,6 +17,7 @@ package com.intellij.openapi.wm;
import com.intellij.ide.ui.UISettings;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -26,9 +27,10 @@ public final class ToolWindowAnchor {
public static final ToolWindowAnchor BOTTOM = new ToolWindowAnchor("bottom");
public static final ToolWindowAnchor RIGHT = new ToolWindowAnchor("right");
@NotNull
private final String myText;
private ToolWindowAnchor(@NonNls String text){
private ToolWindowAnchor(@NonNls @NotNull String text){
myText = text;
}
@@ -40,6 +42,7 @@ public final class ToolWindowAnchor {
return this == TOP || this == BOTTOM;
}
@NotNull
public static ToolWindowAnchor get(int swingOrientationConstant) {
switch(swingOrientationConstant) {
case SwingConstants.TOP:
@@ -56,12 +59,16 @@ public final class ToolWindowAnchor {
}
public boolean isSplitVertically() {
return (this == LEFT && !UISettings.getInstance().LEFT_HORIZONTAL_SPLIT) || (this == RIGHT && !UISettings.getInstance().RIGHT_HORIZONTAL_SPLIT);
return this == LEFT && !UISettings.getInstance().LEFT_HORIZONTAL_SPLIT
|| this == RIGHT && !UISettings.getInstance().RIGHT_HORIZONTAL_SPLIT;
}
@NotNull
public static ToolWindowAnchor fromText(String anchor) {
for (ToolWindowAnchor a : new ToolWindowAnchor[]{TOP, LEFT, BOTTOM, RIGHT}) {
if (a.myText.equals(anchor)) return a;
if (a.myText.equals(anchor)) {
return a;
}
}
throw new IllegalArgumentException("Unknown anchor constant: " + anchor);
}
@@ -73,7 +73,7 @@ public abstract class ToolWindowManager {
public abstract ToolWindow registerToolWindow(@NotNull String id,
@NotNull JComponent component,
@NotNull ToolWindowAnchor anchor,
Disposable parentDisposable,
@NotNull Disposable parentDisposable,
boolean canWorkInDumbMode);
/**
* @deprecated {@link ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)}
@@ -83,7 +83,7 @@ public abstract class ToolWindowManager {
public abstract ToolWindow registerToolWindow(@NotNull String id,
@NotNull JComponent component,
@NotNull ToolWindowAnchor anchor,
Disposable parentDisposable,
@NotNull Disposable parentDisposable,
boolean canWorkInDumbMode,
boolean canCloseContents);
@@ -91,19 +91,31 @@ public abstract class ToolWindowManager {
public abstract ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor);
@NotNull
public abstract ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor, boolean secondary);
public abstract ToolWindow registerToolWindow(@NotNull String id,
boolean canCloseContent,
@NotNull ToolWindowAnchor anchor,
boolean secondary);
@NotNull
public abstract ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor, Disposable parentDisposable, boolean canWorkInDumbMode);
public abstract ToolWindow registerToolWindow(@NotNull String id,
boolean canCloseContent,
@NotNull ToolWindowAnchor anchor,
@NotNull Disposable parentDisposable,
boolean canWorkInDumbMode);
@NotNull
public abstract ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor, Disposable parentDisposable, boolean canWorkInDumbMode, boolean secondary);
public abstract ToolWindow registerToolWindow(@NotNull String id,
boolean canCloseContent,
@NotNull ToolWindowAnchor anchor,
@NotNull Disposable parentDisposable,
boolean canWorkInDumbMode,
boolean secondary);
@NotNull
public ToolWindow registerToolWindow(@NotNull final String id,
final boolean canCloseContent,
@NotNull final ToolWindowAnchor anchor,
final Disposable parentDisposable) {
@NotNull Disposable parentDisposable) {
return registerToolWindow(id, canCloseContent, anchor, parentDisposable, false);
}
@@ -46,9 +46,9 @@ import java.awt.event.*;
* @author Alexander Lobas
*/
public class LightToolWindow extends JPanel {
public static final String LEFT_MIN_KEY = "left";
public static final String RIGHT_MIN_KEY = "right";
public static final int MINIMIZE_WIDTH = 25;
static final String LEFT_MIN_KEY = "left";
static final String RIGHT_MIN_KEY = "right";
static final int MINIMIZE_WIDTH = 25;
private static final String IGNORE_WIDTH_KEY = "ignore_width";
private final LightToolWindowContent myContent;
@@ -139,12 +139,14 @@ public class LightToolWindow extends JPanel {
add(contentWrapper, BorderLayout.CENTER);
addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(final MouseEvent e) {
IdeFocusManager.getInstance(myProject).requestFocus(myFocusedComponent, true);
}
});
addMouseListener(new PopupHandler() {
@Override
public void invokePopup(Component component, int x, int y) {
showGearPopup(component, x, y);
}
@@ -167,12 +169,9 @@ public class LightToolWindow extends JPanel {
return myAnchor;
}
};
myMinimizeButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
myMinimizeButton.setSelected(false);
updateContent(true, true);
}
myMinimizeButton.addActionListener(e -> {
myMinimizeButton.setSelected(false);
updateContent(true, true);
});
myMinimizeButton.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5));
myMinimizeButton.setFocusable(false);
@@ -233,7 +232,7 @@ public class LightToolWindow extends JPanel {
}
}
public void updateAnchor(ToolWindowAnchor newAnchor) {
void updateAnchor(ToolWindowAnchor newAnchor) {
JComponent minimizeParent = myContentSplitter.getInnerComponent();
minimizeParent.putClientProperty(IGNORE_WIDTH_KEY, Boolean.TRUE);
@@ -374,7 +373,7 @@ public class LightToolWindow extends JPanel {
}
private class GearAction extends AnAction {
public GearAction() {
GearAction() {
Presentation presentation = getTemplatePresentation();
presentation.setIcon(AllIcons.General.Gear);
presentation.setHoveredIcon(AllIcons.General.GearHover);
@@ -462,7 +461,7 @@ public class LightToolWindow extends JPanel {
}
private class ToggleWindowedModeAction extends ToggleTypeModeAction {
public ToggleWindowedModeAction() {
ToggleWindowedModeAction() {
super(ToolWindowType.WINDOWED, InternalDecorator.TOGGLE_WINDOWED_MODE_ACTION_ID);
}
@@ -475,7 +474,7 @@ public class LightToolWindow extends JPanel {
private class ToggleTypeModeAction extends ToggleAction {
private final ToolWindowType myType;
public ToggleTypeModeAction(ToolWindowType type, String id) {
ToggleTypeModeAction(@NotNull ToolWindowType type, @NotNull String id) {
myType = type;
copyFrom(ActionManager.getInstance().getAction(id));
}
@@ -1,17 +1,16 @@
package com.intellij.ide.actions;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.DumbAwareAction;
/**
* @author yole
*/
public class SaveDocumentAction extends AnAction {
public class SaveDocumentAction extends DumbAwareAction {
@Override
public void actionPerformed(AnActionEvent e) {
Document doc = getDocument(e);
@@ -2,6 +2,7 @@ package com.intellij.openapi.wm.ex;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -10,8 +11,8 @@ import javax.swing.*;
*/
public class DefaultFrameEditorComponentProvider implements FrameEditorComponentProvider {
@Override
public JComponent createEditorComponent(Project project) {
public JComponent createEditorComponent(@NotNull Project project) {
FileEditorManagerEx editorManager = FileEditorManagerEx.getInstanceEx(project);
return editorManager.getComponent();
return editorManager.getComponent();
}
}
@@ -2,14 +2,16 @@ package com.intellij.openapi.wm.ex;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
/**
* @author Konstantin Bulenkov
*/
@FunctionalInterface
public interface FrameEditorComponentProvider {
ExtensionPointName<FrameEditorComponentProvider> EP = ExtensionPointName.create("com.intellij.frameEditorComponentProvider");
JComponent createEditorComponent(Project project);
JComponent createEditorComponent(@NotNull Project project);
}
@@ -35,9 +35,9 @@ public abstract class ToolWindowManagerEx extends ToolWindowManager {
return (ToolWindowManagerEx)getInstance(project);
}
public abstract void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l);
public abstract void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l, @NotNull Disposable parentDisposable);
public abstract void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l);
public abstract void addToolWindowManagerListener(@NotNull ToolWindowManagerListener listener);
public abstract void addToolWindowManagerListener(@NotNull ToolWindowManagerListener listener, @NotNull Disposable parentDisposable);
public abstract void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener listener);
/**
* @return <code>ID</code> of tool window that was activated last time.
@@ -69,5 +69,6 @@ public abstract class ToolWindowManagerEx extends ToolWindowManager {
public abstract void hideToolWindow(@NotNull String id, boolean hideSide);
@NotNull
public abstract List<String> getIdsOn(@NotNull ToolWindowAnchor anchor);
}
@@ -15,8 +15,10 @@
*/
package com.intellij.openapi.wm.impl;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NotNull;
import java.util.Iterator;
import java.util.Stack;
/**
* Actually this class represent two stacks.
@@ -43,8 +45,8 @@ final class ActiveStack {
* Creates enabled window stack.
*/
ActiveStack() {
myStack = new Stack<String>();
myPersistentStack = new Stack<String>();
myStack = new Stack<>();
myPersistentStack = new Stack<>();
}
/**
@@ -61,10 +63,12 @@ final class ActiveStack {
return myStack.isEmpty();
}
@NotNull
String pop() {
return myStack.pop();
}
@NotNull
String peek() {
return myStack.peek();
}
@@ -73,10 +77,12 @@ final class ActiveStack {
return myStack.size();
}
String peek(int i) {
@NotNull
private String peek(int i) {
return myStack.get(getSize() - i - 1);
}
@NotNull
String[] getStack() {
String[] result = new String[getSize()];
for (int i = 0; i < getSize(); i++) {
@@ -85,6 +91,7 @@ final class ActiveStack {
return result;
}
@NotNull
String[] getPersistentStack() {
String[] result = new String[getPersistentSize()];
for (int i = 0; i < getPersistentSize(); i++) {
@@ -93,7 +100,7 @@ final class ActiveStack {
return result;
}
void push(final String id) {
void push(@NotNull String id) {
remove(id, true);
myStack.push(id);
myPersistentStack.push(id);
@@ -106,6 +113,7 @@ final class ActiveStack {
/**
* Peeks element at the persistent stack. <code>0</code> means the top of the stack.
*/
@NotNull
String peekPersistent(final int index) {
return myPersistentStack.get(myPersistentStack.size() - index - 1);
}
@@ -117,7 +125,7 @@ final class ActiveStack {
* @param removePersistentAlso if <code>true</code> then clears last active <code>ID</code>
* if it's the last active <code>ID</code>.
*/
void remove(final String id, final boolean removePersistentAlso) {
void remove(@NotNull String id, final boolean removePersistentAlso) {
for (Iterator i = myStack.iterator(); i.hasNext();) {
if (id.equals(i.next())) {
i.remove();
@@ -36,11 +36,11 @@ public final class DesktopLayout implements JDOMExternalizable {
/**
* Map between <code>id</code>s and registered <code>WindowInfo</code>s.
*/
private final Map<String, WindowInfoImpl> myRegisteredId2Info;
private final Map<String, WindowInfoImpl> myRegisteredId2Info = new HashMap<>();
/**
* Map between <code>id</code>s and unregistered <code>WindowInfo</code>s.
*/
private final Map<String, WindowInfoImpl> myUnregisteredId2Info;
private final Map<String, WindowInfoImpl> myUnregisteredId2Info = new HashMap<>();
/**
*
*/
@@ -63,19 +63,15 @@ public final class DesktopLayout implements JDOMExternalizable {
* if the cached data is invalid.
*/
private WindowInfoImpl[] myAllInfos;
@NonNls public static final String ID_ATTR = "id";
@NonNls private static final String ID_ATTR = "id";
public DesktopLayout() {
myRegisteredId2Info = new HashMap<String, WindowInfoImpl>();
myUnregisteredId2Info = new HashMap<String, WindowInfoImpl>();
}
/**
* Copies itself from the passed
*
* @param layout to be copied.
*/
public final void copyFrom(final DesktopLayout layout) {
public final void copyFrom(@NotNull DesktopLayout layout) {
final WindowInfoImpl[] infos = layout.getAllInfos();
for (WindowInfoImpl info1 : infos) {
WindowInfoImpl info = myRegisteredId2Info.get(info1.getId());
@@ -128,7 +124,7 @@ public final class DesktopLayout implements JDOMExternalizable {
return info;
}
final void unregister(final String id) {
final void unregister(@NotNull String id) {
final WindowInfoImpl info = myRegisteredId2Info.remove(id).copy();
myUnregisteredId2Info.put(id, info);
// invalidate caches
@@ -142,14 +138,12 @@ public final class DesktopLayout implements JDOMExternalizable {
* If <code>onlyRegistered</code> is <code>true</code> then returns not <code>null</code>
* value if and only if window with <code>id</code> is registered one.
*/
final WindowInfoImpl getInfo(final String id, final boolean onlyRegistered) {
final WindowInfoImpl getInfo(String id, final boolean onlyRegistered) {
final WindowInfoImpl info = myRegisteredId2Info.get(id);
if (onlyRegistered || info != null) {
return info;
}
else {
return myUnregisteredId2Info.get(id);
}
return myUnregisteredId2Info.get(id);
}
@Nullable
@@ -166,6 +160,7 @@ public final class DesktopLayout implements JDOMExternalizable {
/**
* @return <code>WindowInfo</code>s for all registered tool windows.
*/
@NotNull
final WindowInfoImpl[] getInfos() {
if (myRegisteredInfos == null) {
myRegisteredInfos = myRegisteredId2Info.values().toArray(new WindowInfoImpl[myRegisteredId2Info.size()]);
@@ -176,6 +171,7 @@ public final class DesktopLayout implements JDOMExternalizable {
/**
* @return <code>WindowInfos</code>s for all windows that are currently unregistered.
*/
@NotNull
private WindowInfoImpl[] getUnregisteredInfos() {
if (myUnregisteredInfos == null) {
myUnregisteredInfos = myUnregisteredId2Info.values().toArray(new WindowInfoImpl[myUnregisteredId2Info.size()]);
@@ -186,7 +182,8 @@ public final class DesktopLayout implements JDOMExternalizable {
/**
* @return <code>WindowInfo</code>s of all (registered and unregistered) tool windows.
*/
WindowInfoImpl[] getAllInfos() {
@NotNull
private WindowInfoImpl[] getAllInfos() {
final WindowInfoImpl[] registeredInfos = getInfos();
final WindowInfoImpl[] unregisteredInfos = getUnregisteredInfos();
myAllInfos = ArrayUtil.mergeArrays(registeredInfos, unregisteredInfos);
@@ -197,9 +194,10 @@ public final class DesktopLayout implements JDOMExternalizable {
* @return all (registered and not unregistered) <code>WindowInfos</code> for the specified <code>anchor</code>.
* Returned infos are sorted by order.
*/
private WindowInfoImpl[] getAllInfos(final ToolWindowAnchor anchor) {
@NotNull
private WindowInfoImpl[] getAllInfos(@NotNull ToolWindowAnchor anchor) {
WindowInfoImpl[] infos = getAllInfos();
final ArrayList<WindowInfoImpl> list = new ArrayList<WindowInfoImpl>(infos.length);
final ArrayList<WindowInfoImpl> list = new ArrayList<>(infos.length);
for (WindowInfoImpl info : infos) {
if (anchor == info.getAnchor()) {
list.add(info);
@@ -214,7 +212,7 @@ public final class DesktopLayout implements JDOMExternalizable {
* Normalizes order of windows in the passed array. Note, that array should be
* sorted by order (by ascending). Order of first window will be <code>0</code>.
*/
private static void normalizeOrder(final WindowInfoImpl[] infos) {
private static void normalizeOrder(@NotNull WindowInfoImpl[] infos) {
for (int i = 0; i < infos.length; i++) {
infos[i].setOrder(i);
}
@@ -228,7 +226,8 @@ public final class DesktopLayout implements JDOMExternalizable {
* @return comparator which compares <code>StripeButtons</code> in the stripe with
* specified <code>anchor</code>.
*/
final Comparator<StripeButton> comparator(final ToolWindowAnchor anchor) {
@NotNull
final Comparator<StripeButton> comparator(@NotNull ToolWindowAnchor anchor) {
return new MyStripeButtonComparator(anchor);
}
@@ -237,7 +236,7 @@ public final class DesktopLayout implements JDOMExternalizable {
* @return maximum ordinal number in the specified stripe. Returns <code>-1</code>
* if there is no any tool window with the specified anchor.
*/
private int getMaxOrder(final ToolWindowAnchor anchor) {
private int getMaxOrder(@NotNull ToolWindowAnchor anchor) {
int res = -1;
final WindowInfoImpl[] infos = getAllInfos();
for (final WindowInfoImpl info : infos) {
@@ -255,7 +254,7 @@ public final class DesktopLayout implements JDOMExternalizable {
* @param newAnchor new anchor
* @param newOrder new order
*/
final void setAnchor(final String id, final ToolWindowAnchor newAnchor, int newOrder) {
final void setAnchor(@NotNull String id, @NotNull ToolWindowAnchor newAnchor, int newOrder) {
if (newOrder == -1) { // if order isn't defined then the window will the last in the stripe
newOrder = getMaxOrder(newAnchor) + 1;
}
@@ -279,11 +278,12 @@ public final class DesktopLayout implements JDOMExternalizable {
}
}
final void setSplitMode(final String id, boolean split) {
final void setSplitMode(@NotNull String id, boolean split) {
final WindowInfoImpl info = getInfo(id, true);
info.setSplit(split);
}
@Override
public final void readExternal(final Element layoutElement) {
myUnregisteredInfos = null;
for (Object o : layoutElement.getChildren()) {
@@ -301,6 +301,7 @@ public final class DesktopLayout implements JDOMExternalizable {
}
}
@Override
public final void writeExternal(final Element layoutElement) {
final WindowInfoImpl[] infos = getAllInfos();
for (WindowInfoImpl info : infos) {
@@ -310,30 +311,30 @@ public final class DesktopLayout implements JDOMExternalizable {
}
}
public List<String> getVisibleIdsOn(final ToolWindowAnchor anchor, ToolWindowManagerImpl manager) {
ArrayList<String> ids = new ArrayList<String>();
@NotNull
List<String> getVisibleIdsOn(@NotNull ToolWindowAnchor anchor, @NotNull ToolWindowManagerImpl manager) {
List<String> ids = new ArrayList<>();
for (WindowInfoImpl each : getAllInfos(anchor)) {
if (manager == null) break;
final ToolWindow window = manager.getToolWindow(each.getId());
if (window == null) continue;
if (window.isAvailable() || UISettings.getInstance().ALWAYS_SHOW_WINDOW_BUTTONS) {
ids.add(each.getId());
}
final ToolWindow window = manager.getToolWindow(each.getId());
if (window == null) continue;
if (window.isAvailable() || UISettings.getInstance().ALWAYS_SHOW_WINDOW_BUTTONS) {
ids.add(each.getId());
}
}
return ids;
}
private static final class MyWindowInfoComparator implements Comparator<WindowInfoImpl> {
@Override
public int compare(final WindowInfoImpl info1, final WindowInfoImpl info2) {
return info1.getOrder() - info2.getOrder();
}
}
private final class MyStripeButtonComparator implements Comparator<StripeButton> {
private final HashMap<String, WindowInfoImpl> myId2Info;
private final HashMap<String, WindowInfoImpl> myId2Info = new HashMap<>();
public MyStripeButtonComparator(final ToolWindowAnchor anchor) {
myId2Info = new HashMap<String, WindowInfoImpl>();
public MyStripeButtonComparator(@NotNull ToolWindowAnchor anchor) {
final WindowInfoImpl[] infos = getInfos();
for (final WindowInfoImpl info : infos) {
if (anchor == info.getAnchor()) {
@@ -342,6 +343,7 @@ public final class DesktopLayout implements JDOMExternalizable {
}
}
@Override
public final int compare(final StripeButton obj1, final StripeButton obj2) {
final WindowInfoImpl info1 = myId2Info.get(obj1.getWindowInfo().getId());
final int order1 = info1 != null ? info1.getOrder() : 0;
@@ -28,6 +28,7 @@ import com.intellij.ui.JBColor;
import com.intellij.ui.ScreenUtil;
import com.intellij.util.Alarm;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -66,7 +67,7 @@ public final class FloatingDecorator extends JDialog {
private float myEndRatio; // start and end alpha ratio for transparency animation
FloatingDecorator(final IdeFrameImpl owner,final WindowInfoImpl info,final InternalDecorator internalDecorator){
FloatingDecorator(final IdeFrameImpl owner, @NotNull WindowInfoImpl info, @NotNull InternalDecorator internalDecorator){
super(owner,internalDecorator.getToolWindow().getId());
MnemonicHelper.init(getContentPane());
myInternalDecorator=internalDecorator;
@@ -154,7 +155,7 @@ public final class FloatingDecorator extends JDialog {
super.dispose();
}
final void apply(final WindowInfoImpl info){
final void apply(@NotNull WindowInfoImpl info){
LOG.assertTrue(info.isFloating());
myInfo=info;
// Set alpha mode
@@ -116,7 +116,7 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr
}
@Override
protected void toolWindowTypeChanged(ToolWindowType type) {
protected void toolWindowTypeChanged(@NotNull ToolWindowType type) {
fireTypeChanged(type);
}
@@ -214,7 +214,7 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr
myProject = null;
}
private void fireAnchorChanged(ToolWindowAnchor anchor) {
private void fireAnchorChanged(@NotNull ToolWindowAnchor anchor) {
myDispatcher.getMulticaster().anchorChanged(this, anchor);
}
@@ -243,7 +243,7 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr
myDispatcher.getMulticaster().activated(this);
}
private void fireTypeChanged(ToolWindowType type) {
private void fireTypeChanged(@NotNull ToolWindowType type) {
myDispatcher.getMulticaster().typeChanged(this, type);
}
@@ -255,7 +255,7 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr
myDispatcher.getMulticaster().sideStatusChanged(this, isSide);
}
private void fireContentUiTypeChanges(ToolWindowContentUiType type) {
private void fireContentUiTypeChanges(@NotNull ToolWindowContentUiType type) {
myDispatcher.getMulticaster().contentUiTypeChanges(this, type);
}
@@ -512,9 +512,9 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr
}
private final class ChangeAnchorAction extends AnAction implements DumbAware {
private final ToolWindowAnchor myAnchor;
@NotNull private final ToolWindowAnchor myAnchor;
public ChangeAnchorAction(final String title, final ToolWindowAnchor anchor) {
public ChangeAnchorAction(@NotNull String title, @NotNull ToolWindowAnchor anchor) {
super(title);
myAnchor = anchor;
}
@@ -27,23 +27,23 @@ import java.util.EventListener;
*/
interface InternalDecoratorListener extends EventListener{
public void anchorChanged(InternalDecorator source,ToolWindowAnchor anchor);
void anchorChanged(@NotNull InternalDecorator source, @NotNull ToolWindowAnchor anchor);
public void autoHideChanged(InternalDecorator source,boolean autoHide);
void autoHideChanged(@NotNull InternalDecorator source, boolean autoHide);
public void hidden(InternalDecorator source);
void hidden(@NotNull InternalDecorator source);
public void hiddenSide(InternalDecorator source);
void hiddenSide(@NotNull InternalDecorator source);
public void resized(InternalDecorator source);
void resized(@NotNull InternalDecorator source);
public void activated(InternalDecorator source);
void activated(@NotNull InternalDecorator source);
public void typeChanged(InternalDecorator source,ToolWindowType type);
void typeChanged(@NotNull InternalDecorator source, @NotNull ToolWindowType type);
public void sideStatusChanged(InternalDecorator source,boolean isSideTool);
void sideStatusChanged(@NotNull InternalDecorator source, boolean isSideTool);
public void contentUiTypeChanges(InternalDecorator sources, @NotNull ToolWindowContentUiType type);
void contentUiTypeChanges(@NotNull InternalDecorator sources, @NotNull ToolWindowContentUiType type);
public void visibleStripeButtonChanged(InternalDecorator source, boolean visible);
void visibleStripeButtonChanged(@NotNull InternalDecorator source, boolean visible);
}
@@ -28,6 +28,7 @@ import com.intellij.ui.ColorUtil;
import com.intellij.ui.Gray;
import com.intellij.ui.ScreenUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.Border;
@@ -166,7 +167,7 @@ final class Stripe extends JPanel implements UISettingsListener {
super.removeNotify();
}
void addButton(final StripeButton button, final Comparator<StripeButton> comparator) {
void addButton(@NotNull StripeButton button, final Comparator<StripeButton> comparator) {
myPrefSize = null;
myButtons.add(button);
Collections.sort(myButtons, comparator);
@@ -174,7 +175,7 @@ final class Stripe extends JPanel implements UISettingsListener {
revalidate();
}
void removeButton(final StripeButton button) {
void removeButton(@NotNull StripeButton button) {
myPrefSize = null;
myButtons.remove(button);
remove(button);
@@ -475,7 +476,7 @@ final class Stripe extends JPanel implements UISettingsListener {
}
}
public boolean containsScreen(final Rectangle screenRec) {
public boolean containsScreen(@NotNull Rectangle screenRec) {
final Point point = screenRec.getLocation();
SwingUtilities.convertPointFromScreen(point, this);
return new Rectangle(point, screenRec.getSize()).intersects(
@@ -49,7 +49,6 @@ import javax.swing.plaf.PanelUI;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
@@ -74,7 +73,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
private final DefaultActionGroup myActionGroup = new DefaultActionGroup();
private List<AnAction> myVisibleActions = ContainerUtil.newArrayListWithCapacity(2);
public ToolWindowHeader(final ToolWindowImpl toolWindow, @NotNull WindowInfoImpl info, @NotNull final Producer<ActionGroup> gearProducer) {
ToolWindowHeader(final ToolWindowImpl toolWindow, @NotNull WindowInfoImpl info, @NotNull final Producer<ActionGroup> gearProducer) {
setLayout(new BorderLayout());
myToolWindow = toolWindow;
@@ -89,7 +88,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
Component c = getComponent(0);
Dimension size = c.getPreferredSize();
if (size.width < (r.width - insets.left - insets.right)) {
if (size.width < r.width - insets.left - insets.right) {
c.setBounds(insets.left, insets.top, size.width, r.height - insets.top - insets.bottom);
} else {
c.setBounds(insets.left, insets.top, r.width - insets.left - insets.right, r.height - insets.top - insets.bottom);
@@ -170,6 +169,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
myButtonPanel = eastPanel;
westPanel.addMouseListener(new PopupHandler() {
@Override
public void invokePopup(final Component comp, final int x, final int y) {
toolWindow.getContentUI().showContextMenu(comp, x, y, toolWindow.getPopupGroup(), toolWindow.getContentManager().getSelectedContent());
}
@@ -182,6 +182,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
});
addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(final MouseEvent e) {
if (!e.isPopupTrigger()) {
if (UIUtil.isCloseClick(e, MouseEvent.MOUSE_RELEASED)) {
@@ -227,7 +228,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
@Override
public void mouseReleased(final MouseEvent e) {
Runnable runnable =
() -> ToolWindowHeader.this.dispatchEvent(SwingUtilities.convertMouseEvent(e.getComponent(), e, ToolWindowHeader.this));
() -> dispatchEvent(SwingUtilities.convertMouseEvent(e.getComponent(), e, ToolWindowHeader.this));
//noinspection SSBasedInspection
SwingUtilities.invokeLater(runnable);
}
@@ -253,7 +254,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
myInfo = null;
}
public void setAdditionalTitleActions(AnAction[] actions) {
void setAdditionalTitleActions(AnAction[] actions) {
myActionGroup.removeAll();
myActionGroup.addAll(actions);
myUpdater.updateActions(false, true);
@@ -300,7 +301,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
if (anchor == ToolWindowAnchor.BOTTOM) {
return AllIcons.General.HideDownPart;
}
else if (anchor == ToolWindowAnchor.RIGHT) {
if (anchor == ToolWindowAnchor.RIGHT) {
return AllIcons.General.HideRightPart;
}
@@ -312,7 +313,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
if (anchor == ToolWindowAnchor.BOTTOM) {
return AllIcons.General.HideDown;
}
else if (anchor == ToolWindowAnchor.RIGHT) {
if (anchor == ToolWindowAnchor.RIGHT) {
return AllIcons.General.HideRight;
}
@@ -324,7 +325,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
if (anchor == ToolWindowAnchor.BOTTOM) {
return AllIcons.General.HideDownPartHover;
}
else if (anchor == ToolWindowAnchor.RIGHT) {
if (anchor == ToolWindowAnchor.RIGHT) {
return AllIcons.General.HideRightPartHover;
}
@@ -336,7 +337,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
if (anchor == ToolWindowAnchor.BOTTOM) {
return AllIcons.General.HideDownHover;
}
else if (anchor == ToolWindowAnchor.RIGHT) {
if (anchor == ToolWindowAnchor.RIGHT) {
return AllIcons.General.HideRightHover;
}
@@ -419,7 +420,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
protected abstract void sideHidden();
protected abstract void toolWindowTypeChanged(ToolWindowType type);
protected abstract void toolWindowTypeChanged(@NotNull ToolWindowType type);
@Override
public Dimension getPreferredSize() {
@@ -468,18 +469,15 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
setIcon(getActiveIcon(), getInactiveIcon() == null ? getActiveIcon() : getInactiveIcon(), getActiveHoveredIcon());
PropertyChangeListener listener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (myAlternativeAction == null) return;
if ("ancestor".equals(evt.getPropertyName())) {
if (evt.getNewValue() == null) {
AltStateManager.getInstance().removeListener(ActionButton.this);
switchAlternativeAction(false);
}
else {
AltStateManager.getInstance().addListener(ActionButton.this);
}
PropertyChangeListener listener = evt -> {
if (myAlternativeAction == null) return;
if ("ancestor".equals(evt.getPropertyName())) {
if (evt.getNewValue() == null) {
AltStateManager.getInstance().removeListener(this);
switchAlternativeAction(false);
}
else {
AltStateManager.getInstance().addListener(this);
}
}
};
@@ -487,7 +485,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
addPropertyChangeListener(listener);
}
public void updateTooltip() {
void updateTooltip() {
myButton.setToolTipText(getToolTipTextByAction(myCurrentAction));
}
@@ -533,6 +531,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
this(action, activeIcon, activeIcon);
}
@Override
public void actionPerformed(final ActionEvent e) {
AnAction action =
myAlternativeAction != null && BitUtil.isSet(e.getModifiers(), InputEvent.ALT_MASK) ? myAlternativeAction : myAction;
@@ -557,6 +556,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
myButton.setIcons(active, inactive, hovered);
}
@Override
public void setToolTipText(final String text) {
myButton.setToolTipText(text);
}
@@ -588,15 +588,17 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
}
private abstract class HideSideAction extends AnAction implements DumbAware {
@NonNls public static final String HIDE_ACTIVE_SIDE_WINDOW_ACTION_ID = ToolWindowHeader.HIDE_ACTIVE_SIDE_WINDOW_ACTION_ID;
@NonNls static final String HIDE_ACTIVE_SIDE_WINDOW_ACTION_ID = ToolWindowHeader.HIDE_ACTIVE_SIDE_WINDOW_ACTION_ID;
public HideSideAction() {
copyFrom(ActionManager.getInstance().getAction(HIDE_ACTIVE_SIDE_WINDOW_ACTION_ID));
getTemplatePresentation().setText(UIBundle.message("tool.window.hideSide.action.name"));
}
@Override
public abstract void actionPerformed(@NotNull final AnActionEvent e);
@Override
public final void update(@NotNull final AnActionEvent event) {
final Presentation presentation = event.getPresentation();
presentation.setEnabled(myInfo.isVisible());
@@ -604,13 +606,14 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS
}
private abstract class HideAction extends AnAction implements DumbAware {
@NonNls public static final String HIDE_ACTIVE_WINDOW_ACTION_ID = ToolWindowHeader.HIDE_ACTIVE_WINDOW_ACTION_ID;
@NonNls static final String HIDE_ACTIVE_WINDOW_ACTION_ID = ToolWindowHeader.HIDE_ACTIVE_WINDOW_ACTION_ID;
public HideAction() {
copyFrom(ActionManager.getInstance().getAction(HIDE_ACTIVE_WINDOW_ACTION_ID));
getTemplatePresentation().setText(UIBundle.message("tool.window.hide.action.name"));
}
@Override
public final void update(@NotNull final AnActionEvent event) {
final Presentation presentation = event.getPresentation();
presentation.setEnabled(myInfo.isVisible());
@@ -53,9 +53,9 @@ import java.beans.PropertyChangeListener;
import java.util.*;
import java.util.List;
@SuppressWarnings({"ConstantConditions"})
@SuppressWarnings("ConstantConditions")
public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
private final Map<String, ToolWindow> myToolWindows = new HashMap<String, ToolWindow>();
private final Map<String, ToolWindow> myToolWindows = new HashMap<>();
private final Project myProject;
public ToolWindowHeadlessManagerImpl(Project project) {
@@ -75,12 +75,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
MockToolWindow tw = new MockToolWindow(myProject);
myToolWindows.put(id, tw);
if (parentDisposable != null) {
Disposer.register(parentDisposable, new Disposable() {
@Override
public void dispose() {
unregisterToolWindow(id);
}
});
Disposer.register(parentDisposable, () -> unregisterToolWindow(id));
}
return tw;
}
@@ -90,7 +85,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
public ToolWindow registerToolWindow(@NotNull String id,
@NotNull JComponent component,
@NotNull ToolWindowAnchor anchor,
Disposable parentDisposable,
@NotNull Disposable parentDisposable,
boolean canWorkInDumbMode) {
return doRegisterToolWindow(id, parentDisposable);
}
@@ -106,7 +101,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
public ToolWindow registerToolWindow(@NotNull String id,
@NotNull JComponent component,
@NotNull ToolWindowAnchor anchor,
Disposable parentDisposable,
@NotNull Disposable parentDisposable,
boolean canWorkInDumbMode,
boolean canCloseContents) {
return doRegisterToolWindow(id, parentDisposable);
@@ -139,7 +134,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
@NotNull
@Override
public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor,
final Disposable parentDisposable, final boolean dumbAware) {
@NotNull final Disposable parentDisposable, final boolean dumbAware) {
return doRegisterToolWindow(id, parentDisposable);
}
@@ -148,7 +143,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
public ToolWindow registerToolWindow(@NotNull String id,
boolean canCloseContent,
@NotNull ToolWindowAnchor anchor,
Disposable parentDisposable,
@NotNull Disposable parentDisposable,
boolean canWorkInDumbMode,
boolean secondary) {
return doRegisterToolWindow(id, parentDisposable);
@@ -222,16 +217,16 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
}
@Override
public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l) {
public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener listener) {
}
@Override
public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l, @NotNull Disposable parentDisposable) {
public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener listener, @NotNull Disposable parentDisposable) {
}
@Override
public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l) {
public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener listener) {
}
@Override
@@ -270,9 +265,10 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
public void hideToolWindow(@NotNull final String id, final boolean hideSide) {
}
@NotNull
@Override
public List<String> getIdsOn(@NotNull final ToolWindowAnchor anchor) {
return new ArrayList<String>();
return new ArrayList<>();
}
public static class MockToolWindow implements ToolWindowEx {
@@ -330,7 +326,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
}
@Override
public void setAnchor(ToolWindowAnchor anchor, @Nullable Runnable runnable) {
public void setAnchor(@NotNull ToolWindowAnchor anchor, @Nullable Runnable runnable) {
}
@Override
@@ -367,7 +363,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
}
@Override
public void setType(ToolWindowType type, @Nullable Runnable runnable) {
public void setType(@NotNull ToolWindowType type, @Nullable Runnable runnable) {
}
@Override
@@ -500,7 +496,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
private static class MockContentManager implements ContentManager {
private final EventDispatcher<ContentManagerListener> myDispatcher = EventDispatcher.create(ContentManagerListener.class);
private final List<Content> myContents = new ArrayList<Content>();
private final List<Content> myContents = new ArrayList<>();
private Content mySelected;
@NotNull
@@ -60,11 +60,11 @@ import java.util.Set;
* @author Vladimir Kondratyev
*/
public final class ToolWindowImpl implements ToolWindowEx {
private final PropertyChangeSupport myChangeSupport;
private final PropertyChangeSupport myChangeSupport = new PropertyChangeSupport(this);
private final ToolWindowManagerImpl myToolWindowManager;
private final String myId;
private final JComponent myComponent;
private boolean myAvailable;
private boolean myAvailable = true;
private final ContentManager myContentManager;
private Icon myIcon;
private String myStripeTitle;
@@ -74,18 +74,18 @@ public final class ToolWindowImpl implements ToolWindowEx {
private InternalDecorator myDecorator;
private boolean myHideOnEmptyContent = false;
private boolean myHideOnEmptyContent;
private boolean myPlaceholderMode;
private ToolWindowFactory myContentFactory;
private static Set<KeyStroke> FORWARD_TRAVERSAL_KEYSTROKES = new HashSet<KeyStroke>(Arrays.asList(
new KeyStroke[] {
private static final Set<KeyStroke> FORWARD_TRAVERSAL_KEYSTROKES = new HashSet<>(Arrays.asList(
new KeyStroke[]{
KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0)
}
));
private static Set<KeyStroke> BACKWARD_TRAVERSAL_KEYSTROKES = new HashSet<KeyStroke>(Arrays.asList(
new KeyStroke[] {
private static final Set<KeyStroke> BACKWARD_TRAVERSAL_KEYSTROKES = new HashSet<>(Arrays.asList(
new KeyStroke[]{
KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_DOWN_MASK)
}
));
@@ -102,16 +102,13 @@ public final class ToolWindowImpl implements ToolWindowEx {
private static final Logger LOG = Logger.getInstance(ToolWindowImpl.class);
ToolWindowImpl(final ToolWindowManagerImpl toolWindowManager, final String id, boolean canCloseContent, @Nullable final JComponent component) {
ToolWindowImpl(@NotNull ToolWindowManagerImpl toolWindowManager, @NotNull String id, boolean canCloseContent, @Nullable final JComponent component) {
myToolWindowManager = toolWindowManager;
myChangeSupport = new PropertyChangeSupport(this);
myId = id;
myAvailable = true;
final ContentFactory contentFactory = ServiceManager.getService(ContentFactory.class);
myContentUI = new ToolWindowContentUi(this);
myContentManager =
contentFactory.createContentManager(myContentUI, canCloseContent, toolWindowManager.getProject());
myContentManager = contentFactory.createContentManager(myContentUI, canCloseContent, toolWindowManager.getProject());
if (component != null) {
final Content content = contentFactory.createContent(component, "", false);
@@ -224,7 +221,7 @@ public final class ToolWindowImpl implements ToolWindowEx {
public ActionCallback getReady(@NotNull final Object requestor) {
final ActionCallback result = new ActionCallback();
myShowing.getReady(this).doWhenDone(() -> {
ArrayList<FinalizableCommand> cmd = new ArrayList<FinalizableCommand>();
ArrayList<FinalizableCommand> cmd = new ArrayList<>();
cmd.add(new FinalizableCommand(null) {
@Override
public void run() {
@@ -268,7 +265,7 @@ public final class ToolWindowImpl implements ToolWindowEx {
}
@Override
public final void setAnchor(final ToolWindowAnchor anchor, @Nullable final Runnable runnable) {
public final void setAnchor(@NotNull final ToolWindowAnchor anchor, @Nullable final Runnable runnable) {
ApplicationManager.getApplication().assertIsDispatchThread();
myToolWindowManager.setToolWindowAnchor(myId, anchor);
if (runnable != null) {
@@ -330,7 +327,7 @@ public final class ToolWindowImpl implements ToolWindowEx {
}
@Override
public final void setType(final ToolWindowType type, @Nullable final Runnable runnable) {
public final void setType(@NotNull final ToolWindowType type, @Nullable final Runnable runnable) {
ApplicationManager.getApplication().assertIsDispatchThread();
myToolWindowManager.setToolWindowType(myId, type);
if (runnable != null) {
@@ -416,6 +413,7 @@ public final class ToolWindowImpl implements ToolWindowEx {
//return getSelectedContent().getIcon();
}
@NotNull
public final String getId() {
return myId;
}
@@ -531,11 +529,11 @@ public final class ToolWindowImpl implements ToolWindowEx {
return myContentManager.isDisposed();
}
public boolean isPlaceholderMode() {
boolean isPlaceholderMode() {
return myPlaceholderMode;
}
public void setPlaceholderMode(final boolean placeholderMode) {
void setPlaceholderMode(final boolean placeholderMode) {
myPlaceholderMode = placeholderMode;
}
@@ -546,7 +544,7 @@ public final class ToolWindowImpl implements ToolWindowEx {
}
@NotNull
public ActionCallback setActivation(@NotNull ActionCallback activation) {
ActionCallback setActivation(@NotNull ActionCallback activation) {
if (!myActivation.isProcessed() && !myActivation.equals(activation)) {
myActivation.setRejected();
}
@@ -95,26 +95,26 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
private final Project myProject;
private final WindowManagerEx myWindowManager;
private final EventDispatcher<ToolWindowManagerListener> myDispatcher = EventDispatcher.create(ToolWindowManagerListener.class);
private final DesktopLayout myLayout;
private final Map<String, InternalDecorator> myId2InternalDecorator;
private final Map<String, FloatingDecorator> myId2FloatingDecorator;
private final Map<String, WindowedDecorator> myId2WindowedDecorator;
private final Map<String, StripeButton> myId2StripeButton;
private final Map<String, FocusWatcher> myId2FocusWatcher;
private final DesktopLayout myLayout = new DesktopLayout();
private final Map<String, InternalDecorator> myId2InternalDecorator = new HashMap<>();
private final Map<String, FloatingDecorator> myId2FloatingDecorator = new HashMap<>();
private final Map<String, WindowedDecorator> myId2WindowedDecorator = new HashMap<>();
private final Map<String, StripeButton> myId2StripeButton = new HashMap<>();
private final Map<String, FocusWatcher> myId2FocusWatcher = new HashMap<>();
private final Set<String> myDumbAwareIds = Collections.synchronizedSet(ContainerUtil.<String>newTroveSet());
private final EditorComponentFocusWatcher myEditorComponentFocusWatcher;
private final MyToolWindowPropertyChangeListener myToolWindowPropertyChangeListener;
private final InternalDecoratorListener myInternalDecoratorListener;
private final EditorComponentFocusWatcher myEditorComponentFocusWatcher = new EditorComponentFocusWatcher();
private final MyToolWindowPropertyChangeListener myToolWindowPropertyChangeListener = new MyToolWindowPropertyChangeListener();
private final InternalDecoratorListener myInternalDecoratorListener = new MyInternalDecoratorListener();
private boolean myEditorWasActive;
private final ActiveStack myActiveStack;
private final SideStack mySideStack;
private final ActiveStack myActiveStack = new ActiveStack();
private final SideStack mySideStack = new SideStack();
private ToolWindowsPane myToolWindowsPane;
private IdeFrameImpl myFrame;
private DesktopLayout myLayoutToRestoreLater = null;
private DesktopLayout myLayoutToRestoreLater;
@NonNls private static final String EDITOR_ELEMENT = "editor";
@NonNls private static final String ACTIVE_ATTR_VALUE = "active";
@NonNls private static final String FRAME_ELEMENT = "frame";
@@ -127,8 +127,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
private final FileEditorManager myFileEditorManager;
private final LafManager myLafManager;
private final Map<String, Balloon> myWindow2Balloon = new HashMap<String, Balloon>();
private Pair<String, Integer> myMaximizedToolwindowSize = null;
private final Map<String, Balloon> myWindow2Balloon = new HashMap<>();
private KeyState myCurrentState = KeyState.waiting;
private final Alarm myWaiterForSecondPress = new Alarm();
@@ -139,7 +138,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
};
private final PropertyChangeListener myFocusListener;
public boolean isToolWindowRegistered(String id) {
boolean isToolWindowRegistered(@NotNull String id) {
return myLayout.isToolWindowRegistered(id);
}
@@ -148,7 +147,6 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
}
private final Alarm myUpdateHeadersAlarm = new Alarm();
private final Runnable myUpdateHeadersRunnable = () -> updateToolWindowHeaders();
/**
* invoked by reflection
@@ -182,22 +180,8 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
}, project);
}
myLayout = new DesktopLayout();
myLayout.copyFrom(windowManagerEx.getLayout());
myId2InternalDecorator = new HashMap<String, InternalDecorator>();
myId2FloatingDecorator = new HashMap<String, FloatingDecorator>();
myId2WindowedDecorator = new HashMap<String, WindowedDecorator>();
myId2StripeButton = new HashMap<String, StripeButton>();
myId2FocusWatcher = new HashMap<String, FocusWatcher>();
myEditorComponentFocusWatcher = new EditorComponentFocusWatcher();
myToolWindowPropertyChangeListener = new MyToolWindowPropertyChangeListener();
myInternalDecoratorListener = new MyInternalDecoratorListener();
myActiveStack = new ActiveStack();
mySideStack = new SideStack();
project.getMessageBus().connect().subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerListener() {
@Override
public void fileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
@@ -220,13 +204,10 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
}
});
myFocusListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("focusOwner".equals(evt.getPropertyName())) {
myUpdateHeadersAlarm.cancelAllRequests();
myUpdateHeadersAlarm.addRequest(myUpdateHeadersRunnable, 50);
}
myFocusListener = evt -> {
if ("focusOwner".equals(evt.getPropertyName())) {
myUpdateHeadersAlarm.cancelAllRequests();
myUpdateHeadersAlarm.addRequest(this::updateToolWindowHeaders, 50);
}
};
KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener(myFocusListener);
@@ -253,7 +234,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
});
}
public boolean dispatchKeyEvent(KeyEvent e) {
public boolean dispatchKeyEvent(@NotNull KeyEvent e) {
if (e.getKeyCode() != KeyEvent.VK_CONTROL &&
e.getKeyCode() != KeyEvent.VK_ALT &&
e.getKeyCode() != KeyEvent.VK_SHIFT &&
@@ -299,8 +280,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
return false;
}
public static Set<Integer> getActivateToolWindowVKs() {
if (ApplicationManager.getApplication() == null) return new HashSet<Integer>();
@NotNull
private static Set<Integer> getActivateToolWindowVKs() {
if (ApplicationManager.getApplication() == null) return new HashSet<>();
Keymap keymap = KeymapManager.getInstance().getActiveKeymap();
Shortcut[] baseShortcut = keymap.getShortcuts("ActivateProjectToolWindow");
@@ -373,7 +355,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
@Override
public void disposeComponent() {
for (String id : new ArrayList<String>(myId2StripeButton.keySet())) {
for (String id : new ArrayList<>(myId2StripeButton.keySet())) {
unregisterToolWindow(id);
}
@@ -390,21 +372,17 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
UIManager.addPropertyChangeListener(uiManagerPropertyListener);
myLafManager.addLafManagerListener(lafManagerListener);
Disposer.register(myProject, new Disposable() {
@Override
public void dispose() {
UIManager.removePropertyChangeListener(uiManagerPropertyListener);
myLafManager.removeLafManagerListener(lafManagerListener);
}
Disposer.register(myProject, () -> {
UIManager.removePropertyChangeListener(uiManagerPropertyListener);
myLafManager.removeLafManagerListener(lafManagerListener);
});
myFrame = myWindowManager.allocateFrame(myProject);
LOG.assertTrue(myFrame != null);
final ArrayList<FinalizableCommand> commandsList = new ArrayList<FinalizableCommand>();
myToolWindowsPane = new ToolWindowsPane(myFrame, this);
Disposer.register(myProject, myToolWindowsPane);
((IdeRootPane)myFrame.getRootPane()).setToolWindowsPane(myToolWindowsPane);
List<FinalizableCommand> commandsList = new ArrayList<>();
appendUpdateToolWindowsPaneCmd(commandsList);
myFrame.setTitle(FrameTitleBuilder.getInstance().getProjectTitle(myProject));
@@ -432,13 +410,10 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
};
myProject.getMessageBus().connect().subscribe(DumbService.DUMB_MODE, dumbModeListener);
StartupManager.getInstance(myProject).registerPostStartupActivity(new DumbAwareRunnable() {
@Override
public void run() {
registerToolWindowsFromBeans();
if (DumbService.getInstance(myProject).isDumb()) {
disableStripeButtons();
}
StartupManager.getInstance(myProject).registerPostStartupActivity((DumbAwareRunnable)() -> {
registerToolWindowsFromBeans();
if (DumbService.getInstance(myProject).isDumb()) {
disableStripeButtons();
}
});
@@ -446,7 +421,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
if (e instanceof KeyEvent) {
dispatchKeyEvent((KeyEvent)e);
}
if (e instanceof WindowEvent && (e.getID() == WindowEvent.WINDOW_LOST_FOCUS) && e.getSource() == myFrame) {
if (e instanceof WindowEvent && e.getID() == WindowEvent.WINDOW_LOST_FOCUS && e.getSource() == myFrame) {
resetHoldState();
}
return false;
@@ -467,7 +442,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
}
}
private JComponent createEditorComponent(Project project) {
private static JComponent createEditorComponent(@NotNull Project project) {
return FrameEditorComponentProvider.EP.getExtensions()[0].createEditorComponent(project);
}
@@ -542,19 +517,16 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
WindowInfoImpl info = getInfo(bean.id);
if (!info.isSplit() && bean.secondary && !info.wasRead()) {
toolWindow.setSplitMode(bean.secondary, null);
toolWindow.setSplitMode(true, null);
}
final ActionCallback activation = toolWindow.setActivation(new ActionCallback());
final DumbAwareRunnable runnable = new DumbAwareRunnable() {
@Override
public void run() {
if (toolWindow.isDisposed()) return;
final DumbAwareRunnable runnable = () -> {
if (toolWindow.isDisposed()) return;
toolWindow.ensureContentInitialized();
activation.setDone();
}
toolWindow.ensureContentInitialized();
activation.setDone();
};
if (ApplicationManager.getApplication().isUnitTestMode()) {
runnable.run();
@@ -566,7 +538,6 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
@Override
public void projectClosed() {
final ArrayList<FinalizableCommand> commandsList = new ArrayList<FinalizableCommand>();
final String[] ids = getToolWindowIds();
// Remove ToolWindowsPane
@@ -574,6 +545,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
((IdeRootPane)myFrame.getRootPane()).setToolWindowsPane(null);
myWindowManager.releaseFrame(myFrame);
}
List<FinalizableCommand> commandsList = new ArrayList<>();
appendUpdateToolWindowsPaneCmd(commandsList);
// Hide all tool windows
@@ -591,18 +563,18 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
}
@Override
public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l) {
myDispatcher.addListener(l);
public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener listener) {
myDispatcher.addListener(listener);
}
@Override
public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l, @NotNull Disposable parentDisposable) {
myDispatcher.addListener(l, parentDisposable);
public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener listener, @NotNull Disposable parentDisposable) {
myDispatcher.addListener(listener, parentDisposable);
}
@Override
public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l) {
myDispatcher.removeListener(l);
public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener listener) {
myDispatcher.removeListener(listener);
}
/**
@@ -641,7 +613,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
final ExpirableRunnable runnable = new ExpirableRunnable.ForProject(myProject) {
@Override
public void run() {
final ArrayList<FinalizableCommand> commandList = new ArrayList<FinalizableCommand>();
List<FinalizableCommand> commandList = new ArrayList<>();
activateEditorComponentImpl(commandList, forced);
execute(commandList);
}
@@ -669,15 +641,14 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
}
}
private void activateEditorComponentImpl(List<FinalizableCommand> commandList, final boolean forced) {
private void activateEditorComponentImpl(@NotNull List<FinalizableCommand> commandList, final boolean forced) {
final String active = getActiveToolWindowId();
// Now we have to request focus into most recent focused editor
appendRequestFocusInEditorComponentCmd(commandList, forced).doWhenDone(() -> {
final ArrayList<FinalizableCommand> commandList12 = new ArrayList<FinalizableCommand>();
if (LOG.isDebugEnabled()) {
LOG.debug("editor activated");
}
List<FinalizableCommand> commandList12 = new ArrayList<>();
deactivateWindows(null, commandList12);
myActiveStack.clear();
@@ -688,9 +659,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
@NotNull
@Override
public ActionCallback run() {
final ArrayList<FinalizableCommand> commandList1 = new ArrayList<FinalizableCommand>();
List<FinalizableCommand> commandList1 = new ArrayList<>();
final WindowInfoImpl toReactivate = getInfo(active);
final WindowInfoImpl toReactivate = active == null ? null : getInfo(active);
final boolean reactivateLastActive = toReactivate != null && !isToHideOnDeactivation(toReactivate);
deactivateWindows(reactivateLastActive ? active : null, commandList1);
execute(commandList1);
@@ -714,7 +685,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
});
}
private void deactivateWindows( @Nullable String idToIgnore, final List<FinalizableCommand> commandList) {
private void deactivateWindows(@Nullable String idToIgnore, @NotNull List<FinalizableCommand> commandList) {
final WindowInfoImpl[] infos = myLayout.getInfos();
for (final WindowInfoImpl info : infos) {
if (idToIgnore != null && idToIgnore.equals(info.getId())) {
@@ -736,11 +707,10 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
*
* @param dirtyMode if <code>true</code> then all UI operations are performed in "dirty" mode.
* It means that UI isn't validated and repainted just after each add/remove operation.
* @see ToolWindowManagerImpl#prepareForActivation
*/
private void showAndActivate(final String id,
private void showAndActivate(@NotNull String id,
final boolean dirtyMode,
List<FinalizableCommand> commandsList,
@NotNull List<FinalizableCommand> commandsList,
boolean autoFocusContents,
boolean forcedFocusRequest) {
if (!getToolWindow(id).isAvailable()) {
@@ -766,7 +736,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
}
}
void activateToolWindow(final String id, boolean forced, boolean autoFocusContents) {
void activateToolWindow(@NotNull String id, boolean forced, boolean autoFocusContents) {
if (LOG.isDebugEnabled()) {
LOG.debug("enter: activateToolWindow(" + id + ")");
}
@@ -776,13 +746,13 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
return;
}
final ArrayList<FinalizableCommand> commandList = new ArrayList<FinalizableCommand>();
List<FinalizableCommand> commandList = new ArrayList<>();
activateToolWindowImpl(id, commandList, forced, autoFocusContents);
execute(commandList);
}
private void activateToolWindowImpl(final String id,
List<FinalizableCommand> commandList,
private void activateToolWindowImpl(@NotNull String id,
@NotNull List<FinalizableCommand> commandList,
boolean forced,
boolean autoFocusContents) {
if (!FocusManagerImpl.getInstance().isUnforcedRequestAllowed() && !forced) return;
@@ -810,7 +780,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
*
* @throws IllegalStateException if tool window isn't installed.
*/
private void checkId(final String id) {
private void checkId(@NotNull String id) {
if (!myLayout.isToolWindowRegistered(id)) {
throw new IllegalStateException("window with id=\"" + id + "\" isn't registered");
}
@@ -822,7 +792,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
* @param id <code>id</code> of the tool window to be deactivated.
* @param shouldHide if <code>true</code> then also hides specified tool window.
*/
private void deactivateToolWindowImpl(final String id, final boolean shouldHide, final List<FinalizableCommand> commandsList) {
private void deactivateToolWindowImpl(@NotNull String id, final boolean shouldHide, @NotNull List<FinalizableCommand> commandsList) {
if (LOG.isDebugEnabled()) {
LOG.debug("enter: deactivateToolWindowImpl(" + id + "," + shouldHide + ")");
}
@@ -887,37 +857,38 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
/**
* @return floating decorator for the tool window with specified <code>ID</code>.
*/
private FloatingDecorator getFloatingDecorator(final String id) {
private FloatingDecorator getFloatingDecorator(@NotNull String id) {
return myId2FloatingDecorator.get(id);
}
/**
* @return windowed decorator for the tool window with specified <code>ID</code>.
*/
private WindowedDecorator getWindowedDecorator(String id) {
private WindowedDecorator getWindowedDecorator(@NotNull String id) {
return myId2WindowedDecorator.get(id);
}
/**
* @return internal decorator for the tool window with specified <code>ID</code>.
*/
private InternalDecorator getInternalDecorator(final String id) {
private InternalDecorator getInternalDecorator(@NotNull String id) {
return myId2InternalDecorator.get(id);
}
/**
* @return tool button for the window with specified <code>ID</code>.
*/
private StripeButton getStripeButton(final String id) {
private StripeButton getStripeButton(@NotNull String id) {
return myId2StripeButton.get(id);
}
/**
* @return info for the tool window with specified <code>ID</code>.
*/
private WindowInfoImpl getInfo(final String id) {
private WindowInfoImpl getInfo(@NotNull String id) {
return myLayout.getInfo(id, true);
}
@Override
@NotNull
public List<String> getIdsOn(@NotNull final ToolWindowAnchor anchor) {
return myLayout.getVisibleIdsOn(anchor, this);
}
@@ -931,12 +902,12 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
return decorator != null ? decorator.getToolWindow() : null;
}
void showToolWindow(final String id) {
void showToolWindow(@NotNull String id) {
if (LOG.isDebugEnabled()) {
LOG.debug("enter: showToolWindow(" + id + ")");
}
ApplicationManager.getApplication().assertIsDispatchThread();
final ArrayList<FinalizableCommand> commandList = new ArrayList<FinalizableCommand>();
List<FinalizableCommand> commandList = new ArrayList<>();
showToolWindowImpl(id, false, commandList);
execute(commandList);
}
@@ -946,12 +917,12 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
hideToolWindow(id, hideSide, true);
}
public void hideToolWindow(final String id, final boolean hideSide, final boolean moveFocus) {
public void hideToolWindow(@NotNull String id, final boolean hideSide, final boolean moveFocus) {
ApplicationManager.getApplication().assertIsDispatchThread();
checkId(id);
final WindowInfoImpl info = getInfo(id);
if (!info.isVisible()) return;
final ArrayList<FinalizableCommand> commandList = new ArrayList<FinalizableCommand>();
List<FinalizableCommand> commandList = new ArrayList<>();
final boolean wasActive = info.isActive();
// hide and deactivate
@@ -1024,7 +995,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
}
else {
final String toBeActivatedId = myActiveStack.pop();
if (toBeActivatedId != null && (getInfo(toBeActivatedId).isVisible() || isStackEnabled())) {
if (getInfo(toBeActivatedId).isVisible() || isStackEnabled()) {
activateToolWindowImpl(toBeActivatedId, commandList, false, true);
}
else {
@@ -1044,7 +1015,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
/**
* @param dirtyMode if <code>true</code> then all UI operations are performed in dirty mode.
*/
private void showToolWindowImpl(final String id, final boolean dirtyMode, final List<FinalizableCommand> commandsList) {
private void showToolWindowImpl(@NotNull String id, final boolean dirtyMode, @NotNull List<FinalizableCommand> commandsList) {
final WindowInfoImpl toBeShownInfo = getInfo(id);
if (toBeShownInfo.isVisible() || !getToolWindow(id).isAvailable()) {
return;
@@ -1184,7 +1155,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
public ToolWindow registerToolWindow(@NotNull String id,
boolean canCloseContent,
@NotNull ToolWindowAnchor anchor,
Disposable parentDisposable,
@NotNull Disposable parentDisposable,
boolean canWorkInDumbMode,
boolean secondary) {
ToolWindow window = registerToolWindow(id, null, anchor, secondary, canCloseContent, canWorkInDumbMode);
@@ -1226,7 +1197,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
final StripeButton button = new StripeButton(decorator, myToolWindowsPane);
myId2StripeButton.put(id, button);
List<FinalizableCommand> commandsList = new ArrayList<FinalizableCommand>();
List<FinalizableCommand> commandsList = new ArrayList<>();
appendAddButtonCmd(button, info, commandsList);
if (canWorkInDumbMode) {
@@ -1260,12 +1231,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
@NotNull
private ToolWindow registerDisposable(@NotNull final String id, @NotNull final Disposable parentDisposable, @NotNull ToolWindow window) {
Disposer.register(parentDisposable, new Disposable() {
@Override
public void dispose() {
unregisterToolWindow(id);
}
});
Disposer.register(parentDisposable, () -> unregisterToolWindow(id));
return window;
}
@@ -1284,7 +1250,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
// Save recent appearance of tool window
myLayout.unregister(id);
// Remove decorator and tool button from the screen
final ArrayList<FinalizableCommand> commandsList = new ArrayList<FinalizableCommand>();
List<FinalizableCommand> commandsList = new ArrayList<>();
if (info.isVisible()) {
info.setVisible(false);
if (info.isFloating()) {
@@ -1338,7 +1304,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
@Override
public void setLayout(@NotNull final DesktopLayout layout) {
ApplicationManager.getApplication().assertIsDispatchThread();
final ArrayList<FinalizableCommand> commandList = new ArrayList<FinalizableCommand>();
List<FinalizableCommand> commandList = new ArrayList<>();
// hide tool window that are invisible in new layout
final WindowInfoImpl[] currentInfos = myLayout.getInfos();
for (final WindowInfoImpl currentInfo : currentInfos) {
@@ -1400,7 +1366,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
@Override
public void invokeLater(@NotNull final Runnable runnable) {
List<FinalizableCommand> commandList = new ArrayList<FinalizableCommand>();
List<FinalizableCommand> commandList = new ArrayList<>();
commandList.add(new InvokeLaterCmd(runnable, myWindowManager.getCommandProcessor()));
execute(commandList);
}
@@ -1480,19 +1446,16 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
});
listenerWrapper.myBalloon = balloon;
myWindow2Balloon.put(toolWindowId, balloon);
Disposer.register(balloon, new Disposable() {
@Override
public void dispose() {
window.setPlaceholderMode(false);
stripe.updatePresentation();
stripe.revalidate();
stripe.repaint();
myWindow2Balloon.remove(toolWindowId);
}
Disposer.register(balloon, () -> {
window.setPlaceholderMode(false);
stripe.updatePresentation();
stripe.revalidate();
stripe.repaint();
myWindow2Balloon.remove(toolWindowId);
});
Disposer.register(getProject(), balloon);
execute(new ArrayList<FinalizableCommand>(Arrays.<FinalizableCommand>asList(new FinalizableCommand(null) {
execute(new ArrayList<>(Collections.<FinalizableCommand>singletonList(new FinalizableCommand(null) {
@Override
public void run() {
final StripeButton button = stripe.getButtonFor(toolWindowId);
@@ -1550,7 +1513,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
};
if (!button.isValid()) {
SwingUtilities.invokeLater(() -> show.run());
SwingUtilities.invokeLater(show);
}
else {
show.run();
@@ -1573,27 +1536,28 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
return splitters != null;
}
ToolWindowAnchor getToolWindowAnchor(final String id) {
@NotNull
ToolWindowAnchor getToolWindowAnchor(@NotNull String id) {
checkId(id);
return getInfo(id).getAnchor();
}
void setToolWindowAnchor(final String id, final ToolWindowAnchor anchor) {
void setToolWindowAnchor(@NotNull String id, @NotNull ToolWindowAnchor anchor) {
ApplicationManager.getApplication().assertIsDispatchThread();
setToolWindowAnchor(id, anchor, -1);
}
void setToolWindowAnchor(final String id, final ToolWindowAnchor anchor, final int order) {
private void setToolWindowAnchor(@NotNull String id, @NotNull ToolWindowAnchor anchor, final int order) {
ApplicationManager.getApplication().assertIsDispatchThread();
final ArrayList<FinalizableCommand> commandList = new ArrayList<FinalizableCommand>();
List<FinalizableCommand> commandList = new ArrayList<>();
setToolWindowAnchorImpl(id, anchor, order, commandList);
execute(commandList);
}
private void setToolWindowAnchorImpl(final String id,
final ToolWindowAnchor anchor,
private void setToolWindowAnchorImpl(@NotNull String id,
@NotNull ToolWindowAnchor anchor,
final int order,
final ArrayList<FinalizableCommand> commandsList) {
@NotNull List<FinalizableCommand> commandsList) {
checkId(id);
final WindowInfoImpl info = getInfo(id);
if (anchor == info.getAnchor() && order == info.getOrder()) {
@@ -1630,42 +1594,42 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
}
}
boolean isSplitMode(String id) {
boolean isSplitMode(@NotNull String id) {
ApplicationManager.getApplication().assertIsDispatchThread();
checkId(id);
return getInfo(id).isSplit();
}
@NotNull
ToolWindowContentUiType getContentUiType(String id) {
ToolWindowContentUiType getContentUiType(@NotNull String id) {
ApplicationManager.getApplication().assertIsDispatchThread();
checkId(id);
return getInfo(id).getContentUiType();
}
void setSideTool(String id, boolean isSide) {
final ArrayList<FinalizableCommand> commandList = new ArrayList<FinalizableCommand>();
void setSideTool(@NotNull String id, boolean isSide) {
List<FinalizableCommand> commandList = new ArrayList<>();
setSplitModeImpl(id, isSide, commandList);
execute(commandList);
}
public void setContentUiType(String id, @NotNull ToolWindowContentUiType type) {
final ArrayList<FinalizableCommand> commandList = new ArrayList<FinalizableCommand>();
void setContentUiType(@NotNull String id, @NotNull ToolWindowContentUiType type) {
checkId(id);
WindowInfoImpl info = getInfo(id);
info.setContentUiType(type);
List<FinalizableCommand> commandList = new ArrayList<>();
appendApplyWindowInfoCmd(info, commandList);
execute(commandList);
}
void setSideToolAndAnchor(String id, ToolWindowAnchor anchor, int order, boolean isSide) {
final ArrayList<FinalizableCommand> commandList = new ArrayList<FinalizableCommand>();
void setSideToolAndAnchor(@NotNull String id, @NotNull ToolWindowAnchor anchor, int order, boolean isSide) {
setToolWindowAnchor(id, anchor, order);
List<FinalizableCommand> commandList = new ArrayList<>();
setSplitModeImpl(id, isSide, commandList);
execute(commandList);
}
private void setSplitModeImpl(final String id, final boolean isSplit, final ArrayList<FinalizableCommand> commandList) {
private void setSplitModeImpl(@NotNull String id, final boolean isSplit, @NotNull List<FinalizableCommand> commandList) {
checkId(id);
final WindowInfoImpl info = getInfo(id);
if (isSplit == info.isSplit()) {
@@ -1688,18 +1652,18 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
commandList.add(myToolWindowsPane.createUpdateButtonPositionCmd(id, myWindowManager.getCommandProcessor()));
}
ToolWindowType getToolWindowInternalType(final String id) {
ToolWindowType getToolWindowInternalType(@NotNull String id) {
ApplicationManager.getApplication().assertIsDispatchThread();
checkId(id);
return getInfo(id).getInternalType();
}
ToolWindowType getToolWindowType(final String id) {
ToolWindowType getToolWindowType(@NotNull String id) {
checkId(id);
return getInfo(id).getType();
}
private void fireToolWindowRegistered(final String id) {
private void fireToolWindowRegistered(@NotNull String id) {
myDispatcher.getMulticaster().toolWindowRegistered(id);
}
@@ -1707,31 +1671,31 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
myDispatcher.getMulticaster().stateChanged();
}
boolean isToolWindowActive(final String id) {
boolean isToolWindowActive(@NotNull String id) {
ApplicationManager.getApplication().assertIsDispatchThread();
checkId(id);
return getInfo(id).isActive();
}
boolean isToolWindowAutoHide(final String id) {
boolean isToolWindowAutoHide(@NotNull String id) {
ApplicationManager.getApplication().assertIsDispatchThread();
checkId(id);
return getInfo(id).isAutoHide();
}
boolean isToolWindowVisible(final String id) {
boolean isToolWindowVisible(@NotNull String id) {
checkId(id);
return getInfo(id).isVisible();
}
void setToolWindowAutoHide(final String id, final boolean autoHide) {
void setToolWindowAutoHide(@NotNull String id, final boolean autoHide) {
ApplicationManager.getApplication().assertIsDispatchThread();
final ArrayList<FinalizableCommand> commandList = new ArrayList<FinalizableCommand>();
List<FinalizableCommand> commandList = new ArrayList<>();
setToolWindowAutoHideImpl(id, autoHide, commandList);
execute(commandList);
}
private void setToolWindowAutoHideImpl(final String id, final boolean autoHide, final ArrayList<FinalizableCommand> commandsList) {
private void setToolWindowAutoHideImpl(@NotNull String id, final boolean autoHide, @NotNull List<FinalizableCommand> commandsList) {
checkId(id);
final WindowInfoImpl info = getInfo(id);
if (info.isAutoHide() == autoHide) {
@@ -1745,14 +1709,14 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
}
}
void setToolWindowType(final String id, final ToolWindowType type) {
void setToolWindowType(@NotNull String id, @NotNull ToolWindowType type) {
ApplicationManager.getApplication().assertIsDispatchThread();
final ArrayList<FinalizableCommand> commandList = new ArrayList<FinalizableCommand>();
List<FinalizableCommand> commandList = new ArrayList<>();
setToolWindowTypeImpl(id, type, commandList);
execute(commandList);
}
private void setToolWindowTypeImpl(final String id, final ToolWindowType type, final ArrayList<FinalizableCommand> commandsList) {
private void setToolWindowTypeImpl(@NotNull String id, @NotNull ToolWindowType type, @NotNull List<FinalizableCommand> commandsList) {
checkId(id);
final WindowInfoImpl info = getInfo(id);
if (info.getType() == type) {
@@ -1782,7 +1746,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
}
}
private void appendApplyWindowInfoCmd(final WindowInfoImpl info, final List<FinalizableCommand> commandsList) {
private void appendApplyWindowInfoCmd(@NotNull WindowInfoImpl info, @NotNull List<FinalizableCommand> commandsList) {
final StripeButton button = getStripeButton(info.getId());
final InternalDecorator decorator = getInternalDecorator(info.getId());
commandsList.add(new ApplyWindowInfoCmd(info, button, decorator, myWindowManager.getCommandProcessor()));
@@ -1791,10 +1755,10 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
/**
* @see ToolWindowsPane#createAddDecoratorCmd
*/
private void appendAddDecoratorCmd(final InternalDecorator decorator,
final WindowInfoImpl info,
private void appendAddDecoratorCmd(@NotNull InternalDecorator decorator,
@NotNull WindowInfoImpl info,
final boolean dirtyMode,
final List<FinalizableCommand> commandsList) {
@NotNull List<FinalizableCommand> commandsList) {
final CommandProcessor commandProcessor = myWindowManager.getCommandProcessor();
final FinalizableCommand command = myToolWindowsPane.createAddDecoratorCmd(decorator, info, dirtyMode, commandProcessor);
commandsList.add(command);
@@ -1803,17 +1767,17 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
/**
* @see ToolWindowsPane#createRemoveDecoratorCmd
*/
private void appendRemoveDecoratorCmd(final String id, final boolean dirtyMode, final List<FinalizableCommand> commandsList) {
private void appendRemoveDecoratorCmd(@NotNull String id, final boolean dirtyMode, @NotNull List<FinalizableCommand> commandsList) {
final FinalizableCommand command = myToolWindowsPane.createRemoveDecoratorCmd(id, dirtyMode, myWindowManager.getCommandProcessor());
commandsList.add(command);
}
private void appendRemoveFloatingDecoratorCmd(final WindowInfoImpl info, final List<FinalizableCommand> commandsList) {
private void appendRemoveFloatingDecoratorCmd(@NotNull WindowInfoImpl info, @NotNull List<FinalizableCommand> commandsList) {
final RemoveFloatingDecoratorCmd command = new RemoveFloatingDecoratorCmd(info);
commandsList.add(command);
}
private void appendRemoveWindowedDecoratorCmd(final WindowInfoImpl info, final List<FinalizableCommand> commandsList) {
private void appendRemoveWindowedDecoratorCmd(@NotNull WindowInfoImpl info, @NotNull List<FinalizableCommand> commandsList) {
final RemoveWindowedDecoratorCmd command = new RemoveWindowedDecoratorCmd(info);
commandsList.add(command);
}
@@ -1821,7 +1785,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
/**
* @see ToolWindowsPane#createAddButtonCmd
*/
private void appendAddButtonCmd(final StripeButton button, final WindowInfoImpl info, final List<FinalizableCommand> commandsList) {
private void appendAddButtonCmd(final StripeButton button, @NotNull WindowInfoImpl info, @NotNull List<FinalizableCommand> commandsList) {
final Comparator<StripeButton> comparator = myLayout.comparator(info.getAnchor());
final CommandProcessor commandProcessor = myWindowManager.getCommandProcessor();
final FinalizableCommand command = myToolWindowsPane.createAddButtonCmd(button, info, comparator, commandProcessor);
@@ -1831,7 +1795,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
/**
* @see ToolWindowsPane#createAddButtonCmd
*/
private void appendRemoveButtonCmd(final String id, final List<FinalizableCommand> commandsList) {
private void appendRemoveButtonCmd(@NotNull String id, @NotNull List<FinalizableCommand> commandsList) {
final FinalizableCommand command = myToolWindowsPane.createRemoveButtonCmd(id, myWindowManager.getCommandProcessor());
commandsList.add(command);
}
@@ -1855,7 +1819,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
/**
* @see ToolWindowsPane#createSetEditorComponentCmd
*/
public void appendSetEditorComponentCmd(@Nullable final JComponent component, final List<FinalizableCommand> commandsList) {
private void appendSetEditorComponentCmd(@Nullable final JComponent component, @NotNull List<FinalizableCommand> commandsList) {
final CommandProcessor commandProcessor = myWindowManager.getCommandProcessor();
final FinalizableCommand command = myToolWindowsPane.createSetEditorComponentCmd(component, commandProcessor);
commandsList.add(command);
@@ -1885,36 +1849,6 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
return splitters != null ? splitters : fem.getSplitters();
}
/**
* @return <code>true</code> if tool window with the specified <code>id</code>
* is floating and has modal showing child dialog. Such windows should not be closed
* when auto-hide windows are gone.
*/
private boolean hasModalChild(final WindowInfoImpl info) {
if (!info.isVisible() || !info.isFloating()) {
return false;
}
final FloatingDecorator decorator = getFloatingDecorator(info.getId());
LOG.assertTrue(decorator != null);
return isModalOrHasModalChild(decorator);
}
private static boolean isModalOrHasModalChild(final Window window) {
if (window instanceof Dialog) {
final Dialog dialog = (Dialog)window;
if (dialog.isModal() && dialog.isShowing()) {
return true;
}
final Window[] ownedWindows = dialog.getOwnedWindows();
for (int i = ownedWindows.length - 1; i >= 0; i--) {
if (isModalOrHasModalChild(ownedWindows[i])) {
return true;
}
}
}
return false;
}
@Override
public void clearSideStack() {
mySideStack.clear();
@@ -2000,14 +1934,14 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
}
}
public void setDefaultContentUiType(ToolWindowImpl toolWindow, @NotNull ToolWindowContentUiType type) {
void setDefaultContentUiType(@NotNull ToolWindowImpl toolWindow, @NotNull ToolWindowContentUiType type) {
final WindowInfoImpl info = getInfo(toolWindow.getId());
if (info.wasRead()) return;
toolWindow.setContentUiType(type, null);
}
public void stretchWidth(ToolWindowImpl toolWindow, int value) {
void stretchWidth(@NotNull ToolWindowImpl toolWindow, int value) {
myToolWindowsPane.stretchWidth(toolWindow, value);
}
@@ -2021,7 +1955,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
myToolWindowsPane.setMaximized(wnd, maximized);
}
public void stretchHeight(ToolWindowImpl toolWindow, int value) {
void stretchHeight(ToolWindowImpl toolWindow, int value) {
myToolWindowsPane.stretchHeight(toolWindow, value);
}
@@ -2029,7 +1963,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
private Balloon myBalloon;
private final HyperlinkListener myListener;
public BalloonHyperlinkListener(HyperlinkListener listener) {
BalloonHyperlinkListener(HyperlinkListener listener) {
myListener = listener;
}
@@ -2054,7 +1988,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
/**
* Creates floating decorator for specified internal decorator.
*/
private AddFloatingDecoratorCmd(final InternalDecorator decorator, final WindowInfoImpl info) {
private AddFloatingDecoratorCmd(@NotNull InternalDecorator decorator, @NotNull WindowInfoImpl info) {
super(myWindowManager.getCommandProcessor());
myFloatingDecorator = new FloatingDecorator(myFrame, info.copy(), decorator);
myId2FloatingDecorator.put(info.getId(), myFloatingDecorator);
@@ -2093,7 +2027,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
private final class RemoveFloatingDecoratorCmd extends FinalizableCommand {
private final FloatingDecorator myFloatingDecorator;
private RemoveFloatingDecoratorCmd(final WindowInfoImpl info) {
private RemoveFloatingDecoratorCmd(@NotNull WindowInfoImpl info) {
super(myWindowManager.getCommandProcessor());
myFloatingDecorator = getFloatingDecorator(info.getId());
myId2FloatingDecorator.remove(info.getId());
@@ -2126,7 +2060,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
/**
* Creates windowed decorator for specified internal decorator.
*/
private AddWindowedDecoratorCmd(final InternalDecorator decorator, final WindowInfoImpl info) {
private AddWindowedDecoratorCmd(@NotNull InternalDecorator decorator, @NotNull WindowInfoImpl info) {
super(myWindowManager.getCommandProcessor());
myWindowedDecorator = new WindowedDecorator(myProject, info.copy(), decorator);
Window window = myWindowedDecorator.getFrame();
@@ -2146,12 +2080,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
window.setLocationRelativeTo(myFrame);
}
myId2WindowedDecorator.put(info.getId(), myWindowedDecorator);
myWindowedDecorator.addDisposable(new Disposable() {
@Override
public void dispose() {
if (myId2WindowedDecorator.get(info.getId()) != null) {
hideToolWindow(info.getId(), false);
}
myWindowedDecorator.addDisposable(() -> {
if (myId2WindowedDecorator.get(info.getId()) != null) {
hideToolWindow(info.getId(), false);
}
});
}
@@ -2183,7 +2114,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
private final class RemoveWindowedDecoratorCmd extends FinalizableCommand {
private final WindowedDecorator myWindowedDecorator;
private RemoveWindowedDecoratorCmd(final WindowInfoImpl info) {
private RemoveWindowedDecoratorCmd(@NotNull WindowInfoImpl info) {
super(myWindowManager.getCommandProcessor());
myWindowedDecorator = getWindowedDecorator(info.getId());
myId2WindowedDecorator.remove(info.getId());
@@ -2255,8 +2186,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
private final String myId;
private final ToolWindowImpl myToolWindow;
private ToolWindowFocusWatcher(final ToolWindowImpl toolWindow) {
private ToolWindowFocusWatcher(@NotNull ToolWindowImpl toolWindow) {
myId = toolWindow.getId();
install(toolWindow.getComponent());
myToolWindow = toolWindow;
@@ -2317,27 +2247,27 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
*/
private final class MyInternalDecoratorListener implements InternalDecoratorListener {
@Override
public void anchorChanged(final InternalDecorator source, final ToolWindowAnchor anchor) {
public void anchorChanged(@NotNull final InternalDecorator source, @NotNull final ToolWindowAnchor anchor) {
setToolWindowAnchor(source.getToolWindow().getId(), anchor);
}
@Override
public void autoHideChanged(final InternalDecorator source, final boolean autoHide) {
public void autoHideChanged(@NotNull final InternalDecorator source, final boolean autoHide) {
setToolWindowAutoHide(source.getToolWindow().getId(), autoHide);
}
@Override
public void hidden(final InternalDecorator source) {
public void hidden(@NotNull final InternalDecorator source) {
hideToolWindow(source.getToolWindow().getId(), false);
}
@Override
public void hiddenSide(final InternalDecorator source) {
public void hiddenSide(@NotNull final InternalDecorator source) {
hideToolWindow(source.getToolWindow().getId(), true);
}
@Override
public void contentUiTypeChanges(InternalDecorator source, @NotNull ToolWindowContentUiType type) {
public void contentUiTypeChanges(@NotNull InternalDecorator source, @NotNull ToolWindowContentUiType type) {
setContentUiType(source.getToolWindow().getId(), type);
}
@@ -2346,13 +2276,12 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
* tool window depending on decoration type.
*/
@Override
public void resized(final InternalDecorator source) {
public void resized(@NotNull final InternalDecorator source) {
if (!source.isShowing()) {
return; // do not recalculate the tool window size if it is not yet shown (and, therefore, has 0,0,0,0 bounds)
}
final WindowInfoImpl info = getInfo(source.getToolWindow().getId());
InternalDecorator another = null;
if (info.isFloating()) {
final Window owner = SwingUtilities.getWindowAncestor(source);
if (owner != null) {
@@ -2367,6 +2296,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
}
else { // docked and sliding windows
ToolWindowAnchor anchor = info.getAnchor();
InternalDecorator another = null;
if (source.getParent() instanceof Splitter) {
float sizeInSplit = anchor.isSplitVertically() ? source.getHeight() : source.getWidth();
Splitter splitter = (Splitter)source.getParent();
@@ -2399,21 +2329,22 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
}
@Override
public void activated(final InternalDecorator source) {
public void activated(@NotNull final InternalDecorator source) {
activateToolWindow(source.getToolWindow().getId(), true, true);
}
@Override
public void typeChanged(final InternalDecorator source, final ToolWindowType type) {
public void typeChanged(@NotNull final InternalDecorator source, @NotNull final ToolWindowType type) {
setToolWindowType(source.getToolWindow().getId(), type);
}
@Override
public void sideStatusChanged(final InternalDecorator source, final boolean isSideTool) {
public void sideStatusChanged(@NotNull final InternalDecorator source, final boolean isSideTool) {
setSideTool(source.getToolWindow().getId(), isSideTool);
}
public void visibleStripeButtonChanged(InternalDecorator source, boolean visible) {
@Override
public void visibleStripeButtonChanged(@NotNull InternalDecorator source, boolean visible) {
setShowStripeButton(source.getToolWindow().getId(), visible);
}
}
@@ -2546,11 +2477,12 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
return IdeFocusManager.getInstance(myProject).dispatch(e);
}
@NotNull
public Expirable getTimestamp(boolean trackOnlyForcedCommands) {
return IdeFocusManager.getInstance(myProject).getTimestamp(trackOnlyForcedCommands);
}
public void setShowStripeButton(String id, boolean visibleOnPanel) {
void setShowStripeButton(@NotNull String id, boolean visibleOnPanel) {
checkId(id);
WindowInfoImpl info = getInfo(id);
if (visibleOnPanel == info.isShowStripeButton()) {
@@ -2559,12 +2491,12 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
info.setShowStripeButton(visibleOnPanel);
UsageTrigger.trigger("StripeButton[" + id + "]." + (visibleOnPanel ? "shown" : "hidden"));
final ArrayList<FinalizableCommand> commandList = new ArrayList<FinalizableCommand>();
List<FinalizableCommand> commandList = new ArrayList<>();
appendApplyWindowInfoCmd(info, commandList);
execute(commandList);
}
public boolean isShowStripeButton(String id) {
boolean isShowStripeButton(@NotNull String id) {
WindowInfoImpl info = getInfo(id);
return info == null || info.isShowStripeButton();
}
@@ -42,10 +42,10 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.ref.Reference;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
/**
* This panel contains all tool stripes and JLayeredPanle at the center area. All tool windows are
@@ -59,12 +59,12 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
private final IdeFrameImpl myFrame;
private final HashMap<String, StripeButton> myId2Button;
private final HashMap<String, InternalDecorator> myId2Decorator;
private final HashMap<StripeButton, WindowInfoImpl> myButton2Info;
private final HashMap<InternalDecorator, WindowInfoImpl> myDecorator2Info;
private final HashMap<String, Float> myId2SplitProportion;
private Pair<ToolWindow, Integer> myMaximizedProportion = null;
private final HashMap<String, StripeButton> myId2Button = new HashMap<>();
private final HashMap<String, InternalDecorator> myId2Decorator = new HashMap<>();
private final HashMap<StripeButton, WindowInfoImpl> myButton2Info = new HashMap<>();
private final HashMap<InternalDecorator, WindowInfoImpl> myDecorator2Info = new HashMap<>();
private final HashMap<String, Float> myId2SplitProportion = new HashMap<>();
private Pair<ToolWindow, Integer> myMaximizedProportion;
/**
* This panel is the layered pane where all sliding tool windows are located. The DEFAULT
* layer contains splitters. The PALETTE layer contains all sliding tool windows.
@@ -84,29 +84,23 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
private final Stripe myBottomStripe;
private final Stripe myTopStripe;
private final ArrayList<Stripe> myStripes = new ArrayList<Stripe>();
private final List<Stripe> myStripes = new ArrayList<>();
private final ToolWindowManagerImpl myManager;
private boolean myStripesOverlayed;
private final Disposable myDisposable = Disposer.newDisposable();
private boolean myWidescreen = false;
private boolean myLeftHorizontalSplit = false;
private boolean myRightHorizontalSplit = false;
private boolean myWidescreen;
private boolean myLeftHorizontalSplit;
private boolean myRightHorizontalSplit;
ToolWindowsPane(final IdeFrameImpl frame, ToolWindowManagerImpl manager) {
ToolWindowsPane(@NotNull IdeFrameImpl frame, @NotNull ToolWindowManagerImpl manager) {
myManager = manager;
setOpaque(false);
myFrame = frame;
myId2Button = new HashMap<String, StripeButton>();
myId2Decorator = new HashMap<String, InternalDecorator>();
myButton2Info = new HashMap<StripeButton, WindowInfoImpl>();
myDecorator2Info = new HashMap<InternalDecorator, WindowInfoImpl>();
myId2SplitProportion = new HashMap<String, Float>();
// Splitters
myVerticalSplitter = new ThreeComponentsSplitter(true);
Disposer.register(this, myVerticalSplitter);
myVerticalSplitter.setDividerWidth(0);
@@ -193,6 +187,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
/**
* Invoked when enclosed frame is being shown.
*/
@Override
public final void addNotify() {
super.addNotify();
}
@@ -200,6 +195,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
/**
* Invoked when enclosed frame is being disposed.
*/
@Override
public final void removeNotify() {
if (ScreenUtil.isStandardAddRemoveNotify(this)) {
Disposer.dispose(myDisposable);
@@ -211,6 +207,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
return myFrame.getProject();
}
@Override
public final void uiSettingsChanged(final UISettings source) {
updateToolStripesVisibility();
updateLayout();
@@ -225,10 +222,11 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
* @param comparator which is used to sort buttons within the stripe.
* @param finishCallBack invoked when the command is completed.
*/
@NotNull
final FinalizableCommand createAddButtonCmd(final StripeButton button,
final WindowInfoImpl info,
final Comparator<StripeButton> comparator,
final Runnable finishCallBack) {
@NotNull WindowInfoImpl info,
@NotNull Comparator<StripeButton> comparator,
@NotNull Runnable finishCallBack) {
final WindowInfoImpl copiedInfo = info.copy();
myId2Button.put(copiedInfo.getId(), button);
myButton2Info.put(button, copiedInfo);
@@ -242,12 +240,11 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
* @param dirtyMode if <code>true</code> then JRootPane will not be validated and repainted after adding
* the decorator. Moreover in this (dirty) mode animation doesn't work.
*/
final FinalizableCommand createAddDecoratorCmd(
final InternalDecorator decorator,
final WindowInfoImpl info,
final boolean dirtyMode,
final Runnable finishCallBack
) {
@NotNull
final FinalizableCommand createAddDecoratorCmd(@NotNull InternalDecorator decorator,
@NotNull WindowInfoImpl info,
final boolean dirtyMode,
@NotNull Runnable finishCallBack) {
final WindowInfoImpl copiedInfo = info.copy();
final String id = copiedInfo.getId();
@@ -276,10 +273,11 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
*
* @param id <code>ID</code> of the button to be removed.
*/
final FinalizableCommand createRemoveButtonCmd(final String id, final Runnable finishCallBack) {
@NotNull
final FinalizableCommand createRemoveButtonCmd(@NotNull String id, @NotNull Runnable finishCallBack) {
final StripeButton button = getButtonById(id);
final WindowInfoImpl info = getButtonInfoById(id);
//
myButton2Info.remove(button);
myId2Button.remove(id);
return new RemoveToolStripeButtonCmd(button, info, finishCallBack);
@@ -291,7 +289,8 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
* @param dirtyMode if <code>true</code> then JRootPane will not be validated and repainted after removing
* the decorator. Moreover in this (dirty) mode animation doesn't work.
*/
final FinalizableCommand createRemoveDecoratorCmd(final String id, final boolean dirtyMode, final Runnable finishCallBack) {
@NotNull
final FinalizableCommand createRemoveDecoratorCmd(@NotNull String id, final boolean dirtyMode, @NotNull Runnable finishCallBack) {
final Component decorator = getDecoratorById(id);
final WindowInfoImpl info = getDecoratorInfoById(id);
@@ -321,14 +320,17 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
*
* @param component component to be set.
*/
final FinalizableCommand createSetEditorComponentCmd(final JComponent component, final Runnable finishCallBack) {
@NotNull
final FinalizableCommand createSetEditorComponentCmd(final JComponent component, @NotNull Runnable finishCallBack) {
return new SetEditorComponentCmd(component, finishCallBack);
}
final FinalizableCommand createUpdateButtonPositionCmd(String id, final Runnable finishCallback) {
@NotNull
final FinalizableCommand createUpdateButtonPositionCmd(@NotNull String id, @NotNull Runnable finishCallback) {
return new UpdateButtonPositionCmd(id, finishCallback);
}
@NotNull
public final JComponent getMyLayeredPane() {
return myLayeredPane;
}
@@ -361,7 +363,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
/**
* Sets (docks) specified component to the specified anchor.
*/
private void setComponent(final JComponent component, final ToolWindowAnchor anchor, final float weight) {
private void setComponent(final JComponent component, @NotNull ToolWindowAnchor anchor, final float weight) {
if (ToolWindowAnchor.TOP == anchor) {
myVerticalSplitter.setFirstComponent(component);
myVerticalSplitter.setFirstSize((int)(myLayeredPane.getHeight() * weight));
@@ -383,7 +385,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
}
}
private JComponent getComponentAt(ToolWindowAnchor anchor) {
private JComponent getComponentAt(@NotNull ToolWindowAnchor anchor) {
if (ToolWindowAnchor.TOP == anchor) {
return myVerticalSplitter.getFirstComponent();
}
@@ -402,12 +404,12 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
}
}
private float getPreferredSplitProportion(String id, float defaultValue) {
private float getPreferredSplitProportion(@NotNull String id, float defaultValue) {
Float f = myId2SplitProportion.get(id);
return (f == null ? defaultValue : f);
return f == null ? defaultValue : f;
}
private WindowInfoImpl getDockedInfoAt(ToolWindowAnchor anchor, boolean side) {
private WindowInfoImpl getDockedInfoAt(@NotNull ToolWindowAnchor anchor, boolean side) {
for (WindowInfoImpl info : myDecorator2Info.values()) {
if (info.isVisible() && info.isDocked() && info.getAnchor() == anchor && side == info.isSplit()) {
return info;
@@ -417,7 +419,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
return null;
}
public void setDocumentComponent(final JComponent component) {
private void setDocumentComponent(final JComponent component) {
(myWidescreen ? myVerticalSplitter : myHorizontalSplitter).setInnerComponent(component);
}
@@ -464,13 +466,13 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
if (ToolWindowAnchor.TOP == anchor) {
return myTopStripe;
}
else if (ToolWindowAnchor.BOTTOM == anchor) {
if (ToolWindowAnchor.BOTTOM == anchor) {
return myBottomStripe;
}
else if (ToolWindowAnchor.LEFT == anchor) {
if (ToolWindowAnchor.LEFT == anchor) {
return myLeftStripe;
}
else if (ToolWindowAnchor.RIGHT == anchor) {
if (ToolWindowAnchor.RIGHT == anchor) {
return myRightStripe;
}
@@ -478,7 +480,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
}
@Nullable
Stripe getStripeFor(final Rectangle screenRec, Stripe preferred) {
Stripe getStripeFor(@NotNull Rectangle screenRec, @NotNull Stripe preferred) {
if (preferred.containsScreen(screenRec)) {
return myStripes.get(myStripes.indexOf(preferred));
}
@@ -504,15 +506,15 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
}
}
public void stretchWidth(ToolWindow wnd, int value) {
void stretchWidth(@NotNull ToolWindow wnd, int value) {
stretch(wnd, value);
}
public void stretchHeight(ToolWindow wnd, int value) {
void stretchHeight(@NotNull ToolWindow wnd, int value) {
stretch(wnd, value);
}
private void stretch(ToolWindow wnd, int value) {
private void stretch(@NotNull ToolWindow wnd, int value) {
Pair<Resizer, Component> pair = findResizerAndComponent(wnd);
if (pair == null) return;
@@ -520,13 +522,13 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
int actualSize = (vertical ? pair.second.getHeight() : pair.second.getWidth()) + value;
boolean first = wnd.getAnchor() == ToolWindowAnchor.LEFT || wnd.getAnchor() == ToolWindowAnchor.TOP;
int maxValue = vertical ? myVerticalSplitter.getMaxSize(first) : myHorizontalSplitter.getMaxSize(first);
int minValue = vertical ? myVerticalSplitter.getMinSize(first) : myHorizontalSplitter.getMinSize(first);;
int minValue = vertical ? myVerticalSplitter.getMinSize(first) : myHorizontalSplitter.getMinSize(first);
pair.first.setSize(Math.max(minValue, Math.min(maxValue, actualSize)));
}
@Nullable
private Pair<Resizer, Component> findResizerAndComponent(ToolWindow wnd) {
private Pair<Resizer, Component> findResizerAndComponent(@NotNull ToolWindow wnd) {
if (!wnd.isVisible()) return null;
Resizer resizer = null;
@@ -620,7 +622,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
return myMaximizedProportion != null && myMaximizedProportion.first == wnd;
}
public void setMaximized(@NotNull ToolWindow wnd, boolean maximized) {
void setMaximized(@NotNull ToolWindow wnd, boolean maximized) {
Pair<Resizer, Component> resizerAndComponent = findResizerAndComponent(wnd);
if (resizerAndComponent == null) return;
@@ -638,6 +640,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
}
@FunctionalInterface
interface Resizer {
void setSize(int size);
@@ -645,25 +648,27 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
abstract class Splitter implements Resizer {
ThreeComponentsSplitter mySplitter;
Splitter(ThreeComponentsSplitter splitter) {
Splitter(@NotNull ThreeComponentsSplitter splitter) {
mySplitter = splitter;
}
static class FirstComponent extends Splitter {
FirstComponent(ThreeComponentsSplitter splitter) {
FirstComponent(@NotNull ThreeComponentsSplitter splitter) {
super(splitter);
}
@Override
public void setSize(int size) {
mySplitter.setFirstSize(size);
}
}
static class LastComponent extends Splitter {
LastComponent(ThreeComponentsSplitter splitter) {
LastComponent(@NotNull ThreeComponentsSplitter splitter) {
super(splitter);
}
@Override
public void setSize(int size) {
mySplitter.setLastSize(size);
}
@@ -673,10 +678,11 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
abstract class LayeredPane implements Resizer {
Component myComponent;
protected LayeredPane(Component component) {
LayeredPane(@NotNull Component component) {
myComponent = component;
}
@Override
public final void setSize(int size) {
_setSize(size);
if (myComponent.getParent() instanceof JComponent) {
@@ -690,20 +696,22 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
static class Left extends LayeredPane {
Left(Component component) {
Left(@NotNull Component component) {
super(component);
}
@Override
public void _setSize(int size) {
myComponent.setSize(size, myComponent.getHeight());
}
}
static class Right extends LayeredPane {
Right(Component component) {
Right(@NotNull Component component) {
super(component);
}
@Override
public void _setSize(int size) {
Rectangle bounds = myComponent.getBounds();
int delta = size - bounds.width;
@@ -714,20 +722,22 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
}
static class Top extends LayeredPane {
Top(Component component) {
Top(@NotNull Component component) {
super(component);
}
@Override
public void _setSize(int size) {
myComponent.setSize(myComponent.getWidth(), size);
}
}
static class Bottom extends LayeredPane {
Bottom(Component component) {
Bottom(@NotNull Component component) {
super(component);
}
@Override
public void _setSize(int size) {
Rectangle bounds = myComponent.getBounds();
int delta = size - bounds.height;
@@ -744,16 +754,17 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
private final WindowInfoImpl myInfo;
private final boolean myDirtyMode;
public AddDockedComponentCmd(final JComponent component,
final WindowInfoImpl info,
public AddDockedComponentCmd(@NotNull JComponent component,
@NotNull WindowInfoImpl info,
final boolean dirtyMode,
final Runnable finishCallBack) {
@NotNull Runnable finishCallBack) {
super(finishCallBack);
myComponent = component;
myInfo = info;
myDirtyMode = dirtyMode;
}
@Override
public final void run() {
try {
final ToolWindowAnchor anchor = myInfo.getAnchor();
@@ -774,17 +785,19 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
private final WindowInfoImpl myInfo;
private final boolean myDirtyMode;
private AddAndSplitDockedComponentCmd(final JComponent newComponent,
final WindowInfoImpl info, final boolean dirtyMode, final Runnable finishCallBack) {
private AddAndSplitDockedComponentCmd(@NotNull JComponent newComponent,
@NotNull WindowInfoImpl info,
final boolean dirtyMode,
@NotNull Runnable finishCallBack) {
super(finishCallBack);
myNewComponent = newComponent;
myInfo = info;
myDirtyMode = dirtyMode;
}
@Override
public void run() {
try {
float newWeight;
final ToolWindowAnchor anchor = myInfo.getAnchor();
class MySplitter extends Splitter implements UISettingsListener {
@Override
@@ -801,28 +814,26 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
splitter.setOrientation(anchor.isSplitVertically());
if (!anchor.isHorizontal()) {
splitter.setAllowSwitchOrientationByMouseClick(true);
splitter.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (!Splitter.PROP_ORIENTATION.equals(evt.getPropertyName())) return;
boolean isSplitterHorizontalNow = !splitter.isVertical();
UISettings settings = UISettings.getInstance();
if (anchor == ToolWindowAnchor.LEFT) {
if (settings.LEFT_HORIZONTAL_SPLIT != isSplitterHorizontalNow) {
settings.LEFT_HORIZONTAL_SPLIT = isSplitterHorizontalNow;
settings.fireUISettingsChanged();
}
splitter.addPropertyChangeListener(evt -> {
if (!Splitter.PROP_ORIENTATION.equals(evt.getPropertyName())) return;
boolean isSplitterHorizontalNow = !splitter.isVertical();
UISettings settings = UISettings.getInstance();
if (anchor == ToolWindowAnchor.LEFT) {
if (settings.LEFT_HORIZONTAL_SPLIT != isSplitterHorizontalNow) {
settings.LEFT_HORIZONTAL_SPLIT = isSplitterHorizontalNow;
settings.fireUISettingsChanged();
}
if (anchor == ToolWindowAnchor.RIGHT) {
if (settings.RIGHT_HORIZONTAL_SPLIT != isSplitterHorizontalNow) {
settings.RIGHT_HORIZONTAL_SPLIT = isSplitterHorizontalNow;
settings.fireUISettingsChanged();
}
}
if (anchor == ToolWindowAnchor.RIGHT) {
if (settings.RIGHT_HORIZONTAL_SPLIT != isSplitterHorizontalNow) {
settings.RIGHT_HORIZONTAL_SPLIT = isSplitterHorizontalNow;
settings.fireUISettingsChanged();
}
}
});
}
JComponent c = getComponentAt(anchor);
float newWeight;
if (c instanceof InternalDecorator) {
InternalDecorator oldComponent = (InternalDecorator)c;
if (myInfo.isSplit()) {
@@ -872,15 +883,16 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
private final WindowInfoImpl myInfo;
private final boolean myDirtyMode;
public AddSlidingComponentCmd(final Component component,
final WindowInfoImpl info,
public AddSlidingComponentCmd(@NotNull Component component,
@NotNull WindowInfoImpl info,
final boolean dirtyMode,
final Runnable finishCallBack) {
@NotNull Runnable finishCallBack) {
super(finishCallBack);
myComponent = component;
myInfo = info;
myDirtyMode = dirtyMode;
}
@Override
public final void run() {
try {
// Show component.
@@ -946,15 +958,16 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
private final Comparator<StripeButton> myComparator;
public AddToolStripeButtonCmd(final StripeButton button,
final WindowInfoImpl info,
final Comparator<StripeButton> comparator,
final Runnable finishCallBack) {
@NotNull WindowInfoImpl info,
@NotNull Comparator<StripeButton> comparator,
@NotNull Runnable finishCallBack) {
super(finishCallBack);
myButton = button;
myInfo = info;
myComparator = comparator;
}
@Override
public final void run() {
try {
final ToolWindowAnchor anchor = myInfo.getAnchor();
@@ -986,12 +999,13 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
private final StripeButton myButton;
private final WindowInfoImpl myInfo;
public RemoveToolStripeButtonCmd(final StripeButton button, final WindowInfoImpl info, final Runnable finishCallBack) {
public RemoveToolStripeButtonCmd(@NotNull StripeButton button, @NotNull WindowInfoImpl info, @NotNull Runnable finishCallBack) {
super(finishCallBack);
myButton = button;
myInfo = info;
}
@Override
public final void run() {
try {
final ToolWindowAnchor anchor = myInfo.getAnchor();
@@ -1023,12 +1037,13 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
private final WindowInfoImpl myInfo;
private final boolean myDirtyMode;
public RemoveDockedComponentCmd(final WindowInfoImpl info, final boolean dirtyMode, final Runnable finishCallBack) {
public RemoveDockedComponentCmd(@NotNull WindowInfoImpl info, final boolean dirtyMode, @NotNull Runnable finishCallBack) {
super(finishCallBack);
myInfo = info;
myDirtyMode = dirtyMode;
}
@Override
public final void run() {
try {
setComponent(null, myInfo.getAnchor(), 0);
@@ -1047,14 +1062,15 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
private final WindowInfoImpl myInfo;
private final boolean myDirtyMode;
private RemoveSplitAndDockedComponentCmd(final WindowInfoImpl info,
private RemoveSplitAndDockedComponentCmd(@NotNull WindowInfoImpl info,
boolean dirtyMode,
final Runnable finishCallBack) {
@NotNull Runnable finishCallBack) {
super(finishCallBack);
myInfo = info;
myDirtyMode = dirtyMode;
}
@Override
public void run() {
try {
ToolWindowAnchor anchor = myInfo.getAnchor();
@@ -1086,12 +1102,13 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
private final WindowInfoImpl myInfo;
private final boolean myDirtyMode;
public RemoveSlidingComponentCmd(Component component, WindowInfoImpl info, boolean dirtyMode, Runnable finishCallBack) {
public RemoveSlidingComponentCmd(Component component, @NotNull WindowInfoImpl info, boolean dirtyMode, @NotNull Runnable finishCallBack) {
super(finishCallBack);
myComponent = component;
myInfo = info;
myDirtyMode = dirtyMode;
}
@Override
public final void run() {
try {
final UISettings uiSettings = UISettings.getInstance();
@@ -1147,11 +1164,12 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
private final class SetEditorComponentCmd extends FinalizableCommand {
private final JComponent myComponent;
public SetEditorComponentCmd(final JComponent component, final Runnable finishCallBack) {
public SetEditorComponentCmd(final JComponent component, @NotNull Runnable finishCallBack) {
super(finishCallBack);
myComponent = component;
}
@Override
public void run() {
try {
setDocumentComponent(myComponent);
@@ -1167,11 +1185,12 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
private final class UpdateButtonPositionCmd extends FinalizableCommand {
private final String myId;
private UpdateButtonPositionCmd(String id, final Runnable finishCallBack) {
private UpdateButtonPositionCmd(@NotNull String id, @NotNull Runnable finishCallBack) {
super(finishCallBack);
myId = id;
}
@Override
public void run() {
try {
StripeButton stripeButton = getButtonById(myId);
@@ -1209,35 +1228,31 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
* These images are used to perform animated showing and hiding of components.
* They are the member for performance reason.
*/
private SoftReference<BufferedImage> myBottomImageRef;
private SoftReference<BufferedImage> myTopImageRef;
private Reference<BufferedImage> myBottomImageRef;
private Reference<BufferedImage> myTopImageRef;
public MyLayeredPane(final JComponent splitter) {
myBottomImageRef = new SoftReference<BufferedImage>(null);
myTopImageRef = new SoftReference<BufferedImage>(null);
public MyLayeredPane(@NotNull JComponent splitter) {
setOpaque(false);
add(splitter, JLayeredPane.DEFAULT_LAYER);
}
public final Image getBottomImage() {
Pair<BufferedImage, SoftReference<BufferedImage>> result = getImage(myBottomImageRef);
final Image getBottomImage() {
Pair<BufferedImage, Reference<BufferedImage>> result = getImage(myBottomImageRef);
myBottomImageRef = result.second;
return result.first;
}
public final Image getTopImage() {
Pair<BufferedImage, SoftReference<BufferedImage>> result = getImage(myTopImageRef);
final Image getTopImage() {
Pair<BufferedImage, Reference<BufferedImage>> result = getImage(myTopImageRef);
myTopImageRef = result.second;
return result.first;
}
private Pair<BufferedImage, SoftReference<BufferedImage>> getImage(SoftReference<BufferedImage> imageRef) {
@NotNull
private Pair<BufferedImage, Reference<BufferedImage>> getImage(@Nullable Reference<BufferedImage> imageRef) {
LOG.assertTrue(UISettings.getInstance().ANIMATE_WINDOWS);
BufferedImage image = imageRef.get();
if (
image == null ||
image.getWidth(null) < getWidth() || image.getHeight(null) < getHeight()
) {
BufferedImage image = SoftReference.dereference(imageRef);
if (image == null || image.getWidth(null) < getWidth() || image.getHeight(null) < getHeight()) {
final int width = Math.max(Math.max(1, getWidth()), myFrame.getWidth());
final int height = Math.max(Math.max(1, getHeight()), myFrame.getHeight());
if (SystemInfo.isWindows) {
@@ -1251,7 +1266,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
image = UIUtil.createImage(width, height, BufferedImage.TYPE_INT_RGB);
}
imageRef = new SoftReference<BufferedImage>(image);
imageRef = new SoftReference<>(image);
}
return Pair.create(image, imageRef);
}
@@ -1259,6 +1274,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
/**
* When component size becomes larger then bottom and top images should be enlarged.
*/
@Override
public void doLayout() {
final int width = getWidth();
final int height = getHeight();
@@ -1295,7 +1311,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
}
}
public final void setBoundsInPaletteLayer(final Component component, final ToolWindowAnchor anchor, float weight) {
final void setBoundsInPaletteLayer(@NotNull Component component, @NotNull ToolWindowAnchor anchor, float weight) {
if (weight < .0f) {
weight = WindowInfoImpl.DEFAULT_WEIGHT;
}
@@ -1322,7 +1338,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
}
}
public void setStripesOverlayed(boolean stripesOverlayed) {
void setStripesOverlayed(boolean stripesOverlayed) {
myStripesOverlayed = stripesOverlayed;
updateToolStripesVisibility();
}
@@ -32,16 +32,16 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo
/**
* XML tag.
*/
@NonNls static final String TAG="window_info";
@NonNls static final String TAG = "window_info";
/**
* Default window weight.
*/
static final float DEFAULT_WEIGHT= 0.33f;
static final float DEFAULT_SIDE_WEIGHT = 0.5f;
static final float DEFAULT_WEIGHT = 0.33f;
private static final float DEFAULT_SIDE_WEIGHT = 0.5f;
private boolean myActive;
@NotNull
private ToolWindowAnchor myAnchor;
private ToolWindowAnchor myAnchor = ToolWindowAnchor.LEFT;
private boolean myAutoHide;
/**
* Bounds of window in "floating" mode. It equals to <code>null</code> if
@@ -52,9 +52,9 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo
private ToolWindowType myInternalType;
private ToolWindowType myType;
private boolean myVisible;
private boolean myShowStripeButton;
private float myWeight;
private float mySideWeight;
private boolean myShowStripeButton = true;
private float myWeight = DEFAULT_WEIGHT;
private float mySideWeight = DEFAULT_SIDE_WEIGHT;
private boolean mySplitMode;
@NotNull private ToolWindowContentUiType myContentUiType = ToolWindowContentUiType.TABBED;
@@ -62,24 +62,24 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo
* Defines order of tool window button inside the stripe.
* The default value is <code>-1</code>.
*/
private int myOrder;
@NonNls static final String ID_ATTR = "id";
@NonNls static final String ACTIVE_ATTR = "active";
@NonNls static final String ANCHOR_ATTR = "anchor";
@NonNls static final String AUTOHIDE_ATTR = "auto_hide";
@NonNls static final String INTERNAL_TYPE_ATTR = "internal_type";
@NonNls static final String TYPE_ATTR = "type";
@NonNls static final String VISIBLE_ATTR = "visible";
@NonNls static final String WEIGHT_ATTR = "weight";
@NonNls static final String SIDE_WEIGHT_ATTR = "sideWeight";
@NonNls static final String ORDER_ATTR = "order";
@NonNls static final String X_ATTR = "x";
@NonNls static final String Y_ATTR = "y";
@NonNls static final String WIDTH_ATTR = "width";
@NonNls static final String HEIGHT_ATTR = "height";
@NonNls static final String SIDE_TOOL_ATTR = "side_tool";
@NonNls static final String CONTENT_UI_ATTR = "content_ui";
@NonNls static final String SHOW_STRIPE_BUTTON = "show_stripe_button";
private int myOrder = -1;
@NonNls private static final String ID_ATTR = "id";
@NonNls private static final String ACTIVE_ATTR = "active";
@NonNls private static final String ANCHOR_ATTR = "anchor";
@NonNls private static final String AUTOHIDE_ATTR = "auto_hide";
@NonNls private static final String INTERNAL_TYPE_ATTR = "internal_type";
@NonNls private static final String TYPE_ATTR = "type";
@NonNls private static final String VISIBLE_ATTR = "visible";
@NonNls private static final String WEIGHT_ATTR = "weight";
@NonNls private static final String SIDE_WEIGHT_ATTR = "sideWeight";
@NonNls private static final String ORDER_ATTR = "order";
@NonNls private static final String X_ATTR = "x";
@NonNls private static final String Y_ATTR = "y";
@NonNls private static final String WIDTH_ATTR = "width";
@NonNls private static final String HEIGHT_ATTR = "height";
@NonNls private static final String SIDE_TOOL_ATTR = "side_tool";
@NonNls private static final String CONTENT_UI_ATTR = "content_ui";
@NonNls private static final String SHOW_STRIPE_BUTTON = "show_stripe_button";
private boolean myWasRead;
@@ -88,18 +88,8 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo
* Creates <code>WindowInfo</code> for tool window with specified <code>ID</code>.
*/
WindowInfoImpl(@NotNull String id) {
myActive = false;
myAnchor = ToolWindowAnchor.LEFT;
myAutoHide = false;
myFloatingBounds = null;
myId = id;
setType(ToolWindowType.DOCKED);
myVisible = false;
myShowStripeButton = true;
myWeight = DEFAULT_WEIGHT;
mySideWeight = DEFAULT_SIDE_WEIGHT;
myOrder = -1;
mySplitMode = false;
}
/**
@@ -122,7 +112,7 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo
/**
* Copies all data from the passed <code>WindowInfo</code> into itself.
*/
void copyFrom(final WindowInfoImpl info){
void copyFrom(@NotNull WindowInfoImpl info){
myActive = info.myActive;
myAnchor = info.myAnchor;
myAutoHide = info.myAutoHide;
@@ -178,15 +168,16 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo
* window can be in floating mode, but this method has sense if you want to know what type
* tool window had when it was internal one. The method never returns <code>null</code>.
*/
@NotNull
ToolWindowType getInternalType(){
return myInternalType;
}
/**
* @return current type of tool window.
* @see com.intellij.openapi.wm.ToolWindowType#DOCKED
* @see com.intellij.openapi.wm.ToolWindowType#FLOATING
* @see com.intellij.openapi.wm.ToolWindowType#SLIDING
* @see ToolWindowType#DOCKED
* @see ToolWindowType#FLOATING
* @see ToolWindowType#SLIDING
*/
@Override
public ToolWindowType getType(){
@@ -248,11 +239,12 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo
return myVisible;
}
@Override
public boolean isShowStripeButton() {
return myShowStripeButton;
}
public void setShowStripeButton(boolean showStripeButton) {
void setShowStripeButton(boolean showStripeButton) {
myShowStripeButton = showStripeButton;
}
@@ -266,7 +258,7 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo
}
@Override
@SuppressWarnings({"EmptyCatchBlock"})
@SuppressWarnings("EmptyCatchBlock")
public void readExternal(final Element element) {
myId = element.getAttributeValue(ID_ATTR);
myWasRead = true;
@@ -353,7 +345,7 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo
setTypeAndCheck(type);
}
//Hardcoded to avoid single-usage-API
private void setTypeAndCheck(ToolWindowType type) {
private void setTypeAndCheck(@NotNull ToolWindowType type) {
myType = ToolWindowId.PREVIEW == myId && type == ToolWindowType.DOCKED ? ToolWindowType.SLIDING : type;
}
@@ -420,7 +412,7 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo
return myAnchor.hashCode()+myId.hashCode()+myType.hashCode()+myOrder;
}
@SuppressWarnings({"HardCodedStringLiteral"})
@SuppressWarnings("HardCodedStringLiteral")
public String toString(){
return getClass().getName() + "[myId=" + myId
+ "; myVisible=" + myVisible
@@ -439,7 +431,7 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo
']';
}
public boolean wasRead() {
boolean wasRead() {
return myWasRead;
}
}
@@ -15,14 +15,11 @@
*/
package com.intellij.openapi.wm.impl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.FrameWrapper;
import org.jetbrains.annotations.NotNull;
public final class WindowedDecorator extends FrameWrapper {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.WindowedDecorator");
final class WindowedDecorator extends FrameWrapper {
private final Project myProject;
WindowedDecorator(@NotNull Project project, @NotNull WindowInfoImpl info, @NotNull InternalDecorator internalDecorator) {
@@ -17,6 +17,7 @@ package com.intellij.openapi.wm.impl.commands;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.wm.ToolWindowManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -27,15 +28,15 @@ public abstract class FinalizableCommand implements Runnable{
protected ToolWindowManager myManager;
public FinalizableCommand(final Runnable finishCallBack){
myFinishCallBack=finishCallBack;
public FinalizableCommand(Runnable finishCallBack){
myFinishCallBack = finishCallBack;
}
public final void finish(){
myFinishCallBack.run();
}
public void beforeExecute(final ToolWindowManager toolWindowManager) {
public void beforeExecute(@NotNull ToolWindowManager toolWindowManager) {
myManager = toolWindowManager;
}
@@ -562,7 +562,7 @@ public class Mock {
public ToolWindow registerToolWindow(@NotNull String id,
@NotNull JComponent component,
@NotNull ToolWindowAnchor anchor,
Disposable parentDisposable,
@NotNull Disposable parentDisposable,
boolean canWorkInDumbMode, boolean canCloseContents) {
throw new RuntimeException();
}
@@ -572,7 +572,7 @@ public class Mock {
public ToolWindow registerToolWindow(@NotNull String id,
@NotNull JComponent component,
@NotNull ToolWindowAnchor anchor,
Disposable parentDisposable,
@NotNull Disposable parentDisposable,
boolean canWorkInDumbMode) {
throw new RuntimeException();
}
@@ -592,7 +592,7 @@ public class Mock {
@NotNull
@Override
public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor,
final Disposable parentDisposable, final boolean dumbAware) {
@NotNull final Disposable parentDisposable, final boolean dumbAware) {
throw new RuntimeException();
}
@@ -601,7 +601,7 @@ public class Mock {
public ToolWindow registerToolWindow(@NotNull String id,
boolean canCloseContent,
@NotNull ToolWindowAnchor anchor,
Disposable parentDisposable,
@NotNull Disposable parentDisposable,
boolean canWorkInDumbMode,
boolean secondary) {
throw new RuntimeException();
@@ -17,6 +17,7 @@ package com.intellij.util;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.awt.image.BufferedImage;
@@ -50,6 +51,7 @@ public class RetinaImage {
* @param observer the raw image observer
* @return the Retina-aware wrapper
*/
@NotNull
public static Image createFrom(Image image, final int scale, ImageObserver observer) {
int w = image.getWidth(observer);
int h = image.getHeight(observer);
@@ -65,11 +67,13 @@ public class RetinaImage {
return hidpi;
}
@NotNull
public static BufferedImage create(final int width, int height, int type) {
return create(null, width, height, type);
}
@NotNull
private static BufferedImage create(Image image, final int width, int height, int type) {
if (SystemInfo.isAppleJvm) {
return AppleHiDPIScaledImage.create(width, height, type);
@@ -183,8 +183,7 @@ class SchedulingWrapper implements ScheduledExecutorService {
@Override
public int compareTo(@NotNull Delayed other) {
if (other == this) // compare zero if same object
{
if (other == this) {
return 0;
}
if (other instanceof MyScheduledFutureTask) {
@@ -1779,6 +1779,7 @@ public class UIUtil {
}
}
@NotNull
public static BufferedImage createImage(int width, int height, int type) {
if (isRetina()) {
return RetinaImage.create(width, height, type);
@@ -1787,6 +1788,7 @@ public class UIUtil {
return new BufferedImage(width, height, type);
}
@NotNull
public static BufferedImage createImageForGraphics(Graphics2D g, int width, int height, int type) {
if (isRetina(g)) {
return RetinaImage.create(width, height, type);
@@ -60,7 +60,6 @@ import com.intellij.ui.*;
import com.intellij.util.Alarm;
import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
@@ -196,7 +195,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper {
myReset = myCanChangePatchFile ? this::reset : EmptyRunnable.getInstance();
myChangeListChooser = new ChangeListChooserPanel(project, errorMessage -> {
setOKActionEnabled(errorMessage == null);
setOKActionEnabled(errorMessage == null && isChangeTreeEnabled());
setErrorText(errorMessage);
});
ChangeListManager changeListManager = ChangeListManager.getInstance(project);
@@ -244,7 +243,15 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper {
}
private void updateOkActions() {
setOKActionEnabled(!myChangesTreeList.getIncludedChanges().isEmpty());
boolean changeTreeEnabled = isChangeTreeEnabled();
setOKActionEnabled(changeTreeEnabled);
if (changeTreeEnabled) {
myChangeListChooser.updateEnabled();
}
}
private boolean isChangeTreeEnabled() {
return !myChangesTreeList.getIncludedChanges().isEmpty();
}
private void queueRequest() {
@@ -371,6 +378,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper {
myReader = patchReader;
updateTree(true);
paintBusy(false);
updateOkActions();
}, ModalityState.stateForComponent(myCenterPanel));
}
}
@@ -519,8 +527,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper {
protected DefaultTreeModel buildTreeModel(List<AbstractFilePatchInProgress.PatchChange> changes,
ChangeNodeDecorator changeNodeDecorator) {
TreeModelBuilder builder = new TreeModelBuilder(myProject, isShowFlatten());
return builder.buildModel(ObjectsConvertor.convert(changes,
(Convertor<AbstractFilePatchInProgress.PatchChange, Change>)o -> o), changeNodeDecorator);
return builder.buildModel(ObjectsConvertor.convert(changes, o -> o), changeNodeDecorator);
}
@Override
@@ -1,50 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.openapi.vcs.changes.ui.ChangeListChooserPanel">
<grid id="84622" binding="myPanel" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="214" y="106" width="285" height="171"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="cde9d" class="javax.swing.JRadioButton" binding="myRbExisting">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/VcsBundle" key="changes.changelist.chooser.existing.changelist"/>
</properties>
</component>
<component id="e9094" class="javax.swing.JRadioButton" binding="myRbNew">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/VcsBundle" key="changes.changelist.chooser.new.changelist"/>
</properties>
</component>
<component id="6e64e" class="javax.swing.JComboBox" binding="myExistingListsCombo">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="3" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="54fed" class="com.intellij.openapi.vcs.changes.ui.NewEditChangelistPanel" binding="myNewListPanel" custom-create="true">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="3" use-parent-layout="false">
<minimum-size width="300" height="150"/>
<preferred-size width="300" height="150"/>
</grid>
</constraints>
<properties/>
</component>
</children>
</grid>
<buttonGroups>
<group name="buttonGroup1">
<member id="cde9d"/>
<member id="e9094"/>
</group>
</buttonGroups>
</form>
@@ -15,20 +15,23 @@
*/
package com.intellij.openapi.vcs.changes.ui;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.VcsBundle;
import com.intellij.openapi.vcs.VcsConfiguration;
import com.intellij.openapi.vcs.changes.ChangeList;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.LocalChangeList;
import com.intellij.openapi.vcs.changes.committed.CommittedChangeListRenderer;
import com.intellij.openapi.vcs.changes.issueLinks.IssueLinkRenderer;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.*;
import com.intellij.util.NullableConsumer;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.CalledInAwt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -36,140 +39,144 @@ import javax.swing.*;
import java.awt.*;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* @author yole
*/
public class ChangeListChooserPanel extends JPanel {
private static final Comparator<ChangeList> CHANGE_LIST_COMPARATOR = new Comparator<ChangeList>() {
@Override
public int compare(ChangeList o1, ChangeList o2) {
return o1.getName().compareToIgnoreCase(o2.getName());
}
};
import static com.intellij.codeInsight.completion.ComboEditorCompletionContributor.CONTINUE_RUN_COMPLETION;
private JPanel myPanel;
private JRadioButton myRbExisting;
private JRadioButton myRbNew;
private JComboBox myExistingListsCombo;
private NewEditChangelistPanel myNewListPanel;
public class ChangeListChooserPanel extends JPanel {
private final MyEditorComboBox myExistingListsCombo;
private final NewEditChangelistPanel myListPanel;
private final NullableConsumer<String> myOkEnabledListener;
private Project myProject;
private final Project myProject;
private String myLastTypedDescription;
public ChangeListChooserPanel(final Project project, @NotNull final NullableConsumer<String> okEnabledListener) {
super(new BorderLayout());
myProject = project;
myOkEnabledListener = okEnabledListener;
add(myPanel, BorderLayout.CENTER);
myRbExisting.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
updateEnabledItems();
}
});
}
public void init() {
myExistingListsCombo.setRenderer(new ColoredListCellRendererWrapper() {
private final IssueLinkRenderer myLinkRenderer = new IssueLinkRenderer(myProject, this);
myExistingListsCombo = new MyEditorComboBox(project);
myExistingListsCombo.setEditable(true);
myExistingListsCombo.setRenderer(new ColoredListCellRenderer<String>() {
@Override
protected void doCustomize(JList list, Object value, int index, boolean selected, boolean hasFocus) {
if (value instanceof LocalChangeList) {
String name = ((LocalChangeList) value).getName();
if (myExistingListsCombo.getWidth() == 0) {
protected void customizeCellRenderer(@NotNull JList<? extends String> list,
String value,
int index,
boolean selected,
boolean hasFocus) {
if (value != null) {
String name = value;
LocalChangeList changeList = ChangeListManager.getInstance(myProject).findChangeList(name);
int visibleWidth = myExistingListsCombo.getEditorTextField().getVisibleRect().width;
if (visibleWidth == 0) {
name = name.length() > 10 ? name.substring(0, 7) + " .." : name;
}
else {
final FontMetrics fm = list.getFontMetrics(list.getFont());
final int width = fm.stringWidth(name);
final int listWidth = myExistingListsCombo.getWidth();
if ((listWidth > 0) && (width > listWidth)) {
final String truncated = CommittedChangeListRenderer.truncateDescription(name, fm, listWidth - fm.stringWidth(" ..") - 7);
if ((visibleWidth > 0) && (width > visibleWidth)) {
final String truncated = CommittedChangeListRenderer
.truncateDescription(name, fm, visibleWidth - fm.stringWidth(" ..") - 7);
if (truncated.length() > 5) {
name = truncated + " ..";
}
}
}
myLinkRenderer.appendTextWithLinks(name, ((LocalChangeList)value).isDefault()
? SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES);
append(name, changeList != null && changeList.isDefault()
? SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES
: SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
}
});
myNewListPanel.init(null);
myRbNew.addFocusListener(new FocusAdapter() {
myListPanel = new NewEditChangelistPanel(myProject) {
@Override
public void focusGained(FocusEvent e) {
if (myRbNew.isSelected()) {
IdeFocusManager.getInstance(myProject).requestFocus(myNewListPanel.getPreferredFocusedComponent(), true);
}
protected NewEditChangelistPanel.ComponentWithTextFieldWrapper createComponentWithTextField(Project project) {
return new ComponentWithTextFieldWrapper(myExistingListsCombo) {
@NotNull
@Override
public EditorTextField getEditorTextField() {
return myExistingListsCombo.getEditorTextField();
}
};
}
});
final ComboboxSpeedSearch search = new ComboboxSpeedSearch(myExistingListsCombo);
search.setComparator(new SpeedSearchComparator(true, false));
@Override
@CalledInAwt
protected void nameChanged(String errorMessage) {
//invoke later because of undo manager problem: when you try to undo changelist after description was already changed manually
ApplicationManager.getApplication().invokeLater(() -> updateDescription(), ModalityState.current());
myOkEnabledListener.consume(errorMessage);
}
@Override
public void init(LocalChangeList initial) {
super.init(initial);
myDescriptionTextArea.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
super.focusLost(e);
if (getExistingChangelist() == null) {
myLastTypedDescription = myListPanel.getDescription();
}
}
});
}
@Override
protected void nameChangedImpl(Project project, LocalChangeList initial) {
nameChanged(StringUtil.isEmptyOrSpaces(getChangeListName()) ? "Cannot create new changelist with empty name." : null);
}
};
myOkEnabledListener = okEnabledListener;
add(myListPanel, BorderLayout.CENTER);
}
public void init() {
myListPanel.init(null);
}
public void setChangeLists(Collection<? extends ChangeList> changeLists) {
List<ChangeList> list = new ArrayList<ChangeList>(changeLists);
Collections.sort(list, CHANGE_LIST_COMPARATOR);
myExistingListsCombo.setModel(new CollectionComboBoxModel(list, null));
List<String> changelistNames = ContainerUtil.map(changeLists, ChangeList::getName);
Collections.sort(changelistNames);
myExistingListsCombo.setModel(new CollectionComboBoxModel<String>(changelistNames));
}
public void setDefaultName(String name) {
if (! StringUtil.isEmptyOrSpaces(name)) {
myNewListPanel.setChangeListName(name);
if (!StringUtil.isEmptyOrSpaces(name)) {
myListPanel.setChangeListName(name);
}
}
private void updateEnabledItems() {
if (myRbExisting.isSelected()) {
myExistingListsCombo.setEnabled(true);
UIUtil.setEnabled(myNewListPanel, false, true);
myExistingListsCombo.requestFocus();
}
else {
myExistingListsCombo.setEnabled(false);
UIUtil.setEnabled(myNewListPanel, true, true);
myNewListPanel.requestFocus();
}
public void updateEnabled() {
if (myProject != null) {
myNewListPanel.nameChangedImpl(myProject, null);
myListPanel.nameChangedImpl(myProject, null);
}
}
/**
* Method used as getResult, usually invoked inside doOkAction
*/
@Nullable
public LocalChangeList getSelectedList(Project project) {
ChangeListManager manager = ChangeListManager.getInstance(project);
if (myRbNew.isSelected()) {
String newText = myNewListPanel.getChangeListName();
if (manager.findChangeList(newText) != null) {
Messages.showErrorDialog(project,
VcsBundle.message("changes.newchangelist.warning.already.exists.text", newText),
VcsBundle.message("changes.newchangelist.warning.already.exists.title"));
return null;
}
}
final boolean existingSelected = myRbExisting.isSelected();
VcsConfiguration.getInstance(myProject).PRESELECT_EXISTING_CHANGELIST = existingSelected;
String changeListName = myListPanel.getChangeListName();
LocalChangeList localChangeList = manager.findChangeList(changeListName);
if (existingSelected) {
return (LocalChangeList)myExistingListsCombo.getSelectedItem();
if (localChangeList == null) {
localChangeList = manager.addChangeList(changeListName, myListPanel.getDescription());
myListPanel.changelistCreatedOrChanged(localChangeList);
}
else {
LocalChangeList changeList = manager.addChangeList(myNewListPanel.getChangeListName(), myNewListPanel.getDescription());
myNewListPanel.changelistCreatedOrChanged(changeList);
if (myNewListPanel.getMakeActiveCheckBox().isSelected()) {
manager.setDefaultChangeList(changeList);
}
VcsConfiguration.getInstance(project).MAKE_NEW_CHANGELIST_ACTIVE = myNewListPanel.getMakeActiveCheckBox().isSelected();
return changeList;
//update description if changed
localChangeList.setComment(myListPanel.getDescription());
}
if (myListPanel.getMakeActiveCheckBox().isSelected()) {
manager.setDefaultChangeList(localChangeList);
}
VcsConfiguration.getInstance(project).MAKE_NEW_CHANGELIST_ACTIVE = myListPanel.getMakeActiveCheckBox().isSelected();
return localChangeList;
}
public void setDefaultSelection(final ChangeList defaultSelection) {
@@ -177,34 +184,46 @@ public class ChangeListChooserPanel extends JPanel {
myExistingListsCombo.setSelectedIndex(0);
}
else {
myExistingListsCombo.setSelectedItem(defaultSelection);
}
//if defaultSelection was predefined as null then it means we could not use existing is this context
if (defaultSelection != null && VcsConfiguration.getInstance(myProject).PRESELECT_EXISTING_CHANGELIST) {
myRbExisting.setSelected(true);
}
else {
myRbNew.setSelected(true);
myExistingListsCombo.setSelectedItem(defaultSelection.getName());
}
updateDescription();
updateEnabled();
}
updateEnabledItems();
private void updateDescription() {
LocalChangeList list = getExistingChangelist();
String newText = list != null ? list.getComment() : myLastTypedDescription;
if (!StringUtil.equals(myListPanel.getDescription(), newText)) {
myListPanel.setDescription(newText);
}
}
private LocalChangeList getExistingChangelist() {
ChangeListManager manager = ChangeListManager.getInstance(myProject);
String changeListName = myListPanel.getChangeListName();
return manager.findChangeList(changeListName);
}
public JComponent getPreferredFocusedComponent() {
return myRbExisting.isSelected() ? myExistingListsCombo : myNewListPanel.getPreferredFocusedComponent();
return myExistingListsCombo;
}
private void createUIComponents() {
myNewListPanel = new NewEditChangelistPanel(myProject) {
private static class MyEditorComboBox extends ComboBox<String> {
@Override
protected void nameChanged(String errorMessage) {
if (myRbExisting.isSelected()) {
myOkEnabledListener.consume(null);
} else {
myOkEnabledListener.consume(errorMessage);
public MyEditorComboBox(Project project) {
super();
setEditor(new StringComboboxEditor(project, FileTypes.PLAIN_TEXT, this) {
@Override
protected void onEditorCreate(EditorEx editor) {
super.onEditorCreate(editor);
getDocument().putUserData(CONTINUE_RUN_COMPLETION, true);
}
}
};
});
}
@NotNull
private EditorTextField getEditorTextField() {
return ObjectUtils.assertNotNull((EditorTextField)getEditor().getEditorComponent());
}
}
}
@@ -17,8 +17,8 @@ package com.intellij.openapi.vcs.changes.ui;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.editor.SpellCheckingEditorCustomizationProvider;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.event.DocumentListener;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.project.Project;
@@ -30,19 +30,20 @@ import com.intellij.ui.*;
import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.JBUI;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.util.Set;
public abstract class NewEditChangelistPanel extends JPanel {
private EditorTextField myNameTextField;
private EditorTextField myDescriptionTextArea;
private JPanel myAdditionalControlsPanel;
private JCheckBox myMakeActiveCheckBox;
protected final EditorTextField myNameTextField;
protected final EditorTextField myDescriptionTextArea;
private final JPanel myAdditionalControlsPanel;
private final JCheckBox myMakeActiveCheckBox;
private Consumer<LocalChangeList> myConsumer;
private final Project myProject;
protected final Project myProject;
public NewEditChangelistPanel(final Project project) {
super(new GridBagLayout());
@@ -52,14 +53,15 @@ public abstract class NewEditChangelistPanel extends JPanel {
final JLabel nameLabel = new JLabel(VcsBundle.message("edit.changelist.name"));
add(nameLabel, gb);
++ gb.gridx;
++gb.gridx;
gb.fill = GridBagConstraints.HORIZONTAL;
gb.weightx = 1;
myNameTextField = createEditorField(project, 1);
ComponentWithTextFieldWrapper componentWithTextField = createComponentWithTextField(project);
myNameTextField = componentWithTextField.getEditorTextField();
myNameTextField.setOneLineMode(true);
myNameTextField.setText("New changelist");
myNameTextField.selectAll();
add(myNameTextField, gb);
add(componentWithTextField.myComponent, gb);
nameLabel.setLabelFor(myNameTextField);
++ gb.gridy;
@@ -100,11 +102,7 @@ public abstract class NewEditChangelistPanel extends JPanel {
support.installSearch(myNameTextField, myDescriptionTextArea);
myConsumer = support.addControls(myAdditionalControlsPanel, initial);
}
myNameTextField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void beforeDocumentChange(DocumentEvent event) {
}
myNameTextField.getDocument().addDocumentListener(new DocumentAdapter() {
@Override
public void documentChanged(DocumentEvent event) {
nameChangedImpl(myProject, initial);
@@ -160,6 +158,17 @@ public abstract class NewEditChangelistPanel extends JPanel {
protected abstract void nameChanged(String errorMessage);
protected ComponentWithTextFieldWrapper createComponentWithTextField(Project project) {
final EditorTextField editorTextField = createEditorField(project, 1);
return new ComponentWithTextFieldWrapper(editorTextField) {
@NotNull
@Override
public EditorTextField getEditorTextField() {
return editorTextField;
}
};
}
private static EditorTextField createEditorField(final Project project, final int defaultLines) {
final EditorTextFieldProvider service = ServiceManager.getService(project, EditorTextFieldProvider.class);
final EditorTextField editorField;
@@ -178,4 +187,15 @@ public abstract class NewEditChangelistPanel extends JPanel {
editorField.getComponent().setMinimumSize(new Dimension(100, (int)(height * 1.3)));
return editorField;
}
protected abstract static class ComponentWithTextFieldWrapper {
@NotNull private final Component myComponent;
public ComponentWithTextFieldWrapper(@NotNull Component component) {
myComponent = component;
}
@NotNull
abstract EditorTextField getEditorTextField();
}
}
@@ -33,6 +33,8 @@ import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerAdapter;
import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
@@ -128,24 +130,35 @@ public class ProjectLevelVcsManagerImpl extends ProjectLevelVcsManagerEx impleme
private final VcsFileListenerContextHelper myVcsFileListenerContextHelper;
private final VcsAnnotationLocalChangesListenerImpl myAnnotationLocalChangesListener;
public ProjectLevelVcsManagerImpl(Project project, final FileStatusManager manager, MessageBus messageBus,
final FileIndexFacade excludedFileIndex) {
public ProjectLevelVcsManagerImpl(Project project,
final FileStatusManager manager,
MessageBus messageBus,
final FileIndexFacade excludedFileIndex,
ProjectManager projectManager,
DefaultVcsRootPolicy defaultVcsRootPolicy,
VcsFileListenerContextHelper vcsFileListenerContextHelper) {
myProject = project;
myMessageBus = messageBus;
mySerialization = new ProjectLevelVcsManagerSerialization();
myOptionsAndConfirmations = new OptionsAndConfirmations();
myDefaultVcsRootPolicy = DefaultVcsRootPolicy.getInstance(project);
myDefaultVcsRootPolicy = defaultVcsRootPolicy;
myInitialization = new VcsInitialization(myProject);
Disposer.register(project, myInitialization); // wait for the thread spawned in VcsInitialization to terminate
projectManager.addProjectManagerListener(project, new ProjectManagerAdapter() {
@Override
public void projectClosing(Project project) {
Disposer.dispose(myInitialization);
}
});
myMappings = new NewMappings(myProject, myMessageBus, this, manager);
myMappingsToRoots = new MappingsToRoots(myMappings, myProject);
myVcsHistoryCache = new VcsHistoryCache();
myContentRevisionCache = new ContentRevisionCache();
myConnect = myMessageBus.connect();
myVcsFileListenerContextHelper = VcsFileListenerContextHelper.getInstance(myProject);
myVcsFileListenerContextHelper = vcsFileListenerContextHelper;
VcsListener vcsListener = new VcsListener() {
@Override
public void directoryMappingChanged() {
@@ -76,7 +76,7 @@ public class VcsInitialization implements Disposable {
}
}
public void execute() {
private void execute() {
final List<Pair<VcsInitObject, Runnable>> list;
synchronized (myLock) {
list = myList;
@@ -103,6 +103,11 @@ public class VcsInitialization implements Disposable {
@Override
public void dispose() {
myIndicator.cancel();
cancelBackgroundInitialization();
}
private void cancelBackgroundInitialization() {
// do not leave VCS initialization run in background when the project is closed
Future<?> future = myFuture;
if (future != null) {
future.cancel(false);
@@ -15,7 +15,6 @@
*/
package org.jetbrains.plugins.groovy.lang.psi.stubs.hierarchy;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiNameHelper;
import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree;
@@ -33,7 +32,10 @@ import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.psi.stubs.*;
import java.util.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class GrStubIndexer extends StubHierarchyIndexer {
@Override
@@ -48,14 +50,14 @@ public class GrStubIndexer extends StubHierarchyIndexer {
@Nullable
@Override
public List<Pair<String, Unit>> indexFile(@NotNull FileContent content) {
public Unit indexFile(@NotNull FileContent content) {
Stub stubTree = StubTreeBuilder.buildStubTree(content);
if (!(stubTree instanceof GrFileStub)) return null;
GrFileStub grFileStub = (GrFileStub)stubTree;
new StubTree(grFileStub, false);
String pid = null;
String pid = "";
ArrayList<ClassDecl> classList = new ArrayList<ClassDecl>();
Set<String> usedNames = new HashSet<String>();
for (StubElement<?> el : grFileStub.getChildrenStubs()) {
@@ -82,7 +84,7 @@ public class GrStubIndexer extends StubHierarchyIndexer {
}
ClassDecl[] classes = classList.isEmpty() ? ClassDecl.EMPTY_ARRAY : classList.toArray(new ClassDecl[classList.size()]);
Import[] imports = importList.isEmpty() ? Import.EMPTY_ARRAY : importList.toArray(new Import[importList.size()]);
return Collections.singletonList(Pair.create(pid, new Unit(IndexTree.GROOVY, imports, classes)));
return new Unit(pid, IndexTree.GROOVY, imports, classes);
}
@Nullable
@@ -56,6 +56,11 @@ public abstract class StudyBasePluginConfigurator implements StudyPluginConfigur
@Override
public void fileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
for (VirtualFile openedFile : source.getOpenFiles()) {
if (StudyUtils.getTaskFile(project, openedFile) != null) {
return;
}
}
toolWindow.setEmptyText(project);
}
@@ -26,6 +26,8 @@ import com.intellij.openapi.wm.ToolWindowAnchor;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.util.containers.hash.HashMap;
import com.jetbrains.edu.learning.actions.StudyActionWithShortcut;
import com.jetbrains.edu.learning.actions.StudyNextWindowAction;
import com.jetbrains.edu.learning.actions.StudyPrevWindowAction;
import com.jetbrains.edu.learning.core.EduNames;
import com.jetbrains.edu.learning.core.EduUtils;
import com.jetbrains.edu.learning.courseFormat.Course;
@@ -113,6 +115,8 @@ public class StudyProjectComponent implements ProjectComponent {
}
}
}
addShortcut(StudyNextWindowAction.ACTION_ID, new String[]{StudyNextWindowAction.SHORTCUT, StudyNextWindowAction.SHORTCUT2});
addShortcut(StudyPrevWindowAction.ACTION_ID, new String[]{StudyPrevWindowAction.SHORTCUT});
}
else {
LOG.warn("Actions on toolbar are nulls");
@@ -8,7 +8,6 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.util.ui.tree.TreeUtil;
import com.jetbrains.edu.learning.StudyState;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.core.EduNames;
@@ -44,9 +43,6 @@ abstract public class StudyTaskNavigationAction extends StudyActionWithShortcut
int nextTaskIndex = nextTask.getIndex();
int lessonIndex = nextTask.getLesson().getIndex();
Map<String, TaskFile> nextTaskFiles = nextTask.getTaskFiles();
if (nextTaskFiles.isEmpty()) {
return;
}
VirtualFile projectDir = project.getBaseDir();
String lessonDirName = EduNames.LESSON + String.valueOf(lessonIndex);
if (projectDir == null) {
@@ -61,15 +57,26 @@ abstract public class StudyTaskNavigationAction extends StudyActionWithShortcut
if (taskDir == null) {
return;
}
if (nextTaskFiles.isEmpty()) {
ProjectView.getInstance(project).select(taskDir, taskDir, false);
return;
}
VirtualFile shouldBeActive = getFileToActivate(project, nextTaskFiles, taskDir);
JTree tree = ProjectView.getInstance(project).getCurrentProjectViewPane().getTree();
TreePath path = TreeUtil.getFirstNodePath(tree);
tree.collapsePath(path);
TreePath path = tree.getSelectionPath();
if (path != null) {
TreePath oldSelectionPath = path.getParentPath();
if (oldSelectionPath != null) {
tree.collapsePath(oldSelectionPath);
tree.fireTreeCollapsed(oldSelectionPath);
}
}
if (shouldBeActive != null) {
ProjectView.getInstance(project).select(shouldBeActive, shouldBeActive, false);
FileEditorManager.getInstance(project).openFile(shouldBeActive, true);
}
ToolWindow runToolWindow = ToolWindowManager.getInstance(project).getToolWindow(ToolWindowId.RUN);
if (runToolWindow != null) {
runToolWindow.hide(null);
@@ -82,11 +89,13 @@ abstract public class StudyTaskNavigationAction extends StudyActionWithShortcut
for (Map.Entry<String, TaskFile> entry : nextTaskFiles.entrySet()) {
String name = entry.getKey();
TaskFile taskFile = entry.getValue();
VirtualFile srcDir = taskDir.findChild("src");
VirtualFile srcDir = taskDir.findChild(EduNames.SRC);
VirtualFile vf = srcDir == null ? taskDir.findChild(name) : srcDir.findChild(name);
if (vf != null) {
FileEditorManager.getInstance(project).openFile(vf, true);
if (!taskFile.getAnswerPlaceholders().isEmpty()) {
if (shouldBeActive != null) {
FileEditorManager.getInstance(project).openFile(vf, true);
}
if (shouldBeActive == null && !taskFile.getAnswerPlaceholders().isEmpty()) {
shouldBeActive = vf;
}
}
@@ -81,7 +81,8 @@ public class PyCCRunTestsConfigurationProducer extends RunConfigurationProducer<
String testsPath = taskDir.findChild(EduNames.SRC) != null ?
FileUtil.join(taskDirPath, EduNames.SRC, EduNames.TESTS_FILE) :
FileUtil.join(taskDirPath, EduNames.TESTS_FILE);
return file.getPath().equals(testsPath) ? testsPath : null;
String filePath = FileUtil.toSystemDependentName(file.getPath());
return filePath.equals(testsPath) ? testsPath : null;
}
@Override
@@ -56,10 +56,15 @@ import com.intellij.openapi.project.ProjectManagerAdapter;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.*;
import com.intellij.platform.DirectoryProjectConfigurator;
import com.intellij.platform.PlatformProjectViewOpener;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiManager;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.ui.treeStructure.Tree;
@@ -68,6 +73,7 @@ import com.intellij.util.messages.MessageBus;
import com.intellij.util.ui.tree.TreeUtil;
import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
import com.jetbrains.python.inspections.PyPep8Inspection;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -77,6 +83,7 @@ import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@@ -201,7 +208,11 @@ public class PyCharmEduInitialConfigurator {
@Override
public void run() {
if (project.isDisposed()) return;
updateInspectionsProfile();
openProjectStructure();
}
private void openProjectStructure() {
ToolWindowManager.getInstance(project).invokeLater(new Runnable() {
int count = 0;
@@ -212,12 +223,24 @@ public class PyCharmEduInitialConfigurator {
return;
}
ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow("Project");
if (toolWindow !=null && toolWindow.getType() != ToolWindowType.SLIDING) {
if (toolWindow != null && toolWindow.getType() != ToolWindowType.SLIDING) {
toolWindow.activate(null);
}
}
});
}
private void updateInspectionsProfile() {
final String[] codes = new String[]{"W29", "E501"};
final VirtualFile baseDir = project.getBaseDir();
final PsiDirectory directory = PsiManager.getInstance(project).findDirectory(baseDir);
if (directory != null) {
InspectionProjectProfileManager.getInstance(project).getInspectionProfile().modifyToolSettings(
Key.<PyPep8Inspection>create(PyPep8Inspection.INSPECTION_SHORT_NAME), directory,
inspection -> Collections.addAll(inspection.ignoredErrors, codes)
);
}
}
});
}
});
@@ -114,6 +114,31 @@ class StdIn(BaseStdIn):
return '\n'
#=======================================================================================================================
# DebugConsoleStdIn
#=======================================================================================================================
class DebugConsoleStdIn(BaseStdIn):
'''
Object to be added to stdin (to emulate it as non-blocking while the next line arrives)
'''
def __init__(self, dbg, original_stdin):
BaseStdIn.__init__(self)
self.debugger = dbg
self.original_stdin = original_stdin
def readline(self, *args, **kwargs):
# Notify Java side about input and call original function
try:
cmd = self.debugger.cmd_factory.make_input_requested_message()
self.debugger.writer.add_command(cmd)
except Exception:
import traceback
traceback.print_exc()
return '\n'
return self.original_stdin.readline(*args, **kwargs)
class CodeFragment:
def __init__(self, text, is_single_line=True):
self.text = text
@@ -138,6 +138,7 @@ CMD_GET_ARRAY = 143
CMD_STEP_INTO_MY_CODE = 144
CMD_GET_CONCURRENCY_EVENT = 145
CMD_SHOW_RETURN_VALUES = 146
CMD_INPUT_REQUESTED = 147
CMD_VERSION = 501
CMD_RETURN = 502
@@ -191,6 +192,7 @@ ID_TO_MEANING = {
'144': 'CMD_STEP_INTO_MY_CODE',
'145': 'CMD_GET_CONCURRENCY_EVENT',
'146': 'CMD_SHOW_RETURN_VALUES',
'147': 'CMD_INPUT_REQUESTED',
'501': 'CMD_VERSION',
'502': 'CMD_RETURN',
@@ -779,6 +781,13 @@ class NetCommandFactory:
except:
return self.make_error_message(0, get_exception_traceback_str())
def make_input_requested_message(self):
try:
return NetCommand(CMD_INPUT_REQUESTED, 0, '')
except:
return self.make_error_message(0, get_exception_traceback_str())
def make_exit_message(self):
try:
net = NetCommand(CMD_EXIT, 0, '')
+8
View File
@@ -1180,6 +1180,7 @@ def _locked_settrace(
if bufferStdErrToServer:
init_stderr_redirect()
patch_stdin(debugger)
debugger.set_trace_for_frame_and_parents(get_frame(), False, overwrite_prev_trace=overwrite_prev_trace)
@@ -1382,6 +1383,12 @@ def apply_debugger_options(setup_options):
enable_qt_support()
def patch_stdin(debugger):
from _pydev_bundle.pydev_console_utils import DebugConsoleStdIn
orig_stdin = sys.stdin
sys.stdin = DebugConsoleStdIn(debugger, orig_stdin)
#=======================================================================================================================
# main
#=======================================================================================================================
@@ -1512,6 +1519,7 @@ if __name__ == '__main__':
pass # It's ok not having stackless there...
is_module = setup['module']
patch_stdin(debugger)
if fix_app_engine_debug:
sys.stderr.write("pydev debugger: google app engine integration enabled\n")
@@ -139,6 +139,7 @@ public class ProjectSpecificSettingsStep extends ProjectSettingsStepBase impleme
super.initGeneratorListeners();
if (myProjectGenerator instanceof PythonProjectGenerator) {
((PythonProjectGenerator)myProjectGenerator).addSettingsStateListener(this::checkValid);
myErrorLabel.addMouseListener(((PythonProjectGenerator)myProjectGenerator).getErrorLabelMouseListener());
}
}
@@ -37,5 +37,7 @@ public interface IPyDebugProcess extends PyFrameAccessor {
boolean isSuspendedOnAllThreadsPolicy();
void consoleInputRequested();
XDebugSession getSession();
}
@@ -50,6 +50,7 @@ public abstract class AbstractCommand<T> {
public static final int STEP_INTO_MY_CODE = 144;
public static final int LOG_CONCURRENCY_EVENT = 145;
public static final int SHOW_RETURN_VALUES = 146;
public static final int INPUT_REQUESTED = 147;
public static final int ERROR = 901;
@@ -197,6 +198,10 @@ public abstract class AbstractCommand<T> {
return command == WRITE_TO_CONSOLE;
}
public static boolean isInputRequested(final int command) {
return command == INPUT_REQUESTED;
}
public static boolean isExitEvent(final int command) {
return command == EXIT;
}
@@ -547,6 +547,9 @@ public class RemoteDebugger implements ProcessDebugger {
else if (AbstractCommand.isConcurrencyEvent(frame.getCommand())) {
recordConcurrencyEvent(ProtocolParser.parseConcurrencyEvent(frame.getPayload(), myDebugProcess.getPositionConverter()));
}
else if (AbstractCommand.isInputRequested(frame.getCommand())) {
myDebugProcess.consoleInputRequested();
}
else {
placeResponse(frame.getSequence(), frame);
}
@@ -100,6 +100,10 @@ public class PydevConsoleExecuteActionHandler extends ProcessBackedConsoleExecut
sendLineToConsole(new ConsoleCommunication.ConsoleCodeFragment(myInputBuffer.toString(), false));
}
public void clearInputBuffer() {
myInputBuffer = null;
}
private void processOneLine(String line) {
int indentSize = IndentHelperImpl.getIndent(getProject(), PythonFileType.INSTANCE, line, false);
line = StringUtil.trimTrailing(line);
@@ -95,6 +95,18 @@ public class PythonConsoleView extends LanguageConsoleImpl implements Observable
myExecuteActionHandler = consoleExecuteActionHandler;
}
public void inputRequested() {
if (myExecuteActionHandler != null) {
final ConsoleCommunication consoleCommunication = myExecuteActionHandler.getConsoleCommunication();
if (consoleCommunication instanceof PythonDebugConsoleCommunication) {
((PythonDebugConsoleCommunication)consoleCommunication).waitingForInput = true;
myExecuteActionHandler.inputRequested();
myExecuteActionHandler.setEnabled(true);
myExecuteActionHandler.clearInputBuffer();
}
}
}
@Override
public void requestFocus() {
IdeFocusManager.findInstance().requestFocus(getConsoleEditor().getContentComponent(), true);

Some files were not shown because too many files have changed in this diff Show More