diff --git a/.idea/libraries/Netty.xml b/.idea/libraries/Netty.xml
index ef0ce7ca25db..c5b98b3964c1 100644
--- a/.idea/libraries/Netty.xml
+++ b/.idea/libraries/Netty.xml
@@ -1,11 +1,11 @@
-
+
-
+
\ No newline at end of file
diff --git a/images/src/org/intellij/images/util/ImageInfoReader.java b/images/src/org/intellij/images/util/ImageInfoReader.java
index 1c809bbba28f..7dd764faa328 100644
--- a/images/src/org/intellij/images/util/ImageInfoReader.java
+++ b/images/src/org/intellij/images/util/ImageInfoReader.java
@@ -16,6 +16,7 @@
package org.intellij.images.util;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.util.io.UnsyncByteArrayInputStream;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -65,7 +66,7 @@ public class ImageInfoReader {
@Nullable
private static Info read(@NotNull final byte[] data) {
- final DataInputStream is = new DataInputStream(new ByteArrayInputStream(data));
+ final DataInputStream is = new DataInputStream(new UnsyncByteArrayInputStream(data));
try {
return readFileData(is);
}
diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java
index d836d5776302..38a4c9a8c716 100644
--- a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java
+++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java
@@ -966,7 +966,8 @@ public class CompileDriver {
boolean didSomething = false;
final CompilerManager compilerManager = CompilerManager.getInstance(myProject);
- GenericCompilerRunner runner = new GenericCompilerRunner(context, myCompilerFilter, compilerManager, isRebuild, onlyCheckStatus);
+ GenericCompilerRunner runner = new GenericCompilerRunner(context, isRebuild, onlyCheckStatus,
+ compilerManager.getCompilers(GenericCompiler.class, myCompilerFilter));
try {
didSomething |= generateSources(compilerManager, context, forceCompile, onlyCheckStatus);
diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/GenericCompilerRunner.java b/java/compiler/impl/src/com/intellij/compiler/impl/GenericCompilerRunner.java
index e6e5cc500daa..f03a28617323 100644
--- a/java/compiler/impl/src/com/intellij/compiler/impl/GenericCompilerRunner.java
+++ b/java/compiler/impl/src/com/intellij/compiler/impl/GenericCompilerRunner.java
@@ -53,14 +53,12 @@ public class GenericCompilerRunner {
private final Project myProject;
public GenericCompilerRunner(CompileContext context,
- CompilerFilter compilerFilter,
- CompilerManager compilerManager,
boolean forceCompile,
- boolean onlyCheckStatus) {
+ boolean onlyCheckStatus, final GenericCompiler[] compilers) {
myContext = context;
myForceCompile = forceCompile;
myOnlyCheckStatus = onlyCheckStatus;
- myCompilers = compilerManager.getCompilers(GenericCompiler.class, compilerFilter);
+ myCompilers = compilers;
myProject = myContext.getProject();
}
@@ -69,7 +67,7 @@ public class GenericCompilerRunner {
try {
for (GenericCompiler,?,?> compiler : myCompilers) {
if (compiler.getOrderPlace().equals(place)) {
- didSomething = invokeCompiler(compiler);
+ didSomething |= invokeCompiler(compiler);
}
}
}
diff --git a/java/compiler/impl/src/com/intellij/openapi/compiler/generic/SingleTargetCompilerInstance.java b/java/compiler/impl/src/com/intellij/openapi/compiler/generic/SingleTargetCompilerInstance.java
deleted file mode 100644
index f2e4dd3ca71e..000000000000
--- a/java/compiler/impl/src/com/intellij/openapi/compiler/generic/SingleTargetCompilerInstance.java
+++ /dev/null
@@ -1,48 +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.openapi.compiler.generic;
-
-import com.intellij.openapi.compiler.CompileContext;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * @author nik
- */
-public abstract class SingleTargetCompilerInstance- , K,S, O> extends
- GenericCompilerInstance {
- protected SingleTargetCompilerInstance(CompileContext context) {
- super(context);
- }
-
- @NotNull
- @Override
- public List getAllTargets() {
- return Collections.singletonList(BuildTarget.DEFAULT);
- }
-
- @NotNull
- @Override
- public List getSelectedTargets() {
- return getAllTargets();
- }
-
- @Override
- public void processObsoleteTarget(@NotNull String targetId, @NotNull List> obsoleteItems) {
- }
-}
diff --git a/java/compiler/impl/src/com/intellij/openapi/compiler/generic/VirtualFileCompileItem.java b/java/compiler/impl/src/com/intellij/openapi/compiler/generic/VirtualFileCompileItem.java
index 03a14bd0d63c..b1e5394fc60d 100644
--- a/java/compiler/impl/src/com/intellij/openapi/compiler/generic/VirtualFileCompileItem.java
+++ b/java/compiler/impl/src/com/intellij/openapi/compiler/generic/VirtualFileCompileItem.java
@@ -16,8 +16,6 @@
package com.intellij.openapi.compiler.generic;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.io.EnumeratorStringDescriptor;
-import com.intellij.util.io.KeyDescriptor;
import org.jetbrains.annotations.NotNull;
/**
diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/run/BuildArtifactsBeforeRunTaskProvider.java b/java/compiler/impl/src/com/intellij/packaging/impl/run/BuildArtifactsBeforeRunTaskProvider.java
index 3b0e586020f2..ee2315e3a046 100644
--- a/java/compiler/impl/src/com/intellij/packaging/impl/run/BuildArtifactsBeforeRunTaskProvider.java
+++ b/java/compiler/impl/src/com/intellij/packaging/impl/run/BuildArtifactsBeforeRunTaskProvider.java
@@ -99,6 +99,7 @@ public class BuildArtifactsBeforeRunTaskProvider extends BeforeRunTaskProvider" : psiMethod.getName();
- myTargetMethodSignature = JVMNameUtil.getJVMSignature(psiMethod);
+ this(JVMNameUtil.getJVMQualifiedName(psiMethod.getContainingClass()),
+ psiMethod.isConstructor()? "" : psiMethod.getName(),
+ JVMNameUtil.getJVMSignature(psiMethod));
+ }
+
+ public SmartStepFilter(@NotNull JVMName declaringClassName, @NonNls String targetMethodName,
+ @NotNull JVMName targetMethodSignature) {
+ myDeclaringClassName = declaringClassName;
+ myTargetMethodName = targetMethodName;
+ myTargetMethodSignature = targetMethodSignature;
}
public String getTargetMethodName() {
diff --git a/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java b/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java
index 5097256ac559..89cc65ebeeaf 100644
--- a/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java
+++ b/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java
@@ -30,6 +30,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.util.ClassUtil;
import com.intellij.psi.util.PsiClassUtil;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
@@ -106,14 +107,7 @@ public class JavaExecutionUtil {
@Nullable
public static String getRuntimeQualifiedName(final PsiClass aClass) {
- final PsiClass containingClass = aClass.getContainingClass();
- if (containingClass != null) {
- final String parentName = getRuntimeQualifiedName(containingClass);
- return parentName + "$" + aClass.getName();
- }
- else {
- return aClass.getQualifiedName();
- }
+ return ClassUtil.getJVMClassName(aClass);
}
@Nullable
diff --git a/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImplementationHelperImpl.java b/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImplementationHelperImpl.java
index 0c0abdce08d1..46812a81f005 100644
--- a/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImplementationHelperImpl.java
+++ b/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImplementationHelperImpl.java
@@ -16,7 +16,6 @@
package com.intellij.psi.impl.file;
import com.intellij.ide.projectView.ProjectView;
-import com.intellij.ide.projectView.impl.ProjectViewPane;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.undo.GlobalUndoableAction;
import com.intellij.openapi.command.undo.UndoManager;
@@ -139,7 +138,7 @@ public class PsiPackageImplementationHelperImpl extends PsiPackageImplementation
final ProjectView projectView = ProjectView.getInstance(project);
PsiDirectory[] directories = suggestMostAppropriateDirectories(psiPackage);
if (directories.length == 0) return;
- projectView.getProjectViewPaneById(ProjectViewPane.ID).select(directories[0], directories[0].getVirtualFile(), requestFocus);
+ projectView.select(directories[0], directories[0].getVirtualFile(), requestFocus);
}
});
}
diff --git a/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.form b/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.form
index b0ee1e42eb87..96720321c9fe 100644
--- a/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.form
+++ b/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.form
@@ -71,6 +71,7 @@
+
@@ -81,11 +82,12 @@
+
-
+
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java
index 22e98032eb8a..c9f49dbf0d19 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -16,15 +16,15 @@
package com.intellij.codeInsight;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.NullableComputable;
import com.intellij.psi.*;
import com.intellij.psi.controlFlow.*;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.util.InheritanceUtil;
-import com.intellij.psi.util.PsiUtil;
-import com.intellij.psi.util.TypeConversionUtil;
+import com.intellij.psi.search.ProjectScope;
+import com.intellij.psi.util.*;
import com.intellij.util.NullableFunction;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
@@ -347,18 +347,26 @@ public class ExceptionUtil {
@NotNull
public static List getUnhandledCloserExceptions(final PsiResourceVariable resource, @Nullable final PsiElement topElement) {
- final PsiType resourceType = resource.getType();
- if (resourceType instanceof PsiClassType) {
- final PsiClass resourceClass = ((PsiClassType)resourceType).resolve();
- if (resourceClass != null) {
- final PsiMethod[] closers = resourceClass.findMethodsByName("close", false);
- for (final PsiMethod method : closers) {
- if (method.getParameterList().getParametersCount() == 0) {
- return getUnhandledExceptions(method, resource, topElement, PsiSubstitutor.EMPTY);
+ final Project project = resource.getProject();
+ final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
+ final PsiClass autoCloseable = facade.findClass(CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE, ProjectScope.getLibrariesScope(project));
+ if (autoCloseable != null) {
+ final PsiMethod[] methods = autoCloseable.findMethodsByName("close", false);
+ if (methods.length == 1) {
+ final MethodSignature signature = methods[0].getSignature(PsiSubstitutor.EMPTY);
+ final PsiType resourceType = resource.getType();
+ if (resourceType instanceof PsiClassType) {
+ final PsiClass resourceClass = ((PsiClassType)resourceType).resolve();
+ if (resourceClass != null) {
+ final PsiMethod method = MethodSignatureUtil.findMethodBySignature(resourceClass, signature, true);
+ if (method != null) {
+ return getUnhandledExceptions(method, resource, topElement, PsiSubstitutor.EMPTY);
+ }
}
}
}
}
+
return Collections.emptyList();
}
diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java
index ccb8e83f70e2..510cab79e4de 100644
--- a/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java
+++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java
@@ -27,6 +27,7 @@ import com.intellij.psi.tree.TokenSet;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.PropertyKey;
import static com.intellij.lang.PsiBuilderUtil.expect;
import static com.intellij.lang.PsiBuilderUtil.nextTokenType;
@@ -86,7 +87,7 @@ public class DeclarationParser {
}
parseClassBodyDeclarations(builderWrapper, isAnnotation);
- expectOrError(builder, JavaTokenType.RBRACE, JavaErrorMessages.message("expected.rbrace"));
+ expectOrError(builder, JavaTokenType.RBRACE, "expected.rbrace");
}
@Nullable
@@ -139,7 +140,7 @@ public class DeclarationParser {
}
if (declarationsAfterEnd) {
- expectOrError(builder, JavaTokenType.RBRACE, JavaErrorMessages.message("expected.rbrace"));
+ expectOrError(builder, JavaTokenType.RBRACE, "expected.rbrace");
}
}
@@ -426,7 +427,7 @@ public class DeclarationParser {
final boolean anno, final boolean constructor) {
parseParameterList(builder);
- eatBrackets(builder, constructor, JavaErrorMessages.message("expected.semicolon"));
+ eatBrackets(builder, constructor, "expected.semicolon");
if (areTypeAnnotationsSupported(builder)) {
final PsiBuilder.Marker receiver = builder.mark();
@@ -489,8 +490,8 @@ public class DeclarationParser {
builder.advanceLexer();
final IElementType delimiter = resources ? JavaTokenType.SEMICOLON : JavaTokenType.COMMA;
- final String noDelimiterMsg = JavaErrorMessages.message(resources ? "expected.semicolon" : "expected.comma");
- final String noElementMsg = JavaErrorMessages.message(resources ? "expected.resource" : "expected.parameter");
+ final String noDelimiterMsg = resources ? "expected.semicolon" : "expected.comma";
+ final String noElementMsg = resources ? "expected.resource" : "expected.parameter";
PsiBuilder.Marker invalidElements = null;
String errorMessage = null;
@@ -548,7 +549,7 @@ public class DeclarationParser {
if (invalidElements == null) {
if (builder.getTokenType() == delimiter) {
- error(builder, noElementMsg);
+ error(builder, JavaErrorMessages.message(noElementMsg));
builder.advanceLexer();
if (noElements && resources) {
noElements = false;
@@ -557,7 +558,7 @@ public class DeclarationParser {
}
else {
invalidElements = builder.mark();
- errorMessage = delimiterExpected ? noDelimiterMsg : noElementMsg;
+ errorMessage = JavaErrorMessages.message(delimiterExpected ? noDelimiterMsg : noElementMsg);
}
}
@@ -613,7 +614,7 @@ public class DeclarationParser {
if (expect(builder, JavaTokenType.IDENTIFIER)) {
if (!resource) {
- eatBrackets(builder, typeInfo != null && typeInfo.isVarArg, JavaErrorMessages.message("expected.rparen"));
+ eatBrackets(builder, typeInfo != null && typeInfo.isVarArg, "expected.rparen");
done(param, JavaElementType.PARAMETER);
return param;
}
@@ -624,7 +625,7 @@ public class DeclarationParser {
return modListInfo.first;
}
- if (expectOrError(builder, JavaTokenType.EQ, JavaErrorMessages.message("expected.eq"))) {
+ if (expectOrError(builder, JavaTokenType.EQ, "expected.eq")) {
if (myExpressionParser.parse(builder) == null) {
error(builder, JavaErrorMessages.message("expected.expression"));
}
@@ -720,7 +721,8 @@ public class DeclarationParser {
return declaration;
}
- private static boolean eatBrackets(final PsiBuilder builder, final boolean isError, @Nullable final String error) {
+ private static boolean eatBrackets(final PsiBuilder builder, final boolean isError,
+ @Nullable @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String errorKey) {
if (builder.getTokenType() != JavaTokenType.LBRACKET) return true;
final PsiBuilder.Marker marker = isError ? builder.mark() : null;
@@ -735,7 +737,7 @@ public class DeclarationParser {
}
if (marker != null) {
- marker.error(error);
+ marker.error(errorKey != null ? JavaErrorMessages.message(errorKey):null);
}
return result;
@@ -840,9 +842,9 @@ public class DeclarationParser {
pair = builder.mark();
}
- final boolean hasName = expectOrError(builder, JavaTokenType.IDENTIFIER, JavaErrorMessages.message("expected.identifier"));
+ final boolean hasName = expectOrError(builder, JavaTokenType.IDENTIFIER, "expected.identifier");
- expectOrError(builder, JavaTokenType.EQ, JavaErrorMessages.message("expected.eq"));
+ expectOrError(builder, JavaTokenType.EQ, "expected.eq");
parseAnnotationValue(builder);
diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java
index 8424d8defa81..2699fad161ca 100644
--- a/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java
+++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -404,7 +404,7 @@ public class ExpressionParser {
final PsiBuilder.Marker refExpr = expr.precede();
myReferenceParser.parseReferenceParameterList(builder, false, false);
- if (!JavaParserUtil.expectOrError(builder, JavaTokenType.IDENTIFIER, JavaErrorMessages.message("expected.identifier"))) {
+ if (!JavaParserUtil.expectOrError(builder, JavaTokenType.IDENTIFIER, "expected.identifier")) {
refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
startMarker.drop();
return refExpr;
@@ -726,7 +726,7 @@ public class ExpressionParser {
}
bracketCount++;
- if (!JavaParserUtil.expectOrError(builder, JavaTokenType.RBRACKET, JavaErrorMessages.message("expected.rbracket"))) {
+ if (!JavaParserUtil.expectOrError(builder, JavaTokenType.RBRACKET, "expected.rbracket")) {
newExpr.done(JavaElementType.NEW_EXPRESSION);
return newExpr;
}
@@ -812,7 +812,7 @@ public class ExpressionParser {
}
}
- final boolean closed = JavaParserUtil.expectOrError(builder, JavaTokenType.RPARENTH, JavaErrorMessages.message("expected.rparen"));
+ final boolean closed = JavaParserUtil.expectOrError(builder, JavaTokenType.RPARENTH, "expected.rparen");
list.done(JavaElementType.EXPRESSION_LIST);
if (!closed) {
@@ -827,35 +827,29 @@ public class ExpressionParser {
@Nullable
private static IElementType getGtTokenType(final PsiBuilder builder) {
- final PsiBuilder.Marker sp = builder.mark();
-
IElementType tokenType = builder.getTokenType();
- if (tokenType == JavaTokenType.GT) {
- builder.advanceLexer();
- if (builder.getTokenType() == JavaTokenType.GT) {
- builder.advanceLexer();
- if (builder.getTokenType() == JavaTokenType.GT) {
- builder.advanceLexer();
- if (builder.getTokenType() == JavaTokenType.EQ) {
- tokenType = JavaTokenType.GTGTGTEQ;
- }
- else {
- tokenType = JavaTokenType.GTGTGT;
- }
- }
- else if (builder.getTokenType() == JavaTokenType.EQ) {
- tokenType = JavaTokenType.GTGTEQ;
+ if (tokenType != JavaTokenType.GT) return tokenType;
+
+ if (builder.rawLookup(1) == JavaTokenType.GT) {
+ if (builder.rawLookup(2) == JavaTokenType.GT) {
+ if (builder.rawLookup(3) == JavaTokenType.EQ) {
+ tokenType = JavaTokenType.GTGTGTEQ;
}
else {
- tokenType = JavaTokenType.GTGT;
+ tokenType = JavaTokenType.GTGTGT;
}
}
- else if (builder.getTokenType() == JavaTokenType.EQ) {
- tokenType = JavaTokenType.GE;
+ else if (builder.rawLookup(2) == JavaTokenType.EQ) {
+ tokenType = JavaTokenType.GTGTEQ;
+ }
+ else {
+ tokenType = JavaTokenType.GTGT;
}
}
+ else if (builder.rawLookup(1) == JavaTokenType.EQ) {
+ tokenType = JavaTokenType.GE;
+ }
- sp.rollbackTo();
return tokenType;
}
diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java
index d3fd09cc889f..6af4ce564138 100644
--- a/java/java-psi-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java
+++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java
@@ -39,6 +39,7 @@ import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.PropertyKey;
import java.util.List;
@@ -258,9 +259,10 @@ public class JavaParserUtil {
}
}
- public static boolean expectOrError(final PsiBuilder builder, final IElementType expectedType, final String errorMessage) {
+ public static boolean expectOrError(final PsiBuilder builder, final IElementType expectedType,
+ @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String errorMessageKey) {
if (!PsiBuilderUtil.expect(builder, expectedType)) {
- error(builder, errorMessage);
+ error(builder, JavaErrorMessages.message(errorMessageKey));
return false;
}
return true;
@@ -275,7 +277,7 @@ public class JavaParserUtil {
}
public static void semicolon(final PsiBuilder builder) {
- expectOrError(builder, JavaTokenType.SEMICOLON, JavaErrorMessages.message("expected.semicolon"));
+ expectOrError(builder, JavaTokenType.SEMICOLON, "expected.semicolon");
}
public static PsiBuilder braceMatchingBuilder(final PsiBuilder builder) {
diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java
index 68fd2ff197e3..9382af0cac6b 100644
--- a/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java
+++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java
@@ -293,7 +293,7 @@ public class ReferenceParser {
if (expect(builder, JavaTokenType.GT)) {
break;
}
- else if (!expectOrError(builder, JavaTokenType.COMMA, JavaErrorMessages.message("expected.gt.or.comma"))) {
+ else if (!expectOrError(builder, JavaTokenType.COMMA, "expected.gt.or.comma")) {
isOk = false;
break;
}
diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/StatementParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/StatementParser.java
index b4294f6a4cd9..95ad7cfd72a8 100644
--- a/java/java-psi-impl/src/com/intellij/lang/java/parser/StatementParser.java
+++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/StatementParser.java
@@ -131,7 +131,7 @@ public class StatementParser {
parseStatements(builder, parseUntilEof ? BraceMode.TILL_LAST : BraceMode.TILL_FIRST);
- final boolean greedyBlock = !expectOrError(builder, JavaTokenType.RBRACE, JavaErrorMessages.message("expected.rbrace"));
+ final boolean greedyBlock = !expectOrError(builder, JavaTokenType.RBRACE, "expected.rbrace");
builder.getTokenType(); // eat spaces
done(codeBlock, JavaElementType.CODE_BLOCK);
@@ -543,7 +543,7 @@ public class StatementParser {
}
}
- expectOrError(builder, JavaTokenType.COLON, JavaErrorMessages.message("expected.colon"));
+ expectOrError(builder, JavaTokenType.COLON, "expected.colon");
done(statement, JavaElementType.SWITCH_LABEL_STATEMENT);
return statement;
diff --git a/java/java-psi-impl/src/messages/JavaErrorMessages.properties b/java/java-psi-impl/src/messages/JavaErrorMessages.properties
index 317aeb1326bb..1c83fe4b3480 100644
--- a/java/java-psi-impl/src/messages/JavaErrorMessages.properties
+++ b/java/java-psi-impl/src/messages/JavaErrorMessages.properties
@@ -328,6 +328,7 @@ expected.lparen.or.lbracket='(' or '[' expected
expected.array.initializer=Array initializer expected
unexpected.tokens=Unexpected tokens
expected.gt.or.comma='>' or ',' expected.
+string.expected=String literal expected
else.without.if='else' without 'if'
catch.without.try='catch' without 'try'
finally.without.try='finally' without 'try'
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResources.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResources.java
index e8df782c83ac..c0f8eb7cc342 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResources.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResources.java
@@ -1,3 +1,18 @@
+/*
+ * 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.
+ */
class C {
static class E extends Exception { }
static class E1 extends E { }
@@ -10,6 +25,8 @@ class C {
@Override public void close() throws E3 { }
}
+ static interface I extends AutoCloseable { }
+
void m1() {
try (MyResource r = new MyResource()) { r.doSomething(); }
catch (E1 | E2 | E3 ignore) { }
@@ -24,6 +41,8 @@ class C {
catch (E3 e) { }
try (MyResource r = new MyResource()) { }
+
+ try (I r = null) { System.out.println(r); }
}
void m2() throws Exception {
diff --git a/java/java-tests/testData/psi/parser-partial/expressions/Binary2.txt b/java/java-tests/testData/psi/parser-partial/expressions/Binary2.txt
new file mode 100644
index 000000000000..f9e60382ce09
--- /dev/null
+++ b/java/java-tests/testData/psi/parser-partial/expressions/Binary2.txt
@@ -0,0 +1,18 @@
+PsiJavaFile:Binary2.java
+ PsiAssignmentExpression:a > = b
+ PsiBinaryExpression:a >
+ PsiReferenceExpression:a
+ PsiReferenceParameterList
+
+ PsiIdentifier:a('a')
+ PsiWhiteSpace(' ')
+ PsiJavaToken:GT('>')
+ PsiErrorElement:Expression expected
+
+ PsiWhiteSpace(' ')
+ PsiJavaToken:EQ('=')
+ PsiWhiteSpace(' ')
+ PsiReferenceExpression:b
+ PsiReferenceParameterList
+
+ PsiIdentifier:b('b')
\ No newline at end of file
diff --git a/java/java-tests/testData/psi/parser-partial/expressions/Binary3.txt b/java/java-tests/testData/psi/parser-partial/expressions/Binary3.txt
new file mode 100644
index 000000000000..5e5a0718daf8
--- /dev/null
+++ b/java/java-tests/testData/psi/parser-partial/expressions/Binary3.txt
@@ -0,0 +1,18 @@
+PsiJavaFile:Binary3.java
+ PsiAssignmentExpression:a >/**/= b
+ PsiBinaryExpression:a >
+ PsiReferenceExpression:a
+ PsiReferenceParameterList
+
+ PsiIdentifier:a('a')
+ PsiWhiteSpace(' ')
+ PsiJavaToken:GT('>')
+ PsiErrorElement:Expression expected
+
+ PsiComment(C_STYLE_COMMENT)('/**/')
+ PsiJavaToken:EQ('=')
+ PsiWhiteSpace(' ')
+ PsiReferenceExpression:b
+ PsiReferenceParameterList
+
+ PsiIdentifier:b('b')
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/lang/java/lexer/JavaLexerTest.java b/java/java-tests/testSrc/com/intellij/lang/java/lexer/JavaLexerTest.java
index 85e3069f767d..b4e835b2a079 100644
--- a/java/java-tests/testSrc/com/intellij/lang/java/lexer/JavaLexerTest.java
+++ b/java/java-tests/testSrc/com/intellij/lang/java/lexer/JavaLexerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -54,7 +54,7 @@ public class JavaLexerTest extends LexerTestCase {
"DOUBLE_LITERAL ('1e137')");
}
- public void testTigerNumericLiterals() throws Exception {
+ public void testTigerNumericLiterals() {
doTest("0xap0f 0xab.p0F 0x.abcP0f 0xabc.defP0F",
"FLOAT_LITERAL ('0xap0f')\nWHITE_SPACE (' ')\n" +
"FLOAT_LITERAL ('0xab.p0F')\nWHITE_SPACE (' ')\n" +
@@ -115,7 +115,7 @@ public class JavaLexerTest extends LexerTestCase {
"DOUBLE_LITERAL ('0xa_bc.de_fP1_234D')");
}
- public void testMalformedCoinLiterals() throws Exception {
+ public void testMalformedCoinLiterals() {
doTest("0_ _1 0_8 0x_f 0b_1 0B2 0x1.0_p-1 1.0e_1022",
"INTEGER_LITERAL ('0')\nIDENTIFIER ('_')\nWHITE_SPACE (' ')\n" +
"IDENTIFIER ('_1')\nWHITE_SPACE (' ')\n" +
@@ -127,6 +127,13 @@ public class JavaLexerTest extends LexerTestCase {
"DOUBLE_LITERAL ('1.0e')\nIDENTIFIER ('_1022')");
}
+ public void testMalformedOperators() {
+ doTest("(i > = 0)",
+ "LPARENTH ('(')\nIDENTIFIER ('i')\nWHITE_SPACE (' ')\n" +
+ "GT ('>')\nWHITE_SPACE (' ')\nEQ ('=')\n" +
+ "WHITE_SPACE (' ')\nINTEGER_LITERAL ('0')\nRPARENTH (')')\n");
+ }
+
@Override
protected Lexer createLexer() {
return new JavaLexer(LanguageLevel.HIGHEST);
diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java
index fdc02ee9bf87..471190ed3179 100644
--- a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java
+++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -32,6 +32,8 @@ public class ExpressionParserTest extends JavaParsingTestCase {
public void testBinary0() { doParserTest("a + b"); }
public void testBinary1() { doParserTest("a < b"); }
+ public void testBinary2() { doParserTest("a > = b"); }
+ public void testBinary3() { doParserTest("a >/**/= b"); }
public void testCond0() { doParserTest("cond ? true : false"); }
public void testCond1() { doParserTest("cond ?"); }
diff --git a/java/openapi/src/com/intellij/psi/util/ClassUtil.java b/java/openapi/src/com/intellij/psi/util/ClassUtil.java
index 18038c40c13d..d7f8aa2a27c2 100644
--- a/java/openapi/src/com/intellij/psi/util/ClassUtil.java
+++ b/java/openapi/src/com/intellij/psi/util/ClassUtil.java
@@ -245,26 +245,19 @@ public class ClassUtil {
@Nullable
public static String getJVMClassName(PsiClass aClass) {
- final String qName = aClass.getQualifiedName();
- if (qName == null) return null;
- return replaceDotsWithDollars(qName, aClass);
- }
-
- private static String replaceDotsWithDollars(final String qName, PsiClass aClass) {
- StringBuilder qNameBuffer = new StringBuilder(qName);
-
- int fromIndex = qNameBuffer.length();
- PsiElement parent = aClass.getParent();
- while (parent instanceof PsiClass) {
- final int dotIndex = qNameBuffer.lastIndexOf(".", fromIndex);
- if (dotIndex < 0) break;
- qNameBuffer.replace(dotIndex, dotIndex + 1, "$");
- fromIndex = dotIndex - 1;
- parent = parent.getParent();
+ final PsiClass containingClass = aClass.getContainingClass();
+ if (containingClass != null) {
+ String parentName = getJVMClassName(containingClass);
+ if (parentName == null) {
+ return null;
+ }
+
+ return parentName + "$" + aClass.getName();
}
- return qNameBuffer.toString();
+ return aClass.getQualifiedName();
}
+
@Nullable
public static PsiClass findPsiClassByJVMName(final PsiManager manager, final String jvmClassName) {
return findPsiClass(manager, jvmClassName.replace('/', '.'), null, true);
diff --git a/java/testFramework/src/com/intellij/testFramework/fixtures/DefaultLightProjectDescriptor.java b/java/testFramework/src/com/intellij/testFramework/fixtures/DefaultLightProjectDescriptor.java
index 44ce03bbb0ab..1dc3be12660e 100644
--- a/java/testFramework/src/com/intellij/testFramework/fixtures/DefaultLightProjectDescriptor.java
+++ b/java/testFramework/src/com/intellij/testFramework/fixtures/DefaultLightProjectDescriptor.java
@@ -42,6 +42,9 @@ public class DefaultLightProjectDescriptor implements LightProjectDescriptor {
@Override
public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) {
- model.getModuleExtension(LanguageLevelModuleExtension.class).setLanguageLevel(LanguageLevel.HIGHEST);
+ LanguageLevelModuleExtension extension = model.getModuleExtension(LanguageLevelModuleExtension.class);
+ if (extension != null) {
+ extension.setLanguageLevel(LanguageLevel.HIGHEST);
+ }
}
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/Builder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/Builder.java
index 2c642f0df771..4bfc4b9c294e 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/Builder.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/Builder.java
@@ -1,160 +1,10 @@
package org.jetbrains.jps.incremental;
-import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.io.FileUtil;
-import org.jetbrains.ether.dependencyView.Mappings;
-import org.jetbrains.jps.Module;
-import org.jetbrains.jps.ModuleChunk;
-import org.jetbrains.jps.incremental.storage.SourceToOutputMapping;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.*;
-
/**
- * @author Eugene Zhuravlev
- * Date: 9/17/11
+ * @author nik
*/
public abstract class Builder {
- private static final Key> ALL_AFFECTED_FILES_KEY = Key.create("_all_affected_files_");
- private static final Key> ALL_COMPILED_FILES_KEY = Key.create("_all_compiled_files_");
-
- public static enum ExitCode {
- OK, ABORT, ADDITIONAL_PASS_REQUIRED
- }
-
public abstract String getName();
- public abstract ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException;
-
public abstract String getDescription();
-
- public void cleanupResources(CompileContext context, ModuleChunk chunk) {
- ALL_AFFECTED_FILES_KEY.set(context, null);
- ALL_COMPILED_FILES_KEY.set(context, null);
- }
-
- /**
- * @param context
- * @param delta
- * @param chunk
- * @param filesToCompile files compiled in this round
- * @param successfullyCompiled
- * @return true if additional compilation pass is required, false otherwise
- * @throws Exception
- */
- public final boolean updateMappings(CompileContext context, final Mappings delta, ModuleChunk chunk, Collection filesToCompile, Collection successfullyCompiled) throws Exception {
- try {
- boolean additionalPassRequired = false;
-
- final Set removedPaths = getRemovedPaths(context);
-
- final Mappings globalMappings = context.getDataManager().getMappings();
-
- //noinspection SynchronizationOnLocalVariableOrMethodParameter
- synchronized (globalMappings) {
- if (!context.isProjectRebuild() && context.shouldDifferentiate(chunk, context.isCompilingTests())) {
- final Set allCompiledFiles = getAllCompiledFilesContainer(context);
- final Set allAffectedFiles = getAllAffectedFilesContainer(context);
-
- // mark as affected all files that were dirty before compilation
- allAffectedFiles.addAll(filesToCompile);
- // accumulate all successfully compiled in this round
- allCompiledFiles.addAll(successfullyCompiled);
- // unmark as affected all successfully compiled
- allAffectedFiles.removeAll(successfullyCompiled);
-
- final HashSet affectedBeforeDif = new HashSet(allAffectedFiles);
-
- final boolean incremental = globalMappings.differentiate(
- delta, removedPaths, successfullyCompiled, allCompiledFiles, allAffectedFiles
- );
-
- if (incremental) {
- final Set newlyAffectedFiles = new HashSet(allAffectedFiles);
- newlyAffectedFiles.removeAll(affectedBeforeDif);
- newlyAffectedFiles.removeAll(allCompiledFiles); // the diff operation may have affected the class already compiled in thic compilation round
-
- if (!newlyAffectedFiles.isEmpty()) {
- for (File file : newlyAffectedFiles) {
- context.markDirty(file);
- }
- additionalPassRequired = context.isMake() && chunkContainsAffectedFiles(context, chunk, newlyAffectedFiles);
- }
- }
- else {
- additionalPassRequired = context.isMake();
- context.markDirtyRecursively(chunk);
- }
- }
-
- globalMappings.integrate(delta, successfullyCompiled, removedPaths);
- }
-
- return additionalPassRequired;
- }
- catch(RuntimeException e) {
- final Throwable cause = e.getCause();
- if (cause instanceof IOException) {
- throw ((IOException)cause);
- }
- throw e;
- }
- }
-
- // delete all class files that according to mappings correspond to given sources
- public static void deleteCorrespondingOutputFiles(CompileContext context, Map sources) throws Exception {
- if (!context.isProjectRebuild() && !sources.isEmpty()) {
- for (Map.Entry pair : sources.entrySet()) {
- final File file = pair.getKey();
- final String srcPath = FileUtil.toSystemIndependentName(file.getPath());
- final String moduleName = pair.getValue().getName().toLowerCase(Locale.US);
- final SourceToOutputMapping srcToOut = context.getDataManager().getSourceToOutputMap(moduleName, context.isCompilingTests());
- final Collection outputs = srcToOut.getState(srcPath);
- if (outputs != null) {
- for (String output : outputs) {
- FileUtil.delete(new File(output));
- }
- srcToOut.remove(srcPath);
- }
- }
- }
- }
-
- private static boolean chunkContainsAffectedFiles(CompileContext context, ModuleChunk chunk, final Set affected) throws Exception {
- final Set chunkModules = new HashSet(chunk.getModules());
- if (!chunkModules.isEmpty()) {
- for (File file : affected) {
- final RootDescriptor moduleAndRoot = context.getModuleAndRoot(file);
- if (moduleAndRoot != null && chunkModules.contains(moduleAndRoot.module)) {
- return true;
- }
- }
- }
- return false;
- }
-
- private static Set getAllAffectedFilesContainer(CompileContext context) {
- Set allAffectedFiles = ALL_AFFECTED_FILES_KEY.get(context);
- if (allAffectedFiles == null) {
- allAffectedFiles = new HashSet();
- ALL_AFFECTED_FILES_KEY.set(context, allAffectedFiles);
- }
- return allAffectedFiles;
- }
-
- private static Set getAllCompiledFilesContainer(CompileContext context) {
- Set allCompiledFiles = ALL_COMPILED_FILES_KEY.get(context);
- if (allCompiledFiles == null) {
- allCompiledFiles = new HashSet();
- ALL_COMPILED_FILES_KEY.set(context, allCompiledFiles);
- }
- return allCompiledFiles;
- }
-
- private static Set getRemovedPaths(CompileContext context) {
- final Set removed = Paths.CHUNK_REMOVED_SOURCES_KEY.get(context);
- return removed != null? removed : Collections.emptySet();
- }
-
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java
index 7840245b8409..51a128ddc6ff 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java
@@ -2,7 +2,7 @@ package org.jetbrains.jps.incremental;
import org.jetbrains.jps.incremental.groovy.GroovyBuilder;
import org.jetbrains.jps.incremental.java.JavaBuilder;
-import org.jetbrains.jps.incremental.resourses.ResourcesBuilder;
+import org.jetbrains.jps.incremental.resources.ResourcesBuilder;
import java.util.*;
import java.util.concurrent.ExecutorService;
@@ -16,7 +16,7 @@ public class BuilderRegistry {
private static class Holder {
static final BuilderRegistry ourInstance = new BuilderRegistry();
}
- private final Map> myBuilders = new HashMap>();
+ private final Map> myBuilders = new HashMap>();
private ExecutorService myTasksExecutor;
public static BuilderRegistry getInstance() {
@@ -25,7 +25,7 @@ public class BuilderRegistry {
private BuilderRegistry() {
for (BuilderCategory category : BuilderCategory.values()) {
- myBuilders.put(category, new ArrayList());
+ myBuilders.put(category, new ArrayList());
}
final Runtime runtime = Runtime.getRuntime();
myTasksExecutor = Executors.newFixedThreadPool(runtime.availableProcessors());
@@ -60,7 +60,7 @@ public class BuilderRegistry {
return Collections.emptyList(); // todo
}
- public List getBuilders(BuilderCategory category){
+ public List getBuilders(BuilderCategory category){
return Collections.unmodifiableList(myBuilders.get(category)); // todo
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java
index 65efacbb9bcb..ccfa9e42dc4b 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java
@@ -314,7 +314,7 @@ public class IncProjectBuilder {
finally {
try {
for (BuilderCategory category : BuilderCategory.values()) {
- for (Builder builder : myBuilderRegistry.getBuilders(category)) {
+ for (ModuleLevelBuilder builder : myBuilderRegistry.getBuilders(category)) {
builder.cleanupResources(context, chunk);
}
}
@@ -334,7 +334,7 @@ public class IncProjectBuilder {
}
private void runBuilders(CompileContext context, ModuleChunk chunk, BuilderCategory category) throws ProjectBuildException {
- final List builders = myBuilderRegistry.getBuilders(category);
+ final List builders = myBuilderRegistry.getBuilders(category);
if (builders.isEmpty()) {
return;
}
@@ -347,16 +347,16 @@ public class IncProjectBuilder {
do {
nextPassRequired = false;
context.beforeNextCompileRound(chunk);
- for (Builder builder : builders) {
- final Builder.ExitCode buildResult = builder.build(context, chunk);
+ for (ModuleLevelBuilder builder : builders) {
+ final ModuleLevelBuilder.ExitCode buildResult = builder.build(context, chunk);
- if (buildResult == Builder.ExitCode.ABORT) {
+ if (buildResult == ModuleLevelBuilder.ExitCode.ABORT) {
throw new ProjectBuildException("Builder " + builder.getDescription() + " requested build stop");
}
if (myCancelStatus.isCanceled()) {
throw new ProjectBuildException(CANCELED_MESSAGE);
}
- if (buildResult == Builder.ExitCode.ADDITIONAL_PASS_REQUIRED) {
+ if (buildResult == ModuleLevelBuilder.ExitCode.ADDITIONAL_PASS_REQUIRED) {
if (!nextPassRequired) {
// recalculate basis
myModulesProcessed -= (stagesPassed * modulesInChunk) / stageCount;
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java
new file mode 100644
index 000000000000..314187fa1100
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java
@@ -0,0 +1,177 @@
+package org.jetbrains.jps.incremental;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.ether.dependencyView.Mappings;
+import org.jetbrains.jps.Module;
+import org.jetbrains.jps.ModuleChunk;
+import org.jetbrains.jps.incremental.storage.SourceToOutputMapping;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 9/17/11
+ */
+public abstract class ModuleLevelBuilder extends Builder {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.Builder");
+
+ private static final Key> ALL_AFFECTED_FILES_KEY = Key.create("_all_affected_files_");
+ private static final Key> ALL_COMPILED_FILES_KEY = Key.create("_all_compiled_files_");
+
+ public static enum ExitCode {
+ OK, ABORT, ADDITIONAL_PASS_REQUIRED
+ }
+
+ public abstract ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException;
+
+ public void cleanupResources(CompileContext context, ModuleChunk chunk) {
+ ALL_AFFECTED_FILES_KEY.set(context, null);
+ ALL_COMPILED_FILES_KEY.set(context, null);
+ }
+
+ /**
+ * @param context
+ * @param delta
+ * @param chunk
+ * @param filesToCompile files compiled in this round
+ * @param successfullyCompiled
+ * @return true if additional compilation pass is required, false otherwise
+ * @throws Exception
+ */
+ public final boolean updateMappings(CompileContext context, final Mappings delta, ModuleChunk chunk, Collection filesToCompile, Collection successfullyCompiled) throws Exception {
+ try {
+ boolean additionalPassRequired = false;
+
+ final Set removedPaths = getRemovedPaths(context);
+
+ final Mappings globalMappings = context.getDataManager().getMappings();
+
+ //noinspection SynchronizationOnLocalVariableOrMethodParameter
+ synchronized (globalMappings) {
+ if (!context.isProjectRebuild() && context.shouldDifferentiate(chunk, context.isCompilingTests())) {
+ final Set allCompiledFiles = getAllCompiledFilesContainer(context);
+ final Set allAffectedFiles = getAllAffectedFilesContainer(context);
+
+ // mark as affected all files that were dirty before compilation
+ allAffectedFiles.addAll(filesToCompile);
+ // accumulate all successfully compiled in this round
+ allCompiledFiles.addAll(successfullyCompiled);
+ // unmark as affected all successfully compiled
+ allAffectedFiles.removeAll(successfullyCompiled);
+
+ final HashSet affectedBeforeDif = new HashSet(allAffectedFiles);
+
+ final boolean incremental = globalMappings.differentiate(
+ delta, removedPaths, successfullyCompiled, allCompiledFiles, allAffectedFiles
+ );
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Differentiate Results:");
+
+ LOG.debug(" Compiled Files:");
+
+ for (final File c : allCompiledFiles) {
+ LOG.debug(" " + c.getAbsolutePath());
+ }
+
+ LOG.debug(" Affected Files:");
+
+ for (final File c : allAffectedFiles) {
+ LOG.debug(" " + c.getAbsolutePath());
+ }
+
+ LOG.debug("End Of Differentiate Results.");
+ }
+
+ if (incremental) {
+ final Set newlyAffectedFiles = new HashSet(allAffectedFiles);
+ newlyAffectedFiles.removeAll(affectedBeforeDif);
+ newlyAffectedFiles.removeAll(allCompiledFiles); // the diff operation may have affected the class already compiled in thic compilation round
+
+ if (!newlyAffectedFiles.isEmpty()) {
+ for (File file : newlyAffectedFiles) {
+ context.markDirty(file);
+ }
+ additionalPassRequired = context.isMake() && chunkContainsAffectedFiles(context, chunk, newlyAffectedFiles);
+ }
+ }
+ else {
+ additionalPassRequired = context.isMake();
+ context.markDirtyRecursively(chunk);
+ }
+ }
+
+ globalMappings.integrate(delta, successfullyCompiled, removedPaths);
+ }
+
+ return additionalPassRequired;
+ }
+ catch(RuntimeException e) {
+ final Throwable cause = e.getCause();
+ if (cause instanceof IOException) {
+ throw ((IOException)cause);
+ }
+ throw e;
+ }
+ }
+
+ // delete all class files that according to mappings correspond to given sources
+ public static void deleteCorrespondingOutputFiles(CompileContext context, Map sources) throws Exception {
+ if (!context.isProjectRebuild() && !sources.isEmpty()) {
+ for (Map.Entry pair : sources.entrySet()) {
+ final File file = pair.getKey();
+ final String srcPath = FileUtil.toSystemIndependentName(file.getPath());
+ final String moduleName = pair.getValue().getName().toLowerCase(Locale.US);
+ final SourceToOutputMapping srcToOut = context.getDataManager().getSourceToOutputMap(moduleName, context.isCompilingTests());
+ final Collection outputs = srcToOut.getState(srcPath);
+ if (outputs != null) {
+ for (String output : outputs) {
+ FileUtil.delete(new File(output));
+ }
+ srcToOut.remove(srcPath);
+ }
+ }
+ }
+ }
+
+ private static boolean chunkContainsAffectedFiles(CompileContext context, ModuleChunk chunk, final Set affected) throws Exception {
+ final Set chunkModules = new HashSet(chunk.getModules());
+ if (!chunkModules.isEmpty()) {
+ for (File file : affected) {
+ final RootDescriptor moduleAndRoot = context.getModuleAndRoot(file);
+ if (moduleAndRoot != null && chunkModules.contains(moduleAndRoot.module)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private static Set getAllAffectedFilesContainer(CompileContext context) {
+ Set allAffectedFiles = ALL_AFFECTED_FILES_KEY.get(context);
+ if (allAffectedFiles == null) {
+ allAffectedFiles = new HashSet();
+ ALL_AFFECTED_FILES_KEY.set(context, allAffectedFiles);
+ }
+ return allAffectedFiles;
+ }
+
+ private static Set getAllCompiledFilesContainer(CompileContext context) {
+ Set allCompiledFiles = ALL_COMPILED_FILES_KEY.get(context);
+ if (allCompiledFiles == null) {
+ allCompiledFiles = new HashSet();
+ ALL_COMPILED_FILES_KEY.set(context, allCompiledFiles);
+ }
+ return allCompiledFiles;
+ }
+
+ private static Set getRemovedPaths(CompileContext context) {
+ final Set removed = Paths.CHUNK_REMOVED_SOURCES_KEY.get(context);
+ return removed != null? removed : Collections.emptySet();
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ProjectLevelBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ProjectLevelBuilder.java
new file mode 100644
index 000000000000..c8296590c3aa
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ProjectLevelBuilder.java
@@ -0,0 +1,20 @@
+package org.jetbrains.jps.incremental;
+
+/**
+ * @author nik
+ */
+public abstract class ProjectLevelBuilder extends Builder {
+ private final ProjectLevelBuilderCategory myCategory;
+
+ protected ProjectLevelBuilder(ProjectLevelBuilderCategory category) {
+ myCategory = category;
+ }
+
+ public abstract void build(CompileContext context);
+
+ public ProjectLevelBuilderCategory getCategory() {
+ return myCategory;
+ }
+
+ public static enum ProjectLevelBuilderCategory { TRANSLATOR, PACKAGER }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java
index 2bb3e3c411ab..7f8be2cb10a2 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java
@@ -29,7 +29,7 @@ import java.util.*;
* @author Eugene Zhuravlev
* Date: 10/25/11
*/
-public class GroovyBuilder extends Builder {
+public class GroovyBuilder extends ModuleLevelBuilder {
public static final String BUILDER_NAME = "groovy";
private final boolean myForStubs;
private final String myBuilderName;
@@ -43,7 +43,7 @@ public class GroovyBuilder extends Builder {
return myBuilderName;
}
- public Builder.ExitCode build(final CompileContext context, ModuleChunk chunk) throws ProjectBuildException {
+ public ModuleLevelBuilder.ExitCode build(final CompileContext context, ModuleChunk chunk) throws ProjectBuildException {
ExitCode exitCode = ExitCode.OK;
final Map toCompile = new HashMap();
try {
@@ -104,12 +104,13 @@ public class GroovyBuilder extends Builder {
// todo CompilerUtil.addLocaleOptions()
//todo different outputs in a chunk
+ //todo xmx
//todo module jdk path
final List cmd = ExternalProcessUtil.buildJavaCommandLine(
SystemProperties.getJavaHome() + "/bin/java",
"org.jetbrains.groovy.compiler.rt.GroovycRunner",
Collections.emptyList(), new ArrayList(cp),
- Arrays.asList("-Xmx384m"/*, "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5858"*/),
+ Arrays.asList("-Xmx384m"/*, "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5239"*/),
Arrays.asList(myForStubs ? "stubs" : "groovyc", tempFile.getPath())
);
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java
index 1be97a81fcf4..2269278c3908 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java
@@ -49,7 +49,7 @@ import java.util.concurrent.ExecutorService;
* @author Eugene Zhuravlev
* Date: 9/21/11
*/
-public class JavaBuilder extends Builder{
+public class JavaBuilder extends ModuleLevelBuilder {
public static final String BUILDER_NAME = "java";
private static final String JAVA_EXTENSION = ".java";
private static final String FORM_EXTENSION = ".form";
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/resourses/ResourcesBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java
similarity index 97%
rename from jps/jps-builders/src/org/jetbrains/jps/incremental/resourses/ResourcesBuilder.java
rename to jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java
index a8b7725d3fd4..a318f8ef4dd7 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/resourses/ResourcesBuilder.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java
@@ -1,4 +1,4 @@
-package org.jetbrains.jps.incremental.resourses;
+package org.jetbrains.jps.incremental.resources;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
@@ -19,7 +19,7 @@ import java.util.Locale;
* @author Eugene Zhuravlev
* Date: 10/6/11
*/
-public class ResourcesBuilder extends Builder{
+public class ResourcesBuilder extends ModuleLevelBuilder {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.resourses.ResourcesBuilder");
public static final String BUILDER_NAME = "resources";
diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/DependencyContext.java b/jps/model/src/org/jetbrains/ether/dependencyView/DependencyContext.java
index c3c796f349de..75756ad6f05e 100644
--- a/jps/model/src/org/jetbrains/ether/dependencyView/DependencyContext.java
+++ b/jps/model/src/org/jetbrains/ether/dependencyView/DependencyContext.java
@@ -172,9 +172,23 @@ class DependencyContext {
public Logger
getLogger(final com.intellij.openapi.diagnostic.Logger log) {
return new Logger() {
@Override
- public void debug(S s) {
+ public void debug(String comment, S s) {
if (log.isDebugEnabled()) {
- log.debug(getValue(s));
+ log.debug(comment + getValue(s));
+ }
+ }
+
+ @Override
+ public void debug(String comment, String t) {
+ if (log.isDebugEnabled()){
+ log.debug(comment + t);
+ }
+ }
+
+ @Override
+ public void debug(String comment, boolean t) {
+ if (log.isDebugEnabled()) {
+ log.debug(comment + Boolean.toString(t));
}
}
};
diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Logger.java b/jps/model/src/org/jetbrains/ether/dependencyView/Logger.java
index 20ffdf19d8f4..a409a4c9ec6f 100644
--- a/jps/model/src/org/jetbrains/ether/dependencyView/Logger.java
+++ b/jps/model/src/org/jetbrains/ether/dependencyView/Logger.java
@@ -23,5 +23,7 @@ package org.jetbrains.ether.dependencyView;
* To change this template use File | Settings | File Templates.
*/
public interface Logger {
- void debug(T t);
+ void debug(String comment, T t);
+ void debug(String comment, String t);
+ void debug(String comment, boolean t);
}
diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java
index 43bde0ea86f3..16846ac8e8f2 100644
--- a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java
+++ b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java
@@ -1,13 +1,12 @@
package org.jetbrains.ether.dependencyView;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.Nullable;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Opcodes;
-import com.intellij.openapi.diagnostic.Logger;
-import org.jetbrains.annotations.*;
-
import java.io.File;
import java.io.IOException;
import java.lang.annotation.ElementType;
@@ -22,7 +21,7 @@ import java.util.*;
* To change this template use File | Settings | File Templates.
*/
public class Mappings {
- private final static Logger LOG = Logger.getInstance ("#org.jetbrains.ether.dependencyView.Mappings");
+ private final static Logger LOG = Logger.getInstance("#org.jetbrains.ether.dependencyView.Mappings");
private final static String CLASS_TO_SUBCLASSES = "classToSubclasses.tab";
private final static String CLASS_TO_CLASS = "classToClass.tab";
@@ -38,12 +37,20 @@ public class Mappings {
private DependencyContext myContext;
private org.jetbrains.ether.dependencyView.Logger myDebugS;
- private void debug(final String s) {
+ private static void debug(final String s) {
LOG.debug(s);
}
- private void debug(final DependencyContext.S s) {
- myDebugS.debug(s);
+ private void debug(final String comment, final DependencyContext.S s) {
+ myDebugS.debug(comment, s);
+ }
+
+ private void debug(final String comment, final String s) {
+ myDebugS.debug(comment, s);
+ }
+
+ private void debug(final String comment, final boolean s) {
+ myDebugS.debug(comment, s);
}
private MultiMaplet myClassToSubclasses;
@@ -534,16 +541,25 @@ public class Mappings {
final Collection affectedUsages,
final Collection dependants,
final boolean usages) {
+ debug("Affecting subclasses of class: ", className);
+
final DependencyContext.S fileName = myClassToSourceFile.get(className);
if (fileName == null) {
+ debug("No source file detected for class ", className);
+ debug("End of affectSubclasses");
return;
}
+ debug("Source file name: ", fileName);
+
if (usages) {
+ debug("Class usages affection requested");
+
final ClassRepr classRepr = reprByName(className);
if (classRepr != null) {
+ debug("Added class usage for ", classRepr.name);
affectedUsages.add(classRepr.createUsage());
}
}
@@ -579,6 +595,7 @@ public class Mappings {
dependents.addAll(deps);
}
+ debug("Affect field usage referenced of class ", p);
affectedUsages
.add(rootUsage instanceof UsageRepr.FieldAssignUsage ? field.createAssignUsage(myContext, p) : field.createUsage(myContext, p));
}
@@ -598,6 +615,8 @@ public class Mappings {
dependents.addAll(deps);
}
+ debug("Affect method usage referenced of class ", p);
+
affectedUsages
.add(rootUsage instanceof UsageRepr.MetaMethodUsage ? method.createMetaUsage(myContext, p) : method.createUsage(myContext, p));
}
@@ -730,32 +749,38 @@ public class Mappings {
// Public branch --- hopeless
if ((member.access & Opcodes.ACC_PUBLIC) > 0) {
- debug("Switched to non-incremental mode");
+ debug("Public access, switching to a non-incremental mode");
return false;
}
// Protected branch
if ((member.access & Opcodes.ACC_PROTECTED) > 0) {
- debug("Softening non-incremental decision: adding all relevant subclasses for a recompilation");
+ debug("Protected access, softening non-incremental decision: adding all relevant subclasses for a recompilation");
+ debug("Root class: ", owner);
final Collection propagated = self.propagateFieldAccess(isField ? member.name : myContext.get(""), owner);
for (DependencyContext.S className : propagated) {
- affectedFiles.add(new File(myContext.getValue(myClassToSourceFile.get(className))));
+ final String fileName = myContext.getValue(myClassToSourceFile.get(className));
+ debug("Adding ", fileName);
+ affectedFiles.add(new File(fileName));
}
}
- debug("Softening non-incremental decision: adding all package classes for a recompilation");
-
final String packageName = ClassRepr.getPackageName(myContext.getValue(isField ? owner : member.name));
+ debug("Softening non-incremental decision: adding all package classes for a recompilation");
+ debug("Package name: ", packageName);
+
// Package-local branch
for (Map.Entry e : myClassToSourceFile.entrySet()) {
final DependencyContext.S className = e.getKey();
final DependencyContext.S fileName = e.getValue();
if (ClassRepr.getPackageName(myContext.getValue(className)).equals(packageName)) {
- affectedFiles.add(new File(myContext.getValue(fileName)));
+ final String f = myContext.getValue(fileName);
+ debug("Adding: ", f);
+ affectedFiles.add(new File(f));
}
}
@@ -767,6 +792,8 @@ public class Mappings {
final Collection filesToCompile,
final Collection compiledFiles,
final Collection affectedFiles) {
+ debug("Begin of Differentiate:");
+
delta.compensateRemovedContent(filesToCompile);
final Util u = new Util(delta);
@@ -798,14 +825,12 @@ public class Mappings {
final Difference.Specifier classDiff = Difference.make(pastClasses, classes);
- debug("Processing changed classes");
-
+ debug("Processing changed classes:");
for (Pair changed : classDiff.changed()) {
final ClassRepr it = changed.first;
final ClassRepr.Diff diff = (ClassRepr.Diff)changed.second;
- debug("Changed: ");
- debug(it.name);
+ debug("Changed: ", it.name);
final int addedModifiers = diff.addedModifiers();
final int removedModifiers = diff.removedModifiers();
@@ -815,24 +840,34 @@ public class Mappings {
final boolean signatureChanged = (diff.base() & Difference.SIGNATURE) > 0;
if (superClassChanged || interfacesChanged || signatureChanged) {
+ debug("Superclass changed: ", superClassChanged);
+ debug("Interfaces changed: ", interfacesChanged);
+ debug("Signature changed ", signatureChanged);
+
final boolean extendsChanged = superClassChanged && !diff.extendsAdded();
final boolean interfacesRemoved = interfacesChanged && !diff.interfaces().removed().isEmpty();
+ debug("Extends changed: ", extendsChanged);
+ debug("Interfaces removed: ", interfacesRemoved);
+
u.affectSubclasses(it.name, affectedFiles, affectedUsages, dependants, extendsChanged || interfacesRemoved || signatureChanged);
}
if ((diff.addedModifiers() & Opcodes.ACC_INTERFACE) > 0 || (diff.removedModifiers() & Opcodes.ACC_INTERFACE) > 0) {
+ debug("Class-to-interface or interface-to-class conversion detected, added class usage to affected usages");
affectedUsages.add(it.createUsage());
}
if (it.isAnnotation() && it.policy == RetentionPolicy.SOURCE) {
debug("Annotation, retention policy = SOURCE => a switch to non-incremental mode requested");
if (!incrementalDecision(it.outerClassName, it, affectedFiles)) {
+ debug("End of Differentiate, returning false");
return false;
}
}
if ((addedModifiers & Opcodes.ACC_PROTECTED) > 0) {
+ debug("Introduction of 'protected' modifier detected, adding class usage + inheritance constraint to affected usages");
final UsageRepr.Usage usage = it.createUsage();
affectedUsages.add(usage);
@@ -840,6 +875,7 @@ public class Mappings {
}
if (diff.packageLocalOn()) {
+ debug("Introduction of 'package local' access detected, adding class usage + package constraint to affected usages");
final UsageRepr.Usage usage = it.createUsage();
affectedUsages.add(usage);
@@ -847,54 +883,64 @@ public class Mappings {
}
if ((addedModifiers & Opcodes.ACC_FINAL) > 0 || (addedModifiers & Opcodes.ACC_PRIVATE) > 0) {
+ debug("Introduction of 'private' or 'final' modifier(s) detected, adding class usage to affected usages");
affectedUsages.add(it.createUsage());
}
- if ((addedModifiers & Opcodes.ACC_ABSTRACT) > 0) {
- affectedUsages.add(UsageRepr.createClassNewUsage(myContext, it.name));
- }
-
- if ((addedModifiers & Opcodes.ACC_STATIC) > 0 ||
- (removedModifiers & Opcodes.ACC_STATIC) > 0 ||
- (addedModifiers & Opcodes.ACC_ABSTRACT) > 0) {
+ if ((addedModifiers & Opcodes.ACC_ABSTRACT) > 0 || (addedModifiers & Opcodes.ACC_STATIC) > 0) {
+ debug("Introduction of 'abstract' or 'static' modifier(s) detected, adding class new usage to affected usages");
affectedUsages.add(UsageRepr.createClassNewUsage(myContext, it.name));
}
if (it.isAnnotation()) {
+ debug("Class is annotation, performing annotation-specific analysis");
+
if (diff.retentionChanged()) {
+ debug("Retention policy change detected, adding class usage to affected usages");
affectedUsages.add(it.createUsage());
}
else {
final Collection removedtargets = diff.targets().removed();
if (removedtargets.contains(ElementType.LOCAL_VARIABLE)) {
- debug("Annotation, removed target contains LOCAL_VARIABLE => a switch to non-incremental mode requested");
+ debug("Removed target contains LOCAL_VARIABLE => a switch to non-incremental mode requested");
if (!incrementalDecision(it.outerClassName, it, affectedFiles)) {
+ debug("End of Differentiate, returning false");
return false;
}
}
if (!removedtargets.isEmpty()) {
+ debug("Removed some annotation targets, adding annotation query");
annotationQuery.add((UsageRepr.AnnotationUsage)UsageRepr
.createAnnotationUsage(myContext, TypeRepr.createClassType(myContext, it.name), null, removedtargets));
}
for (MethodRepr m : diff.methods().added()) {
if (!m.hasValue()) {
+ debug("Added method with no default value: ", m.name);
+ debug("Adding class usage to affected usages");
affectedUsages.add(it.createUsage());
}
}
}
+
+ debug("End of annotation-specific analysis");
}
+ debug("Processing added methods: ");
for (MethodRepr m : diff.methods().added()) {
+ debug("Method: ", m.name);
+
if (it.isAnnotation()) {
+ debug("Class is annotation, skipping method analysis");
continue;
}
if ((it.access & Opcodes.ACC_INTERFACE) > 0 ||
(it.access & Opcodes.ACC_ABSTRACT) > 0 ||
(m.access & Opcodes.ACC_ABSTRACT) > 0) {
+ debug("Class is abstract, or is interface, or added method in abstract => affecting all subclasses");
u.affectSubclasses(it.name, affectedFiles, affectedUsages, dependants, false);
}
@@ -908,6 +954,7 @@ public class Mappings {
}
else {
propagated = u.propagateMethodAccess(m.name, it.name);
+ debug("Conservative case on overriding methods, affecting method usages");
u.affectMethodUsages(m, propagated, m.createMetaUsage(myContext, it.name), affectedUsages, dependants);
}
}
@@ -924,10 +971,12 @@ public class Mappings {
for (MethodRepr mm : lessSpecific) {
if (!mm.equals(m)) {
+ debug("Found less specific method, affecting method usages");
u.affectMethodUsages(mm, propagated, mm.createUsage(myContext, it.name), affectedUsages, dependants);
}
}
+ debug("Processing affected by specificity methods");
for (Pair p : affectedMethods) {
final MethodRepr mm = p.first;
final ClassRepr cc = p.second;
@@ -936,7 +985,12 @@ public class Mappings {
}
else {
+ debug("Method: ", mm.name);
+ debug("Class : ", cc.name);
+
if (overrides.satisfy(mm)) {
+ debug("Current method overrides that found");
+
final Option subtypeOf = u.isSubtypeOf(mm.type, m.type);
if (weakerAccess(mm.access, m.access) ||
@@ -949,11 +1003,15 @@ public class Mappings {
final DependencyContext.S file = myClassToSourceFile.get(cc.name);
if (file != null) {
- affectedFiles.add(new File(myContext.getValue(file)));
+ final String f = myContext.getValue(file);
+ debug("Complex condition is satisfied, affecting file ", f);
+ affectedFiles.add(new File(f));
}
}
}
else {
+ debug("Current method does not override that found");
+
final Collection yetPropagated = self.propagateMethodAccess(mm.name, cc.name);
final Collection deps = myClassToClassDependency.get(cc.name);
@@ -961,6 +1019,7 @@ public class Mappings {
dependants.addAll(deps);
}
+ debug("Affecting method usages for that found");
u.affectMethodUsages(mm, yetPropagated, mm.createUsage(myContext, cc.name), affectedUsages, dependants);
}
}
@@ -977,19 +1036,26 @@ public class Mappings {
final DependencyContext.S outerClass = r.outerClassName;
if (u.methodVisible(outerClass, m)) {
- affectedFiles.add(new File(myContext.getValue(sourceFileName)));
+ final String f = myContext.getValue(sourceFileName);
+ debug("Affecting file due to local overriding: ", f);
+ affectedFiles.add(new File(f));
}
}
}
}
}
}
+ debug("End of added methods processing");
+ debug("Processing removed methods:");
for (MethodRepr m : diff.methods().removed()) {
+ debug("Method ", m.name);
+
final Collection> overridenMethods = u.findOverridenMethods(m, it);
final Collection propagated = u.propagateMethodAccess(m.name, it.name);
if (overridenMethods.size() == 0) {
+ debug("No overridden methods found, affecting method usages");
u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), affectedUsages, dependants);
}
else {
@@ -1006,6 +1072,7 @@ public class Mappings {
}
if (!clear) {
+ debug("No clearly overridden methods found, affecting method usages");
u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), affectedUsages, dependants);
}
}
@@ -1046,21 +1113,31 @@ public class Mappings {
final DependencyContext.S source = myClassToSourceFile.get(p);
if (source != null) {
- affectedFiles.add(new File(myContext.getValue(source)));
+ final String f = myContext.getValue(source);
+ debug(
+ "Removed method is not abstract & is overrides some abstract method which is not then over-overriden in subclass ",
+ p);
+ debug("Affecting subclass source file ", f);
+ affectedFiles.add(new File(f));
}
}
}
}
}
}
+ debug("End of removed methods processing");
+ debug("Processing changed methods:");
for (Pair mr : diff.methods().changed()) {
final MethodRepr m = mr.first;
final MethodRepr.Diff d = (MethodRepr.Diff)mr.second;
final boolean throwsChanged = (d.exceptions().added().size() > 0) || (d.exceptions().changed().size() > 0);
+ debug("Method: ", m.name);
+
if (it.isAnnotation()) {
if (d.defaultRemoved()) {
+ debug("Class is annotation, default value is removed => adding annotation query");
final List l = new LinkedList();
l.add(m.name);
annotationQuery.add((UsageRepr.AnnotationUsage)UsageRepr
@@ -1076,6 +1153,7 @@ public class Mappings {
final Set usages = new HashSet();
if (d.packageLocalOn()) {
+ debug("Method became package-local, affecting method usages outside the package");
u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, dependants);
for (UsageRepr.Usage usage : usages) {
@@ -1089,6 +1167,7 @@ public class Mappings {
if ((d.base() & Difference.TYPE) > 0 || (d.base() & Difference.SIGNATURE) > 0 || throwsChanged) {
if (!affected) {
+ debug("Return type, throws list or signature changed --- affecting method usages");
u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, dependants);
affectedUsages.addAll(usages);
}
@@ -1098,11 +1177,13 @@ public class Mappings {
(d.removedModifiers() & Opcodes.ACC_STATIC) > 0 ||
(d.addedModifiers() & Opcodes.ACC_PRIVATE) > 0) {
if (!affected) {
+ debug("Added static or private specifier or removed static specifier --- affecting method usages");
u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, dependants);
affectedUsages.addAll(usages);
}
if ((d.addedModifiers() & Opcodes.ACC_STATIC) > 0) {
+ debug("Added static specifier --- affecting subclasses");
u.affectSubclasses(it.name, affectedFiles, affectedUsages, dependants, false);
}
}
@@ -1110,11 +1191,13 @@ public class Mappings {
if ((d.addedModifiers() & Opcodes.ACC_FINAL) > 0 ||
(d.addedModifiers() & Opcodes.ACC_PUBLIC) > 0 ||
(d.addedModifiers() & Opcodes.ACC_ABSTRACT) > 0) {
+ debug("Added final, public or abstract specifier --- affecting subclasses");
u.affectSubclasses(it.name, affectedFiles, affectedUsages, dependants, false);
}
if ((d.addedModifiers() & Opcodes.ACC_PROTECTED) > 0 && !((d.removedModifiers() & Opcodes.ACC_PRIVATE) > 0)) {
if (!constrained) {
+ debug("Added public or package-local method became protected --- affect method usages with protected constraint");
if (!affected) {
u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, dependants);
affectedUsages.addAll(usages);
@@ -1129,10 +1212,14 @@ public class Mappings {
}
}
}
+ debug("End of changed methods processing");
final int mask = Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;
+ debug("Processing added fields");
for (FieldRepr f : diff.fields().added()) {
+ debug("Field: ", f.name);
+
final boolean fPrivate = (f.access & Opcodes.ACC_PRIVATE) > 0;
final boolean fProtected = (f.access & Opcodes.ACC_PROTECTED) > 0;
final boolean fPublic = (f.access & Opcodes.ACC_PUBLIC) > 0;
@@ -1141,32 +1228,34 @@ public class Mappings {
if (!fPrivate) {
final Collection subClasses = getAllSubclasses(it.name);
- if (subClasses != null) {
- for (final DependencyContext.S subClass : subClasses) {
- final ClassRepr r = u.reprByName(subClass);
- final DependencyContext.S sourceFileName = myClassToSourceFile.get(subClass);
+ for (final DependencyContext.S subClass : subClasses) {
+ final ClassRepr r = u.reprByName(subClass);
+ final DependencyContext.S sourceFileName = myClassToSourceFile.get(subClass);
- if (r != null && sourceFileName != null) {
- if (r.isLocal) {
+ if (r != null && sourceFileName != null) {
+ if (r.isLocal) {
+ debug("Affecting local subclass (introduced field can potentially hide surrounding method parameters/local variables): ",
+ sourceFileName);
+ affectedFiles.add(new File(myContext.getValue(sourceFileName)));
+ }
+ else {
+ final DependencyContext.S outerClass = r.outerClassName;
+
+ if (!empty(outerClass) && u.fieldVisible(outerClass, f)) {
+ debug("Affecting inner subclass (introduced field can potentially hide surrounding class fields): ", sourceFileName);
affectedFiles.add(new File(myContext.getValue(sourceFileName)));
}
- else {
- final DependencyContext.S outerClass = r.outerClassName;
-
- if (!empty(outerClass) && u.fieldVisible(outerClass, f)) {
- affectedFiles.add(new File(myContext.getValue(sourceFileName)));
- }
- }
}
+ }
- final Collection propagated = u.propagateFieldAccess(f.name, subClass);
- u.affectFieldUsages(f, propagated, f.createUsage(myContext, subClass), affectedUsages, dependants);
+ debug("Affecting field usages referenced from subclass ", subClass);
+ final Collection propagated = u.propagateFieldAccess(f.name, subClass);
+ u.affectFieldUsages(f, propagated, f.createUsage(myContext, subClass), affectedUsages, dependants);
- final Collection deps = myClassToClassDependency.get(subClass);
+ final Collection deps = myClassToClassDependency.get(subClass);
- if (deps != null) {
- dependants.addAll(deps);
- }
+ if (deps != null) {
+ dependants.addAll(deps);
}
}
}
@@ -1186,6 +1275,7 @@ public class Mappings {
final Collection propagated = o.propagateFieldAccess(ff.name, cc.name);
final Set localUsages = new HashSet();
+ debug("Affecting usages of overridden field in class ", cc.name);
u.affectFieldUsages(ff, propagated, ff.createUsage(myContext, cc.name), localUsages, dependants);
if (fPrivate || (fPublic && (ffPublic || ffPLocal)) || (fProtected && ffProtected) || (fPLocal && ffPLocal)) {
@@ -1214,16 +1304,16 @@ public class Mappings {
}
}
}
+ debug("End of added fields processing");
- debug("Processing removed fields");
-
+ debug("Processing removed fields:");
for (FieldRepr f : diff.fields().removed()) {
- debug("Field ");
- debug(f.name);
+ debug("Field: ", it.name);
if ((f.access & Opcodes.ACC_PRIVATE) == 0 && (f.access & mask) == mask && f.hasValue()) {
debug("Field had value and was (non-private) final static => a switch to non-incremental mode requested");
if (!incrementalDecision(it.name, f, affectedFiles)) {
+ debug("End of Differentiate, returning false");
return false;
}
}
@@ -1231,20 +1321,20 @@ public class Mappings {
final Collection propagated = u.propagateFieldAccess(f.name, it.name);
u.affectFieldUsages(f, propagated, f.createUsage(myContext, it.name), affectedUsages, dependants);
}
+ debug("End of removed fields processing");
- debug("Processing changed fields");
-
+ debug("Processing changed fields:");
for (Pair f : diff.fields().changed()) {
final Difference d = f.second;
final FieldRepr field = f.first;
- debug("Field ");
- debug(field.name);
+ debug("Field: ", it.name);
if ((field.access & Opcodes.ACC_PRIVATE) == 0 && (field.access & mask) == mask) {
if ((d.base() & Difference.ACCESS) > 0 || (d.base() & Difference.VALUE) > 0) {
debug("Inline field changed it's access or value => a switch to non-incremental mode requested");
- if (!incrementalDecision(it.name, field, affectedFiles)){
+ if (!incrementalDecision(it.name, field, affectedFiles)) {
+ debug("End of Differentiate, returning false");
return false;
}
}
@@ -1254,6 +1344,7 @@ public class Mappings {
final Collection propagated = u.propagateFieldAccess(field.name, it.name);
if ((d.base() & Difference.TYPE) > 0 || (d.base() & Difference.SIGNATURE) > 0) {
+ debug("Type or signature changed --- affecting field usages");
u.affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), affectedUsages, dependants);
}
else if ((d.base() & Difference.ACCESS) > 0) {
@@ -1261,7 +1352,7 @@ public class Mappings {
(d.removedModifiers() & Opcodes.ACC_STATIC) > 0 ||
(d.addedModifiers() & Opcodes.ACC_PRIVATE) > 0 ||
(d.addedModifiers() & Opcodes.ACC_VOLATILE) > 0) {
-
+ debug("Added/removed static modifier or added private/volatile modifier --- affecting field usages");
u.affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), affectedUsages, dependants);
}
else {
@@ -1269,12 +1360,14 @@ public class Mappings {
final Set usages = new HashSet();
if ((d.addedModifiers() & Opcodes.ACC_FINAL) > 0) {
+ debug("Added final modifier --- affecting field assign usages");
u.affectFieldUsages(field, propagated, field.createAssignUsage(myContext, it.name), usages, dependants);
affectedUsages.addAll(usages);
affected = true;
}
if ((d.removedModifiers() & Opcodes.ACC_PUBLIC) > 0) {
+ debug("Removed public modifier, affecting field usages with appropriate constraint");
if (!affected) {
u.affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), usages, dependants);
affectedUsages.addAll(usages);
@@ -1293,12 +1386,18 @@ public class Mappings {
}
}
}
+ debug("End of changed fields processing");
}
+ debug("End of changed classes processing");
+ debug("Processing removed classes:");
for (ClassRepr c : classDiff.removed()) {
+ debug("Adding usages of class ", c.name);
affectedUsages.add(c.createUsage());
}
+ debug("End of removed classes processing.");
+ debug("Processing added classes:");
for (ClassRepr c : classDiff.added()) {
final Collection depClasses = myClassToClassDependency.get(c.name);
@@ -1307,12 +1406,16 @@ public class Mappings {
final DependencyContext.S fName = myClassToSourceFile.get(depClass);
if (fName != null) {
- affectedFiles.add(new File(myContext.getValue(fName)));
+ final String f = myContext.getValue(fName);
+ debug("Adding dependent file ", f);
+ affectedFiles.add(new File(f));
}
}
}
}
+ debug("End of added classes processing.");
+ debug("Checking dependent files:");
if (dependants != null) {
final Set dependentFiles = new HashSet();
@@ -1332,6 +1435,8 @@ public class Mappings {
continue filewise;
}
+ debug("Dependent file: ", depFile);
+
final Collection depClusters = mySourceFileToUsages.get(depFile);
for (UsageRepr.Cluster depCluster : depClusters) {
@@ -1347,6 +1452,7 @@ public class Mappings {
final Util.UsageConstraint constraint = usageConstraints.get(usage);
if (constraint == null) {
+ debug("Added file with no constraints");
affectedFiles.add(theFile);
continue filewise;
}
@@ -1354,6 +1460,7 @@ public class Mappings {
final Set residenceClasses = depCluster.getResidence(usage);
for (DependencyContext.S residentName : residenceClasses) {
if (constraint.checkResidence(residentName)) {
+ debug("Added file with satisfied constraint");
affectedFiles.add(theFile);
continue filewise;
}
@@ -1369,6 +1476,7 @@ public class Mappings {
for (UsageRepr.Usage usage : annotationUsages) {
for (UsageRepr.AnnotationUsage query : annotationQuery) {
if (query.satisfies(usage)) {
+ debug("Added file due to annotation query");
affectedFiles.add(theFile);
continue filewise;
}
@@ -1381,6 +1489,13 @@ public class Mappings {
}
}
+ if (removed != null) {
+ for (String r : removed) {
+ affectedFiles.remove(new File(r));
+ }
+ }
+
+ debug("End of Differentiate, returning true");
return true;
}
@@ -1425,7 +1540,6 @@ public class Mappings {
}
}
-
myClassToSubclasses.putAll(delta.myClassToSubclasses);
mySourceFileToClasses.putAll(delta.mySourceFileToClasses);
mySourceFileToUsages.putAll(delta.mySourceFileToUsages);
diff --git a/lib/netty-3.2.5.Final.jar b/lib/netty-3.2.5.Final.jar
deleted file mode 100644
index f3b79fcbaa75..000000000000
Binary files a/lib/netty-3.2.5.Final.jar and /dev/null differ
diff --git a/lib/netty-3.3.0.Final.jar b/lib/netty-3.3.0.Final.jar
new file mode 100644
index 000000000000..7929a276f775
Binary files /dev/null and b/lib/netty-3.3.0.Final.jar differ
diff --git a/lib/required_for_dist.txt b/lib/required_for_dist.txt
index 6e5ed206d18f..5a2fd8ed757e 100644
--- a/lib/required_for_dist.txt
+++ b/lib/required_for_dist.txt
@@ -44,5 +44,5 @@ xmlrpc-2.0.jar
xpp3-1.1.4-min.jar
xstream.jar
swingx-core-1.6.2.jar
-netty-3.2.5.Final.jar
+netty-3.3.0.Final.jar
protobuf-2.3.0.jar
diff --git a/lib/src/netty-3.2.5.Final-sources.jar b/lib/src/netty-3.2.5.Final-sources.jar
deleted file mode 100644
index cb6cb9bf537e..000000000000
Binary files a/lib/src/netty-3.2.5.Final-sources.jar and /dev/null differ
diff --git a/lib/src/netty-3.3.0.Final-sources.jar b/lib/src/netty-3.3.0.Final-sources.jar
new file mode 100644
index 000000000000..40d5a4efc500
Binary files /dev/null and b/lib/src/netty-3.3.0.Final-sources.jar differ
diff --git a/platform/lang-api/src/com/intellij/execution/ui/actions/BaseViewAction.java b/platform/lang-api/src/com/intellij/execution/ui/actions/BaseViewAction.java
index 869491c8a685..06c8cd55a7d7 100644
--- a/platform/lang-api/src/com/intellij/execution/ui/actions/BaseViewAction.java
+++ b/platform/lang-api/src/com/intellij/execution/ui/actions/BaseViewAction.java
@@ -17,7 +17,6 @@
package com.intellij.execution.ui.actions;
import com.intellij.execution.ui.layout.Grid;
-import com.intellij.execution.ui.layout.GridCell;
import com.intellij.execution.ui.layout.Tab;
import com.intellij.execution.ui.layout.ViewContext;
import com.intellij.openapi.actionSystem.AnActionEvent;
@@ -74,11 +73,6 @@ public abstract class BaseViewAction extends DumbAwareAction {
return e.getData(ViewContext.CONTENT_KEY);
}
- protected static boolean isDetached(ViewContext context, Content content) {
- final GridCell cell = context.findCellFor(content);
- return cell != null && cell.isDetached();
- }
-
@Nullable
protected static Tab getTabFor(final ViewContext context, final Content[] content) {
Grid grid = context.findGridFor(content[0]);
diff --git a/platform/lang-api/src/com/intellij/execution/ui/layout/CellTransform.java b/platform/lang-api/src/com/intellij/execution/ui/layout/CellTransform.java
index e37c46a19083..b9c7b21da197 100644
--- a/platform/lang-api/src/com/intellij/execution/ui/layout/CellTransform.java
+++ b/platform/lang-api/src/com/intellij/execution/ui/layout/CellTransform.java
@@ -72,12 +72,6 @@ public interface CellTransform {
interface Facade {
void minimize(Content content, Restore restore);
-
- void moveToTab(final Content content);
-
- void moveToGrid(final Content content);
-
- Restore detach(final Content[] content);
}
}
diff --git a/platform/lang-api/src/com/intellij/execution/ui/layout/GridCell.java b/platform/lang-api/src/com/intellij/execution/ui/layout/GridCell.java
index 2201bd8d6699..ebcbdd6a2a51 100644
--- a/platform/lang-api/src/com/intellij/execution/ui/layout/GridCell.java
+++ b/platform/lang-api/src/com/intellij/execution/ui/layout/GridCell.java
@@ -16,17 +16,10 @@
package com.intellij.execution.ui.layout;
-import com.intellij.openapi.util.ActionCallback;
import com.intellij.ui.content.Content;
public interface GridCell {
- boolean isDetached();
-
int getContentCount();
- void attach();
-
void minimize(final Content content);
-
- ActionCallback detach();
}
\ No newline at end of file
diff --git a/platform/lang-api/src/com/intellij/execution/ui/layout/Tab.java b/platform/lang-api/src/com/intellij/execution/ui/layout/Tab.java
index c208e3c49b1f..686162a17391 100644
--- a/platform/lang-api/src/com/intellij/execution/ui/layout/Tab.java
+++ b/platform/lang-api/src/com/intellij/execution/ui/layout/Tab.java
@@ -22,6 +22,7 @@ public interface Tab {
void setDetached(final PlaceInGrid placeInGrid, final boolean detached);
int getIndex();
+ int getDefaultIndex();
boolean isDetached(final PlaceInGrid placeInGrid);
}
\ No newline at end of file
diff --git a/platform/lang-api/src/com/intellij/execution/ui/layout/View.java b/platform/lang-api/src/com/intellij/execution/ui/layout/View.java
index 761a1b502250..c81532e8105f 100644
--- a/platform/lang-api/src/com/intellij/execution/ui/layout/View.java
+++ b/platform/lang-api/src/com/intellij/execution/ui/layout/View.java
@@ -32,4 +32,8 @@ public interface View {
void assignTab(Tab tab);
void setTabIndex(int tabIndex);
+
+ int getWindow();
+
+ void setWindow(int windowNumber);
}
\ No newline at end of file
diff --git a/platform/lang-api/src/com/intellij/lang/cacheBuilder/DefaultWordsScanner.java b/platform/lang-api/src/com/intellij/lang/cacheBuilder/DefaultWordsScanner.java
index 3c87dda6701c..8f777e4864c9 100644
--- a/platform/lang-api/src/com/intellij/lang/cacheBuilder/DefaultWordsScanner.java
+++ b/platform/lang-api/src/com/intellij/lang/cacheBuilder/DefaultWordsScanner.java
@@ -51,29 +51,29 @@ public class DefaultWordsScanner implements WordsScanner {
public void processWords(CharSequence fileText, Processor processor) {
myLexer.start(fileText);
- WordOccurrence occurence = null; // shared occurence
+ WordOccurrence occurrence = null; // shared occurrence
while (myLexer.getTokenType() != null) {
final IElementType type = myLexer.getTokenType();
if (myIdentifierTokenSet.contains(type)) {
- if (occurence == null) {
- occurence = new WordOccurrence(fileText, myLexer.getTokenStart(), myLexer.getTokenEnd(), WordOccurrence.Kind.CODE);
+ if (occurrence == null) {
+ occurrence = new WordOccurrence(fileText, myLexer.getTokenStart(), myLexer.getTokenEnd(), WordOccurrence.Kind.CODE);
}
else {
- occurence.init(fileText, myLexer.getTokenStart(), myLexer.getTokenEnd(), WordOccurrence.Kind.CODE);
+ occurrence.init(fileText, myLexer.getTokenStart(), myLexer.getTokenEnd(), WordOccurrence.Kind.CODE);
}
- if (!processor.process(occurence)) return;
+ if (!processor.process(occurrence)) return;
}
else if (myCommentTokenSet.contains(type)) {
- if (!stripWords(processor, fileText,myLexer.getTokenStart(),myLexer.getTokenEnd(), WordOccurrence.Kind.COMMENTS,occurence, false)) return;
+ if (!stripWords(processor, fileText,myLexer.getTokenStart(),myLexer.getTokenEnd(), WordOccurrence.Kind.COMMENTS,occurrence, false)) return;
}
else if (myLiteralTokenSet.contains(type)) {
- if (!stripWords(processor, fileText, myLexer.getTokenStart(),myLexer.getTokenEnd(),WordOccurrence.Kind.LITERALS,occurence, myMayHaveFileRefsInLiterals)) return;
+ if (!stripWords(processor, fileText, myLexer.getTokenStart(),myLexer.getTokenEnd(),WordOccurrence.Kind.LITERALS,occurrence, myMayHaveFileRefsInLiterals)) return;
}
else {
// process all word-like characters as words
// Plugin writers may have (Maximka in JavaScript especially) some keyword token types omitted from the identifierTokenSet
- if (!stripWords(processor, fileText, myLexer.getTokenStart(), myLexer.getTokenEnd(), WordOccurrence.Kind.CODE, occurence, false)) return;
+ if (!stripWords(processor, fileText, myLexer.getTokenStart(), myLexer.getTokenEnd(), WordOccurrence.Kind.CODE, occurrence, false)) return;
}
myLexer.advance();
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java
index f4f219c30e12..dbe5d13a980b 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java
@@ -268,10 +268,14 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
myScrollPane.setViewportBorder(JBScrollPane.createIndentBorder());
final DefaultActionGroup actions = new DefaultActionGroup();
- actions.add(new BackAction());
- actions.add(new ForwardAction());
+ final BackAction back = new BackAction();
+ final ForwardAction forward = new ForwardAction();
+ actions.add(back);
+ actions.add(forward);
actions.add(myExternalDocAction = new ExternalDocAction());
-
+ back.registerCustomShortcutSet(CustomShortcutSet.fromString("LEFT"), this);
+ forward.registerCustomShortcutSet(CustomShortcutSet.fromString("RIGHT"), this);
+ myExternalDocAction.registerCustomShortcutSet(CustomShortcutSet.fromString("UP"), this);
if (additionalActions != null) {
for (final AnAction action : additionalActions) {
actions.add(action);
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java
index c78850c2ca40..d2672ff88fc1 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java
@@ -35,6 +35,7 @@ import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
+import com.intellij.ui.docking.DockManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -76,7 +77,7 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom
public RunContentManager getContentManager() {
if (myContentManager == null) {
- myContentManager = new RunContentManagerImpl(myProject);
+ myContentManager = new RunContentManagerImpl(myProject, DockManager.getInstance(myProject));
Disposer.register(myProject, myContentManager);
}
return myContentManager;
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java
index 7a42e42487ac..0a6f6b508feb 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java
@@ -23,6 +23,7 @@ import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.GenericProgramRunner;
+import com.intellij.execution.ui.layout.impl.DockableGridContainerFactory;
import com.intellij.ide.DataManager;
import com.intellij.ide.impl.ContentManagerWatcher;
import com.intellij.openapi.Disposable;
@@ -47,6 +48,7 @@ import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.openapi.wm.ex.ToolWindowManagerAdapter;
import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
import com.intellij.ui.content.*;
+import com.intellij.ui.docking.DockManager;
import com.intellij.util.concurrency.Semaphore;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
@@ -65,13 +67,17 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
private static final Key DESCRIPTOR_KEY = new Key("Descriptor");
private final Project myProject;
+ private DockableGridContainerFactory myContentFactory;
private final Map myToolwindowIdToContentManagerMap = new HashMap();
private final Map myListeners = new HashMap();
private final LinkedList myToolwindowIdZbuffer = new LinkedList();
- public RunContentManagerImpl(Project project) {
+ public RunContentManagerImpl(Project project, DockManager dockManager) {
myProject = project;
+ myContentFactory = new DockableGridContainerFactory();
+ dockManager.register(DockableGridContainerFactory.TYPE, myContentFactory);
+ Disposer.register(myProject, myContentFactory);
}
public void init() {
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/AttachCellAction.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/AttachCellAction.java
deleted file mode 100644
index 062347e926d7..000000000000
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/AttachCellAction.java
+++ /dev/null
@@ -1,51 +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.execution.ui.layout.actions;
-
-import com.intellij.execution.ui.actions.BaseViewAction;
-import com.intellij.execution.ui.layout.Grid;
-import com.intellij.execution.ui.layout.GridCell;
-import com.intellij.execution.ui.layout.ViewContext;
-import com.intellij.idea.ActionsBundle;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.ui.content.Content;
-
-public class AttachCellAction extends BaseViewAction {
-
- protected void update(final AnActionEvent e, final ViewContext context, final Content[] content) {
- if (content.length == 0 || !isDetached(context, content[0])) {
- setEnabled(e, false);
- return;
- }
-
- Grid grid = context.findGridFor(content[0]);
-
- GridCell cell = grid.getCellFor(content[0]);
- if (ViewContext.CELL_TOOLBAR_PLACE.equals(e.getPlace()) && content.length == 1) {
- setEnabled(e, cell.getContentCount() == 1);
- } else {
- setEnabled(e, true);
- if (cell.getContentCount() > 1) {
- e.getPresentation().setText(ActionsBundle.message("action.Runner.AttachCells.text", cell.getContentCount()));
- }
- }
- }
-
- protected void actionPerformed(final AnActionEvent e, final ViewContext context, final Content[] content) {
- context.findCellFor(content[0]).attach();
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/CloseViewAction.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/CloseViewAction.java
index 98bfe91eecfe..cb18ab9d5840 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/CloseViewAction.java
+++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/CloseViewAction.java
@@ -19,11 +19,19 @@ package com.intellij.execution.ui.layout.actions;
import com.intellij.execution.ui.actions.BaseViewAction;
import com.intellij.execution.ui.layout.ViewContext;
import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.util.IconLoader;
import com.intellij.ui.content.Content;
+import javax.swing.*;
+
public class CloseViewAction extends BaseViewAction {
+ private static final Icon ICON = IconLoader.getIcon("/actions/closeNew.png");
+ private static final Icon HOVERED_ICON = IconLoader.getIcon("/actions/closeNewHovered.png");
+
protected void update(final AnActionEvent e, final ViewContext context, final Content[] content) {
setEnabled(e, isEnabled(context, content, e.getPlace()));
+ e.getPresentation().setIcon(ICON);
+ e.getPresentation().setHoveredIcon(HOVERED_ICON);
}
protected void actionPerformed(final AnActionEvent e, final ViewContext context, final Content[] content) {
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/DetachCellAction.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/DetachCellAction.java
deleted file mode 100644
index 31215923d4db..000000000000
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/DetachCellAction.java
+++ /dev/null
@@ -1,59 +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.execution.ui.layout.actions;
-
-import com.intellij.execution.ui.actions.BaseViewAction;
-import com.intellij.execution.ui.layout.Grid;
-import com.intellij.execution.ui.layout.GridCell;
-import com.intellij.execution.ui.layout.ViewContext;
-import com.intellij.idea.ActionsBundle;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.ui.content.Content;
-
-public class DetachCellAction extends BaseViewAction {
- protected void update(final AnActionEvent e, final ViewContext context, final Content[] content) {
- if (content.length == 0 || isDetached(context, content[0])) {
- setEnabled(e, false);
- return;
- }
-
- Grid grid = context.findGridFor(content[0]);
- if (grid == null) {
- setEnabled(e, false);
- return;
- }
-
- if (ViewContext.TAB_TOOLBAR_PLACE.equals(e.getPlace()) || (ViewContext.TAB_POPUP_PLACE.equals(e.getPlace()))) {
- setEnabled(e, grid.getContents().size() == 1);
- }
- else {
- GridCell cell = grid.getCellFor(content[0]);
- if (ViewContext.CELL_TOOLBAR_PLACE.equals(e.getPlace()) && content.length == 1) {
- setEnabled(e, cell.getContentCount() == 1);
- } else {
- setEnabled(e, true);
- if (cell.getContentCount() > 1) {
- e.getPresentation().setText(ActionsBundle.message("action.Runner.DetachCells.text", cell.getContentCount()));
- }
- }
- }
- }
-
- protected void actionPerformed(final AnActionEvent e, final ViewContext context, final Content[] content) {
- context.findCellFor(content[0]).detach();
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MinimizeViewAction.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MinimizeViewAction.java
index 79982fb99f8b..fc16369ed688 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MinimizeViewAction.java
+++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MinimizeViewAction.java
@@ -39,19 +39,15 @@ public class MinimizeViewAction extends BaseViewAction {
return false;
}
- if (isDetached(context, content[0])) {
- return false;
- }
-
if (ViewContext.TAB_TOOLBAR_PLACE.equals(place) || ViewContext.TAB_POPUP_PLACE.equals(place)) {
- return false;
- }
- else {
Tab tab = getTabFor(context, content);
if (tab == null) {
return false;
}
- return tab.isDefault();
+ return !tab.isDefault();
+ }
+ else {
+ return getTabFor(context, content) != null;
}
}
}
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MoveToGridAction.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MoveToGridAction.java
deleted file mode 100644
index f66f5014d878..000000000000
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MoveToGridAction.java
+++ /dev/null
@@ -1,50 +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.execution.ui.layout.actions;
-
-import com.intellij.execution.ui.actions.BaseViewAction;
-import com.intellij.execution.ui.layout.Grid;
-import com.intellij.execution.ui.layout.Tab;
-import com.intellij.execution.ui.layout.ViewContext;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.ui.content.Content;
-
-public class MoveToGridAction extends BaseViewAction {
- protected void update(final AnActionEvent e, final ViewContext context, final Content[] content) {
- if (!context.isMoveToGridActionEnabled() || content.length != 1) {
- setEnabled(e, false);
- return;
- }
-
- if (isDetached(context, content[0])) {
- setEnabled(e, false);
- return;
- }
-
- Grid grid = context.findGridFor(content[0]);
- if (grid == null) {
- setEnabled(e, false);
- return;
- }
- Tab tab = context.getTabFor(grid);
- setEnabled(e, tab != null && !tab.isDefault() && grid.getContents().size() == 1);
- }
-
- protected void actionPerformed(final AnActionEvent e, final ViewContext context, final Content[] content) {
- context.getCellTransform().moveToGrid(content[0]);
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MoveToTabAction.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MoveToTabAction.java
deleted file mode 100644
index bf23cb10c3f0..000000000000
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MoveToTabAction.java
+++ /dev/null
@@ -1,56 +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.execution.ui.layout.actions;
-
-import com.intellij.execution.ui.actions.BaseViewAction;
-import com.intellij.execution.ui.layout.Grid;
-import com.intellij.execution.ui.layout.Tab;
-import com.intellij.execution.ui.layout.ViewContext;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.ui.content.Content;
-
-public class MoveToTabAction extends BaseViewAction {
- protected void update(final AnActionEvent e, final ViewContext context, final Content[] content) {
- if (!context.isMoveToGridActionEnabled() || content.length != 1) {
- setEnabled(e, false);
- return;
- }
- if (isDetached(context, content[0])) {
- setEnabled(e, false);
- return;
- }
-
- Grid grid = context.findGridFor(content[0]);
- if (grid == null) {
- setEnabled(e, false);
- return;
- }
-
-
- Tab tab = context.getTabFor(grid);
-
- if (ViewContext.TAB_TOOLBAR_PLACE.equals(e.getPlace())) {
- setEnabled(e, false);
- } else {
- setEnabled(e, tab != null && tab.isDefault());
- }
- }
-
- protected void actionPerformed(final AnActionEvent e, final ViewContext context, final Content[] content) {
- context.getCellTransform().moveToTab(content[0]);
- }
-}
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/AbstractTab.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/AbstractTab.java
index 282ce022dc1a..fb2f1293e2a9 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/AbstractTab.java
+++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/AbstractTab.java
@@ -21,6 +21,7 @@ import javax.swing.*;
abstract class AbstractTab {
int myIndex;
+ int myDefaultIndex = -1;
String myDisplayName;
Icon myIcon;
@@ -38,6 +39,7 @@ abstract class AbstractTab {
void copyFrom(final AbstractTab from) {
myIndex = from.myIndex;
+ myDefaultIndex = from.myDefaultIndex;
myDisplayName = from.myDisplayName;
myIcon = from.myIcon;
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/DockableGridContainerFactory.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/DockableGridContainerFactory.java
new file mode 100644
index 000000000000..4e9c694291d9
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/DockableGridContainerFactory.java
@@ -0,0 +1,36 @@
+/*
+ * 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.execution.ui.layout.impl;
+
+import com.intellij.ui.docking.DockContainer;
+import com.intellij.ui.docking.DockContainerFactory;
+import com.intellij.ui.docking.DockableContent;
+
+/**
+ * @author Dennis.Ushakov
+ */
+public class DockableGridContainerFactory implements DockContainerFactory {
+ public static final String TYPE = "runner-grid";
+
+ @Override
+ public DockContainer createContainer(DockableContent content) {
+ final RunnerContentUi.DockableGrid dockableGrid = (RunnerContentUi.DockableGrid)content;
+ return new RunnerContentUi(dockableGrid.getRunnerUi(), dockableGrid.getOriginalRunnerUi(), dockableGrid.getWindow());
+ }
+
+ @Override
+ public void dispose() {}
+}
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java
index f479bc7860e9..53df6f2e8ea8 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java
@@ -18,18 +18,16 @@ package com.intellij.execution.ui.layout.impl;
import com.intellij.execution.ui.layout.*;
import com.intellij.execution.ui.layout.actions.MinimizeViewAction;
-import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.DataProvider;
-import com.intellij.openapi.ui.popup.ComponentPopupBuilder;
import com.intellij.openapi.ui.popup.JBPopup;
-import com.intellij.openapi.ui.popup.JBPopupFactory;
-import com.intellij.openapi.util.*;
-import com.intellij.openapi.wm.IdeFrame;
-import com.intellij.openapi.wm.WindowManager;
+import com.intellij.openapi.util.ActionCallback;
+import com.intellij.openapi.util.DimensionService;
+import com.intellij.openapi.util.MutualMap;
import com.intellij.ui.components.panels.NonOpaquePanel;
-import com.intellij.ui.components.panels.Wrapper;
import com.intellij.ui.content.Content;
+import com.intellij.ui.docking.DockContainer;
+import com.intellij.ui.docking.DockManager;
import com.intellij.ui.switcher.SwitchTarget;
import com.intellij.ui.tabs.JBTabs;
import com.intellij.ui.tabs.TabInfo;
@@ -43,15 +41,14 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
+import java.util.List;
import java.util.Set;
-public class GridCellImpl implements GridCell, Disposable {
-
+public class GridCellImpl implements GridCell {
private final GridImpl myContainer;
private final MutualMap myContents = new MutualMap(true);
@@ -62,16 +59,12 @@ public class GridCellImpl implements GridCell, Disposable {
private final PlaceInGrid myPlaceInGrid;
private final ViewContextEx myContext;
- private CellTransform.Restore.List myRestoreFromDetach;
private JBPopup myPopup;
- private boolean myDisposed;
public GridCellImpl(ViewContextEx context, @NotNull GridImpl container, GridImpl.Placeholder placeholder, PlaceInGrid placeInGrid) {
myContext = context;
myContainer = container;
- Disposer.register(container, this);
-
myPlaceInGrid = placeInGrid;
myPlaceholder = placeholder;
myTabs = new JBTabsImpl(myContext.getProject(), myContext.getActionManager(), myContext.getFocusManager(), container).setDataProvider(new DataProvider() {
@@ -97,23 +90,17 @@ public class GridCellImpl implements GridCell, Disposable {
}
}).setSideComponentVertical(!context.getLayoutSettings().isToolbarHorizontal())
.setStealthTabMode(true)
- .setFocusCycle(false).setPaintFocus(true).setProvideSwitchTargets(false);
+ .setFocusCycle(false).setPaintFocus(true).setProvideSwitchTargets(false).setTabDraggingEnabled(true);
myTabs.addTabMouseListener(new MouseAdapter() {
public void mousePressed(final MouseEvent e) {
if (UIUtil.isCloseClick(e)) {
- if (isDetached()) {
- myPopup.cancel();
- myPopup = null;
- }
- else {
minimize(e);
- }
}
}
});
rebuildPopupGroup();
- myTabs.addListener(new TabsListener() {
+ myTabs.addListener(new TabsListener.Adapter() {
public void beforeSelectionChanged(TabInfo oldSelection, TabInfo newSelection) {
if (oldSelection != null && myContext.isStateBeingRestored()) {
@@ -181,7 +168,7 @@ public class GridCellImpl implements GridCell, Disposable {
}
}
else {
- if (myPlaceholder.isNull() && !isDetached()) {
+ if (myPlaceholder.isNull()) {
myPlaceholder.setContent(myTabs.getComponent());
}
@@ -211,7 +198,7 @@ public class GridCellImpl implements GridCell, Disposable {
ActionGroup group = (ActionGroup)myContext.getActionManager().getAction(RunnerContentUi.VIEW_TOOLBAR);
tabInfo.setTabLabelActions(group, ViewContext.CELL_TOOLBAR_PLACE);
-
+ tabInfo.setDragOutDelegate(((RunnerContentUi)myContext).myDragOutDelegate);
return tabInfo;
}
@@ -248,7 +235,7 @@ public class GridCellImpl implements GridCell, Disposable {
return myMinimizedContents.contains(content);
}
- public java.util.List getTargets(boolean onlyVisible) {
+ public List getTargets(boolean onlyVisible) {
if (myTabs.getPresentation().isHideTabs()) return new ArrayList();
return myTabs.getTargets(onlyVisible, false);
@@ -287,7 +274,7 @@ public class GridCellImpl implements GridCell, Disposable {
}
@Nullable
- private TabInfo getTabFor(Content content) {
+ TabInfo getTabFor(Content content) {
return myContents.getValue(content);
}
@@ -306,14 +293,21 @@ public class GridCellImpl implements GridCell, Disposable {
restoreProportions();
Content[] contents = getContents();
+ int window = 0;
for (Content each : contents) {
- if (myContainer.getStateFor(each).isMinimizedInGrid()) {
+ final View view = myContainer.getStateFor(each);
+ if (view.isMinimizedInGrid()) {
minimize(each);
}
+ window = view.getWindow();
}
-
- if (!isRestoringFromDetach() && myContainer.getTab().isDetached(myPlaceInGrid) && contents.length > 0) {
- _detach(!myContext.isStateBeingRestored()).notifyWhenDone(result);
+ final Tab tab = myContainer.getTab();
+ final boolean detached = (tab != null && tab.isDetached(myPlaceInGrid)) || window != myContext.getWindow();
+ if (detached && contents.length > 0) {
+ if (tab != null) {
+ tab.setDetached(myPlaceInGrid, false);
+ }
+ myContext.detachTo(window, this).notifyWhenDone(result);
} else {
result.setDone();
}
@@ -321,7 +315,7 @@ public class GridCellImpl implements GridCell, Disposable {
return result;
}
- private Content[] getContents() {
+ Content[] getContents() {
return myContents.getKeys().toArray(new Content[myContents.size()]);
}
@@ -339,6 +333,14 @@ public class GridCellImpl implements GridCell, Disposable {
for (Content each : myMinimizedContents) {
saveState(each, true);
}
+
+ final DimensionService service = DimensionService.getInstance();
+ final Dimension size = myContext.getContentManager().getComponent().getSize();
+ service.setSize(getDimensionKey(), size, myContext.getProject());
+ if (myContext.getWindow() != 0) {
+ final JFrame frame = (JFrame)DockManager.getInstance(myContext.getProject()).getIdeFrame((DockContainer)myContext);
+ service.setLocation(getDimensionKey(), frame.getLocationOnScreen());
+ }
}
public void saveProportions() {
@@ -350,8 +352,7 @@ public class GridCellImpl implements GridCell, Disposable {
state.setMinimizedInGrid(minimized);
state.setPlaceInGrid(myPlaceInGrid);
state.assignTab(myContainer.getTabIndex());
-
- state.getTab().setDetached(myPlaceInGrid, isDetached());
+ state.setWindow(myContext.getWindow());
}
public void restoreProportions() {
@@ -362,7 +363,7 @@ public class GridCellImpl implements GridCell, Disposable {
for (Content each : myContents.getKeys()) {
final TabInfo eachTab = getTabFor(each);
boolean isSelected = eachTab != null && myTabs.getSelectedInfo() == eachTab;
- if (isSelected && (isShowing || isDetached())) {
+ if (isSelected && isShowing) {
myContext.getContentManager().addSelectedContent(each);
}
else {
@@ -391,147 +392,22 @@ public class GridCellImpl implements GridCell, Disposable {
}
}
- public ActionCallback detach() {
- return _detach(true);
+ @Nullable
+ public Point getLocation() {
+ return DimensionService.getInstance().getLocation(getDimensionKey(), myContext.getProject());
}
- private ActionCallback _detach(final boolean requestFocus) {
- myContext.saveUiState();
-
- final DimensionService dimService = DimensionService.getInstance();
- Point storedLocation = dimService.getLocation(getDimensionKey(), myContext.getProject());
- Dimension storedSize = dimService.getSize(getDimensionKey(), myContext.getProject());
-
- final IdeFrame frame = WindowManager.getInstance().getIdeFrame(myContext.getProject());
- final Rectangle targetBounds = frame.suggestChildFrameBounds();
-
-
- if (storedLocation != null && storedSize != null) {
- targetBounds.setLocation(storedLocation);
- targetBounds.setSize(storedSize);
- }
-
- final ActionCallback result = new ActionCallback();
-
- if (storedLocation == null || storedSize == null) {
- if (myContents.size() > 0) {
- myContext.validate(myContents.getKeys().iterator().next(), new ActiveRunnable() {
- public ActionCallback run() {
- if (!myTabs.getComponent().isShowing()) {
- detachTo(targetBounds.getLocation(), targetBounds.getSize(), false, requestFocus).notifyWhenDone(result);
- } else {
- detachForShowingTabs(requestFocus).notifyWhenDone(result);
- }
-
- return new ActionCallback.Done();
- }
- });
-
- return result;
- }
- }
-
- detachTo(targetBounds.getLocation(), targetBounds.getSize(), false, requestFocus).notifyWhenDone(result);
-
- return result;
+ @Nullable
+ public Dimension getSize() {
+ return DimensionService.getInstance().getSize(getDimensionKey(), myContext.getProject());
}
-
- private ActionCallback detachForShowingTabs(boolean requestFocus) {
- return detachTo(myTabs.getComponent().getLocationOnScreen(), myTabs.getComponent().getSize(), false, requestFocus);
- }
-
- private ActionCallback detachTo(Point screenPoint, Dimension size, boolean dragging, final boolean requestFocus) {
- if (isDetached()) {
- if (myPopup != null) {
- return new ActionCallback.Done();
- }
- }
-
- final Content[] contents = getContents();
-
- myRestoreFromDetach = new CellTransform.Restore.List();
-
- myRestoreFromDetach.add(myPlaceholder.detach());
- myRestoreFromDetach.add(myContainer.detach(contents));
- myRestoreFromDetach.add(new CellTransform.Restore() {
- public ActionCallback restoreInGrid() {
- ensureVisible();
- return new ActionCallback.Done();
- }
- });
-
- myPopup = createPopup(dragging, requestFocus);
- myPopup.setSize(size);
- myPopup.setLocation(screenPoint);
- myPopup.show(myContext.getContentManager().getComponent());
-
- myContext.saveUiState();
-
- myTabs.updateTabActions(true);
-
- return new ActionCallback.Done();
- }
-
- private void ensureVisible() {
- if (myTabs.getSelectedInfo() != null) {
- myContext.select(getContentFor(myTabs.getSelectedInfo()), true);
- }
- }
-
- private JBPopup createPopup(boolean dragging, final boolean requestFocus) {
- Wrapper wrapper = new Wrapper(myTabs.getComponent());
- wrapper.setBorder(new EmptyBorder(1, 0, 0, 0));
- final ComponentPopupBuilder builder = JBPopupFactory.getInstance().createComponentPopupBuilder(wrapper, myTabs.getComponent())
- .setTitle(myContainer.getSessionName())
- .setMovable(true)
- .setRequestFocus(requestFocus)
- .setFocusable(true)
- .setResizable(true)
- .setDimensionServiceKey(myContext.getProject(), getDimensionKey(), true)
- .setCancelOnOtherWindowOpen(false)
- .setCancelOnClickOutside(false)
- .setCancelKeyEnabled(true)
- .setLocateByContent(dragging)
- .setLocateWithinScreenBounds(!dragging)
- .setCancelKeyEnabled(false)
- .setBelongsToGlobalPopupStack(false)
- .setModalContext(false)
- .setCancelCallback(new Computable() {
- public Boolean compute() {
- if (myDisposed || myContents.size() == 0) return Boolean.TRUE;
- myRestoreFromDetach.restoreInGrid();
- myRestoreFromDetach = null;
- myContext.saveUiState();
- myTabs.updateTabActions(true);
- return Boolean.TRUE;
- }
- });
-
- return builder.createPopup();
- }
-
- public void attach() {
- if (isDetached()) {
- myPopup.cancel();
- myPopup = null;
- }
- }
-
-
- public boolean isDetached() {
- return myRestoreFromDetach != null && !myRestoreFromDetach.isRestoringNow();
- }
-
- public boolean isRestoringFromDetach() {
- return myRestoreFromDetach != null && myRestoreFromDetach.isRestoringNow();
- }
-
+
private String getDimensionKey() {
return "GridCell.Tab." + myContainer.getTab().getIndex() + "." + myPlaceInGrid.name();
}
- public boolean isValidForCalculatePropertions() {
- return !isDetached() && getContentCount() > 0;
+ public boolean isValidForCalculateProportions() {
+ return getContentCount() > 0;
}
public void minimize(Content content) {
@@ -553,13 +429,4 @@ public class GridCellImpl implements GridCell, Disposable {
updateSelection(myTabs.getComponent().getRootPane() != null);
return new ActionCallback.Done();
}
-
- public void dispose() {
- myDisposed = true;
-
- if (myPopup != null) {
- myPopup.cancel();
- myPopup = null;
- }
- }
}
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridImpl.java
index dfb6659f6c1a..f023d86d3a9b 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridImpl.java
@@ -35,7 +35,7 @@ import java.awt.*;
import java.util.*;
import java.util.List;
-public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform.Facade, DataProvider {
+public class GridImpl extends Wrapper implements Grid, Disposable, DataProvider {
private final ThreeComponentsSplitter myTopSplit = new ThreeComponentsSplitter();
private final Splitter mySplitter = new Splitter(true);
@@ -152,8 +152,7 @@ public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform
public boolean updateGridUI() {
for (final GridCellImpl cell : myPlaceInGrid2Cell.values()) {
- final boolean eachToHide = myContents.size() == 1 && !cell.isDetached();
- cell.setHideTabs(eachToHide);
+ cell.setHideTabs(myContents.size() == 1);
}
final Content onlyContent = myContents.get(0);
@@ -252,7 +251,7 @@ public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform
final GridCellImpl cell = myPlaceInGrid2Cell.get(placeInGrid);
- if (!cell.isValidForCalculatePropertions()) return;
+ if (!cell.isValidForCalculateProportions()) return;
final TabImpl tab = (TabImpl)getTab();
@@ -335,19 +334,12 @@ public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform
ArrayList result = new ArrayList();
for (Content each : getContents()) {
- if (!isDetached(each)) {
- result.add(each);
- }
+ result.add(each);
}
return result;
}
-
- public boolean isDetached(Content content) {
- return getCellFor(content).isDetached();
- }
-
public List getContents() {
return myContents;
}
@@ -360,28 +352,6 @@ public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform
});
}
- public void moveToTab(final Content content) {
- myViewContext.getCellTransform().moveToTab(content);
- }
-
- public void moveToGrid(final Content content) {
- myViewContext.getCellTransform().moveToGrid(content);
- }
-
- public CellTransform.Restore detach(final Content[] content) {
- final CellTransform.Restore.List restore = new CellTransform.Restore.List();
- restore.add(myViewContext.getCellTransform().detach(content));
- restore.add(new CellTransform.Restore() {
- public ActionCallback restoreInGrid() {
- revalidate();
- repaint();
- return new ActionCallback.Done();
- }
- });
-
- return restore;
- }
-
@Nullable
public Object getData(@NonNls final String dataId) {
if (ViewContext.CONTEXT_KEY.is(dataId)) {
@@ -394,10 +364,6 @@ public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform
return null;
}
- public String getSessionName() {
- return mySessionName;
- }
-
@Nullable
public SwitchTarget getCellFor(Component c) {
Component eachParent = c;
@@ -419,9 +385,7 @@ public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform
Collection cells = myPlaceInGrid2Cell.values();
ArrayList result = new ArrayList();
for (GridCellImpl each : cells) {
- if (!each.isDetached()) {
- result.addAll(each.getTargets(onlyVisible));
- }
+ result.addAll(each.getTargets(onlyVisible));
}
return result;
}
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java
new file mode 100644
index 000000000000..944876b1cca3
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java
@@ -0,0 +1,276 @@
+/*
+ * 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.execution.ui.layout.impl;
+
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.actionSystem.ActionGroup;
+import com.intellij.openapi.actionSystem.ActionManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.wm.IdeFocusManager;
+import com.intellij.ui.Gray;
+import com.intellij.ui.awt.RelativePoint;
+import com.intellij.ui.tabs.TabInfo;
+import com.intellij.ui.tabs.TabsUtil;
+import com.intellij.ui.tabs.UiDecorator;
+import com.intellij.ui.tabs.impl.JBTabsImpl;
+import com.intellij.ui.tabs.impl.TabLabel;
+import com.intellij.util.ui.SameColor;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import java.awt.*;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Dennis.Ushakov
+ */
+public class
+ JBRunnerTabs extends JBTabsImpl {
+ public JBRunnerTabs(@Nullable Project project, ActionManager actionManager, IdeFocusManager focusManager, @NotNull Disposable parent) {
+ super(project, actionManager, focusManager, parent);
+ }
+
+ @Override
+ protected void paintFirstGhost(Graphics2D g2d) {}
+
+ @Override
+ protected void paintLastGhost(Graphics2D g2d) {}
+
+ public boolean isGhostsAlwaysVisible() {
+ return false;
+ }
+
+ protected void doPaintInactive(Graphics2D g2d,
+ boolean leftGhostExists,
+ TabLabel label,
+ Rectangle effectiveBounds,
+ boolean rightGhostExists) {
+ Insets insets = getTabsBorder().getEffectiveBorder();
+
+ int _x = effectiveBounds.x + insets.left;
+ int _y = effectiveBounds.y + insets.top + 5;
+ int _width = effectiveBounds.width - insets.left - insets.right;
+ int _height = effectiveBounds.height - insets.top - insets.bottom - 5;
+ _height -= TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT;
+
+ g2d
+ .setPaint(new GradientPaint(_x, _y, new Color(255, 255, 255, 180), _x, _y + effectiveBounds.height, new Color(255, 255, 255, 100)));
+ g2d.fillRect(_x, _y, _width, _height);
+
+ g2d.setColor(new Color(255, 255, 255, 100));
+ g2d.drawRect(_x, _y, _width - 1, _height - 1);
+ }
+
+ @Override
+ protected void doPaintBackground(Graphics2D g2d, Rectangle clip) {
+ g2d.setColor(UIUtil.getPanelBackground());
+ g2d.fill(clip);
+
+ g2d.setColor(new Color(0, 0, 0, 50));
+ g2d.fill(clip);
+
+ List visibleInfos = getVisibleInfos();
+
+ Insets insets = getTabsBorder().getEffectiveBorder();
+
+ int maxOffset = 0;
+ int maxLength = 0;
+
+ for (int i = visibleInfos.size() - 1; i >= 0; i--) {
+ TabInfo visibleInfo = visibleInfos.get(i);
+ TabLabel tabLabel = myInfo2Label.get(visibleInfo);
+ Rectangle r = tabLabel.getBounds();
+ if (r.width == 0 || r.height == 0) continue;
+ maxOffset = r.x + r.width;
+ maxLength = r.height;
+ break;
+ }
+
+ maxOffset++;
+
+ Rectangle r2 = getBounds();
+
+ Rectangle rectangle;
+ int y = r2.y + insets.top;
+ int height = maxLength - insets.top - insets.bottom;
+ height -= TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT;
+
+ rectangle = new Rectangle(maxOffset, y, r2.width - maxOffset - insets.left - insets.right, height);
+
+ g2d.setPaint(UIUtil.getPanelBackground());
+ g2d.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
+ g2d.fillRect(0, 0, rectangle.x + rectangle.width, 5);
+ g2d.fillRect(2, maxLength, getSize().width, getSize().height);
+ g2d.drawLine(0, 0, 0, getSize().height);
+ }
+
+ protected void paintSelectionAndBorder(Graphics2D g2d) {
+ if (getSelectedInfo() == null) return;
+
+ TabLabel label = getSelectedLabel();
+ Rectangle r = label.getBounds();
+ r = new Rectangle(r.x, r.y + 5, r.width, r.height - 5);
+
+ ShapeInfo selectedShape = _computeSelectedLabelShape(r);
+
+ Insets insets = getTabsBorder().getEffectiveBorder();
+ Insets i = selectedShape.path.transformInsets(insets);
+
+ int _x = r.x;
+ int _y = r.y;
+ int _height = r.height;
+
+ if (!isHideTabs()) {
+ g2d.setPaint(new GradientPaint(_x, _y, new SameColor(255), _x, _y + _height, UIUtil.getPanelBackground()));
+
+ g2d.fill(selectedShape.fillPath.getShape());
+
+ g2d.setColor(new Color(255, 255, 255, 180));
+ g2d.draw(selectedShape.fillPath.getShape());
+ }
+ g2d.setColor(UIUtil.getPanelBackground());
+ g2d.fillRect(2, selectedShape.labelPath.getMaxY() - 3, selectedShape.path.getMaxX() - 3, 4);
+ g2d.drawLine(1, selectedShape.labelPath.getMaxY(), 1, getHeight() - 1);
+ g2d.drawLine(selectedShape.path.getMaxX() - 1, selectedShape.labelPath.getMaxY() - 4,
+ selectedShape.path.getMaxX() - 1, getHeight() - 1);
+
+ if (isHideTabs()) return;
+ g2d.setColor(new Color(0, 0, 0, 50));
+ g2d.drawLine(1, selectedShape.labelPath.getMaxY(), 1, getHeight() - 1);
+ g2d.drawLine(selectedShape.path.getMaxX() - 1, selectedShape.labelPath.getMaxY() - 4,
+ selectedShape.path.getMaxX() - 1, getHeight() - 1);
+ }
+
+ @Override
+ public Color getBackground() {
+ return Gray._142;
+ }
+
+ protected ShapeInfo _computeSelectedLabelShape(Rectangle r) {
+ final ShapeInfo shape = new ShapeInfo();
+
+ shape.path = getEffectiveLayout().createShapeTransform(getSize());
+ shape.insets = shape.path.transformInsets(getLayoutInsets());
+ shape.labelPath = shape.path.createTransform(r);
+
+ shape.labelBottomY = shape.labelPath.getMaxY() - shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1);
+ shape.labelTopY = shape.labelPath.getY() + shape.labelPath.deltaY(1);
+ shape.labelLeftX = shape.labelPath.getX();
+ shape.labelRightX = shape.labelPath.getMaxX() - shape.labelPath.deltaX(1);
+
+ int leftX = shape.insets.left;
+
+ shape.path.moveTo(leftX, shape.labelBottomY);
+ shape.path.lineTo(shape.labelLeftX, shape.labelBottomY);
+ shape.path.lineTo(shape.labelLeftX, shape.labelTopY);
+ shape.path.lineTo(shape.labelRightX, shape.labelTopY);
+ shape.path.lineTo(shape.labelRightX, shape.labelBottomY);
+
+ int lastX = shape.path.getWidth() - shape.path.deltaX(shape.insets.right);
+
+ shape.path.lineTo(lastX, shape.labelBottomY);
+ shape.path.lineTo(lastX, shape.labelBottomY + shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1));
+ shape.path.lineTo(leftX, shape.labelBottomY + shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1));
+
+ shape.path.closePath();
+ shape.fillPath = shape.path.copy();
+
+ return shape;
+ }
+
+ @Override
+ public int getToolbarInset() {
+ return 8;
+ }
+
+ public boolean shouldAddToGlobal(Point point) {
+ final TabLabel label = getSelectedLabel();
+ if (label == null || point == null) {
+ return true;
+ }
+ final Rectangle bounds = label.getBounds();
+ return point.y <= bounds.y + bounds.height;
+ }
+
+ @Override
+ public Rectangle layout(JComponent c, Rectangle bounds) {
+ if (c instanceof Toolbar) {
+ bounds.height -= 5;
+ return super.layout(c, bounds);
+ }
+ if (c instanceof GridImpl) {
+ bounds.x -= 1;
+ bounds.width += 1;
+ }
+ return super.layout(c, bounds);
+ }
+
+ @Override
+ public void processDropOver(TabInfo over, RelativePoint relativePoint) {
+ super.processDropOver(over, relativePoint);
+ final Point point = relativePoint.getPoint(getComponent());
+ for (Map.Entry entry : myInfo2Label.entrySet()) {
+ final TabLabel label = entry.getValue();
+ if (label.getBounds().contains(point) && myDropInfo != entry.getKey()) {
+ select(entry.getKey(), false);
+ break;
+ }
+ }
+ }
+
+ @Override
+ protected TabLabel createTabLabel(TabInfo info) {
+ return new MyTabLabel(this, info);
+ }
+
+ private static class MyTabLabel extends TabLabel {
+ public MyTabLabel(JBTabsImpl tabs, final TabInfo info) {
+ super(tabs, info);
+ }
+
+ @Override
+ public void apply(UiDecorator.UiDecoration decoration) {
+ setFont(UIUtil.getLabelFont(UIUtil.FontSize.SMALL));
+ myLabel.setFont(UIUtil.getLabelFont(UIUtil.FontSize.SMALL));
+ setBorder(new EmptyBorder(7, 5, 7, 5));
+ }
+
+ @Override
+ public void setTabActionsAutoHide(boolean autoHide) {
+ super.setTabActionsAutoHide(autoHide);
+ apply(null);
+ }
+
+ @Override
+ public void setTabActions(ActionGroup group) {
+ super.setTabActions(group);
+ if (myActionPanel != null) {
+ final JComponent wrapper = (JComponent)myActionPanel.getComponent(0);
+ wrapper.remove(0);
+ wrapper.add(Box.createHorizontalStrut(6), BorderLayout.WEST);
+ }
+ }
+
+ @Override
+ protected int getSelectedOffset() {
+ return getNonSelectedOffset();
+ }
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java
index b2732529f4f6..4448dacb739e 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java
+++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java
@@ -28,21 +28,28 @@ import com.intellij.openapi.util.ActiveRunnable;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.wm.IdeFocusManager;
+import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.ui.UIBundle;
+import com.intellij.ui.awt.RelativePoint;
+import com.intellij.ui.awt.RelativeRectangle;
import com.intellij.ui.components.panels.NonOpaquePanel;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.ui.content.*;
+import com.intellij.ui.docking.DockContainer;
+import com.intellij.ui.docking.DockManager;
+import com.intellij.ui.docking.DockableContent;
+import com.intellij.ui.docking.DragSession;
+import com.intellij.ui.docking.impl.DockManagerImpl;
import com.intellij.ui.switcher.QuickActionProvider;
import com.intellij.ui.switcher.SwitchProvider;
import com.intellij.ui.switcher.SwitchTarget;
import com.intellij.ui.tabs.JBTabs;
import com.intellij.ui.tabs.TabInfo;
import com.intellij.ui.tabs.TabsListener;
-import com.intellij.ui.tabs.UiDecorator;
-import com.intellij.ui.tabs.impl.JBTabsImpl;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.AbstractLayoutManager;
+import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -50,13 +57,15 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
+import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.*;
import java.util.List;
+import java.util.concurrent.CopyOnWriteArraySet;
public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Facade, ViewContextEx, PropertyChangeListener, SwitchProvider,
- QuickActionProvider {
+ QuickActionProvider, DockContainer {
@NonNls public static final String LAYOUT = "Runner.Layout";
@NonNls public static final String VIEW_POPUP = "Runner.View.Popup";
@@ -70,8 +79,9 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
MyComponent myComponent = new MyComponent();
private final Wrapper myToolbar = new Wrapper();
+ final MyDragOutDelegate myDragOutDelegate = new MyDragOutDelegate();
- JBTabs myTabs;
+ JBRunnerTabs myTabs;
private final Comparator myTabsComparator = new Comparator() {
public int compare(final TabInfo o1, final TabInfo o2) {
//noinspection ConstantConditions
@@ -110,6 +120,20 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
private int myAttractionCount;
private ActionGroup myLeftToolbarActions;
+ private JBTabs myCurrentOver;
+ private Image myCurrentOverImg;
+ private TabInfo myCurrentOverInfo;
+ private RunnerContentUi myOriginal;
+ private CopyOnWriteArraySet myDockingListeners = new CopyOnWriteArraySet();
+ private Set myChildren = new TreeSet(new Comparator() {
+ @Override
+ public int compare(RunnerContentUi o1, RunnerContentUi o2) {
+ return o1.myWindow - o2.myWindow;
+ }
+ });
+ private int myWindow;
+ private boolean myDisposing;
+
public RunnerContentUi(Project project,
RunnerLayoutUi ui,
ActionManager actionManager,
@@ -124,6 +148,12 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
myFocusManager = focusManager;
}
+ public RunnerContentUi(RunnerContentUi ui, RunnerContentUi original, int window) {
+ this(ui.myProject, ui.myRunnerUi, ui.myActionManager, ui.myFocusManager, ui.myLayoutSettings, ui.mySessionName);
+ myOriginal = original;
+ original.myChildren.add(this);
+ myWindow = window == 0 ? original.findFreeWindow() : window;
+ }
public void setTopActions(@NotNull final ActionGroup topActions, @NotNull String place) {
myTopActions = topActions;
@@ -150,32 +180,27 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
public void initUi() {
if (myTabs != null) return;
- myTabs = new JBTabsImpl(myProject, myActionManager, myFocusManager, this)
- .setDataProvider(new DataProvider() {
- public Object getData(@NonNls final String dataId) {
- if (ViewContext.CONTENT_KEY.is(dataId)) {
- TabInfo info = myTabs.getTargetInfo();
- if (info != null) {
- return getGridFor(info).getData(dataId);
- }
+ myTabs = (JBRunnerTabs)new JBRunnerTabs(myProject, myActionManager, myFocusManager, this).setDataProvider(new DataProvider() {
+ public Object getData(@NonNls final String dataId) {
+ if (ViewContext.CONTENT_KEY.is(dataId)) {
+ TabInfo info = myTabs.getTargetInfo();
+ if (info != null) {
+ return getGridFor(info).getData(dataId);
}
- else if (ViewContext.CONTEXT_KEY.is(dataId)) {
- return RunnerContentUi.this;
- }
- return null;
}
- }).setProvideSwitchTargets(false).setInnerInsets(new Insets(1, 0, 0, 0)).setToDrawBorderIfTabsHidden(false)
- .setUiDecorator(new UiDecorator() {
- @NotNull
- public UiDecoration getDecoration() {
- return new UiDecoration(null, new Insets(1, 8, 1, 8));
+ else if (ViewContext.CONTEXT_KEY.is(dataId)) {
+ return RunnerContentUi.this;
}
- }).getJBTabs();
+ return null;
+ }
+ }).setTabLabelActionsAutoHide(false).setProvideSwitchTargets(false).setInnerInsets(new Insets(0, 0, 0, 0))
+ .setToDrawBorderIfTabsHidden(false).setTabDraggingEnabled(isMoveToGridActionEnabled()).setUiDecorator(null).getJBTabs();
rebuildTabPopup();
-
- myTabs.getPresentation().setPaintBorder(0, 0, 0, 0).setTabSidePaintBorder(2).setPaintFocus(false)
+ myTabs.getPresentation().setPaintBorder(0, 0, 0, 0).setPaintFocus(false)
.setRequestFocusOnLastFocusedComponent(true);
+ myTabs.getComponent().setBackground(myToolbar.getBackground());
+ myTabs.getComponent().setBorder(new EmptyBorder(0, 2, 0, 0));
final NonOpaquePanel wrappper = new NonOpaquePanel(new BorderLayout(0, 0));
wrappper.add(myToolbar, BorderLayout.WEST);
@@ -194,6 +219,11 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
}
}
+ @Override
+ public void tabsMoved() {
+ saveUiState();
+ }
+
public void selectionChanged(final TabInfo oldSelection, final TabInfo newSelection) {
if (!myTabs.getComponent().isShowing()) return;
@@ -207,6 +237,14 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
}
}
});
+
+ if (myOriginal != null) {
+ final ContentManager manager = ContentFactory.SERVICE.getInstance().createContentManager(this, false, myProject);
+ Disposer.register((Disposable)myRunnerUi, manager);
+ manager.getComponent();
+ } else {
+ DockManager.getInstance(myProject).register(this);
+ }
}
private void rebuildTabPopup() {
@@ -249,10 +287,15 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
return group;
}
- public void doWhenInitialized(final Runnable runnable) {
- myInitialized.doWhenDone(runnable);
+ @Override
+ public boolean isOriginal() {
+ return myOriginal == null;
}
+ @Override
+ public int getWindow() {
+ return myWindow;
+ }
public void propertyChange(final PropertyChangeEvent evt) {
Content content = (Content)evt.getSource();
@@ -302,11 +345,193 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
}
}
+ @Override
+ public ActionCallback detachTo(int window, GridCell cell) {
+ if (myOriginal != null) {
+ return myOriginal.detachTo(window, cell);
+ }
+ RunnerContentUi target = null;
+ if (window > 0) {
+ for (RunnerContentUi child : myChildren) {
+ if (child.myWindow == window) {
+ target = child;
+ break;
+ }
+ }
+ }
+ final GridCellImpl gridCell = (GridCellImpl)cell;
+ final Content[] contents = gridCell.getContents();
+ storeDefaultIndices(contents);
+ for (Content content : contents) {
+ content.putUserData(RunnerLayout.DROP_INDEX, getStateFor(content).getTab().getIndex());
+ }
+ Dimension size = gridCell.getSize();
+ if (size == null) {
+ size = new Dimension(200, 200);
+ }
+ final DockableGrid content = new DockableGrid(null, null, size, Arrays.asList(contents), window);
+ if (target != null) {
+ target.add(content, null);
+ } else {
+ final Point location = gridCell.getLocation();
+ location.translate(size.width / 2, size.height / 2);
+ getDockManager().createNewDockContainerFor(content, new RelativePoint(location));
+ }
+ return new ActionCallback.Done();
+ }
+
+ private void storeDefaultIndices(Content[] contents) {
+ for (Content content : contents) {
+ content.putUserData(RunnerLayout.DEFAULT_INDEX, getStateFor(content).getTab().getDefaultIndex());
+ }
+ }
+
+ @Override
+ public RelativeRectangle getAcceptArea() {
+ return new RelativeRectangle(myTabs.getComponent());
+ }
+
+ @Override
+ public boolean canAccept(DockableContent content, RelativePoint point) {
+ if (!(content instanceof DockableGrid)) {
+ return false;
+ }
+ final RunnerContentUi ui = ((DockableGrid)content).getOriginalRunnerUi();
+ return ui.getProject() == myProject && ui.mySessionName.equals(mySessionName);
+ }
+
+ @Override
public JComponent getComponent() {
initUi();
return myComponent;
}
+ @Override
+ public JComponent getContainerComponent() {
+ initUi();
+ return myManager.getComponent();
+ }
+
+ @Override
+ public void add(DockableContent dockable, RelativePoint dropTarget) {
+ saveUiState();
+
+ final DockableGrid dockableGrid = (DockableGrid)dockable;
+ final List contents = dockableGrid.getContents();
+ final boolean wasRestoring = myOriginal != null && myOriginal.isStateBeingRestored();
+ setStateIsBeingRestored(true, this);
+ try {
+ final Point point = dropTarget != null ? dropTarget.getPoint(myComponent) : null;
+ boolean hadGrid = !myTabs.shouldAddToGlobal(point);
+
+ for (Content content : contents) {
+ dockableGrid.getRunnerUi().myManager.removeContent(content, false);
+ myManager.removeContent(content, false);
+ if (hadGrid && contents.size() == 1 && !wasRestoring) {
+ getStateFor(content).assignTab(getTabFor(getSelectedGrid()));
+ getStateFor(content).setPlaceInGrid(myLayoutSettings.getDefaultGridPlace(content));
+ } else if (contents.size() == 1 && !wasRestoring) {
+ getStateFor(content).assignTab(myLayoutSettings.createNewTab());
+ getStateFor(content).setPlaceInGrid(myLayoutSettings.getDefaultGridPlace(content));
+ }
+ getStateFor(content).setWindow(myWindow);
+ myManager.addContent(content);
+ }
+ } finally {
+ setStateIsBeingRestored(false, this);
+ }
+
+ saveUiState();
+
+ updateTabsUI(true);
+ }
+
+ @Override
+ public void closeAll() {
+ final Content[] contents = myManager.getContents();
+ for (Content content : contents) {
+ getStateFor(content).setWindow(0);
+ }
+ myManager.removeAllContents(false);
+ for (Content content : contents) {
+ myOriginal.myManager.addContent(content);
+ myOriginal.findCellFor(content).minimize(content);
+ }
+ }
+
+ @Override
+ public void addListener(final Listener listener, Disposable parent) {
+ myDockingListeners.add(listener);
+ Disposer.register(parent, new Disposable() {
+ @Override
+ public void dispose() {
+ myDockingListeners.remove(listener);
+ }
+ });
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return myTabs.isEmptyVisible() || myDisposing;
+ }
+
+ @Override
+ public Image startDropOver(DockableContent content, RelativePoint point) {
+ return null;
+ }
+
+ @Override
+ public Image processDropOver(DockableContent content, RelativePoint point) {
+ JBTabs current = getTabsAt(content, point);
+
+ if (myCurrentOver != null && myCurrentOver != current) {
+ resetDropOver(content);
+ }
+
+ if (myCurrentOver == null && current != null) {
+ myCurrentOver = current;
+ Presentation presentation = content.getPresentation();
+ myCurrentOverInfo = new TabInfo(new JLabel("")).setText(presentation.getText()).setIcon(presentation.getIcon());
+ myCurrentOverImg = myCurrentOver.startDropOver(myCurrentOverInfo, point);
+ }
+
+ if (myCurrentOver != null) {
+ myCurrentOver.processDropOver(myCurrentOverInfo, point);
+ }
+
+ return myCurrentOverImg;
+ }
+
+ @Nullable
+ private JBTabs getTabsAt(DockableContent content, RelativePoint point) {
+ if (content instanceof DockableGrid) {
+ final Point p = point.getPoint(getComponent());
+ Component c = SwingUtilities.getDeepestComponentAt(getComponent(), p.x, p.y);
+ while (c != null) {
+ if (c instanceof JBTabs) {
+ return (JBTabs)c;
+ }
+ c = c.getParent();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void resetDropOver(DockableContent content) {
+ if (myCurrentOver != null) {
+ myCurrentOver.resetDropOver(myCurrentOverInfo);
+ myCurrentOver = null;
+ myCurrentOverInfo = null;
+ myCurrentOverImg = null;
+ }
+ }
+
+ @Override
+ public boolean isDisposeWhenEmpty() {
+ return myOriginal != null;
+ }
+
public boolean isCycleRoot() {
return false;
}
@@ -337,6 +562,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
event.getContent().addPropertyChangeListener(RunnerContentUi.this);
+ fireContentOpened(event.getContent());
}
public void contentRemoved(final ContentManagerEvent event) {
@@ -349,6 +575,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
removeGridIfNeeded(grid);
}
updateTabsUI(false);
+ fireContentClosed(event.getContent());
}
public void contentRemoveQuery(final ContentManagerEvent event) {
@@ -387,6 +614,16 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
grid = new GridImpl(this, mySessionName);
grid.setBorder(new EmptyBorder(1, 0, 0, 0));
+ if (myCurrentOver != null || myOriginal != null) {
+ Integer forcedDropIndex = content.getUserData(RunnerLayout.DROP_INDEX);
+ final int index = myTabs.getDropInfoIndex() + (myOriginal != null ? myOriginal.getTabOffsetFor(this) : 0);
+ final TabImpl tab = myLayoutSettings.getOrCreateTab(-1);
+ final Integer defaultIndex = content.getUserData(RunnerLayout.DEFAULT_INDEX);
+ tab.setDefaultIndex(defaultIndex != null ? defaultIndex : -1);
+ tab.setIndex(forcedDropIndex != null ? forcedDropIndex : index);
+ getStateFor(content).assignTab(tab);
+ }
+
TabInfo tab = new TabInfo(grid).setObject(getStateFor(content).getTab()).setText("Tab");
@@ -418,6 +655,15 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
return grid;
}
+ private int getTabOffsetFor(RunnerContentUi ui) {
+ int offset = myTabs.getTabCount();
+ for (RunnerContentUi child : myChildren) {
+ if (child == ui) break;
+ offset += child.myTabs.getTabCount();
+ }
+ return offset;
+ }
+
@Nullable
public GridCell findCellFor(final Content content) {
GridImpl cell = getGridFor(content, false);
@@ -498,9 +744,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
for (TabInfo each : tabs) {
hasToolbarContent |= updateTabUI(each);
}
-
- myTabs.getPresentation().setHideTabs(!hasToolbarContent && tabs.size() <= 1);
-
+ myTabs.getPresentation().setHideTabs(!hasToolbarContent && tabs.size() <= 1 && myOriginal == null);
myTabs.updateTabActions(validateNow);
if (validateNow) {
@@ -508,7 +752,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
}
}
- private static boolean updateTabUI(TabInfo tab) {
+ private boolean updateTabUI(TabInfo tab) {
TabImpl t = getTabFor(tab);
if (t == null) {
return false;
@@ -534,9 +778,11 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
}
if (icon == null && contents.size() == 1) {
+ tab.setHidden(grid.isMinimized(contents.get(0)));
icon = contents.get(0).getIcon();
}
+ tab.setDragOutDelegate(myTabs.getTabs().size() > 1 || !isOriginal() ? myDragOutDelegate : null);
Tab gridTab = grid.getTab();
tab.setText(title).setIcon(gridTab != null && gridTab.isDefault() ? null : icon);
@@ -569,10 +815,38 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
public void saveUiState() {
if (isStateBeingRestored()) return;
+ if (myOriginal != null) {
+ myOriginal.saveUiState();
+ return;
+ }
+ int offset = updateTabsIndices(myTabs, 0);
+ for (RunnerContentUi child : myChildren) {
+ offset = updateTabsIndices(child.myTabs, offset);
+ }
+
+ doSaveUiState();
+ }
+
+ private static int updateTabsIndices(final JBRunnerTabs tabs, int offset) {
+ for (TabInfo each : tabs.getTabs()) {
+ final int index = tabs.getIndexOf(each);
+ final TabImpl tab = getTabFor(each);
+ if (tab != null) tab.setIndex(index + offset);
+ }
+ return offset + tabs.getTabCount();
+ }
+
+ private void doSaveUiState() {
+ if (isStateBeingRestored()) return;
+
for (TabInfo each : myTabs.getTabs()) {
GridImpl eachGrid = getGridFor(each);
eachGrid.saveUiState();
}
+
+ for (RunnerContentUi child : myChildren) {
+ child.doSaveUiState();
+ }
}
@Nullable
@@ -581,6 +855,17 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
return getTabFor(info);
}
+ @Override
+ public void showNotify() {
+ final Window window = SwingUtilities.getWindowAncestor(myComponent);
+ if (window instanceof IdeFrame.Child) {
+ ((IdeFrame.Child)window).setFrameTitle(mySessionName);
+ }
+ }
+
+ @Override
+ public void hideNotify() {}
+
@Nullable
private static TabImpl getTabFor(@Nullable final TabInfo tab) {
if (tab == null) {
@@ -640,6 +925,10 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
if (myComponent.getRootPane() != null) {
saveUiState();
}
+ if (myOriginal != null) {
+ myDisposing = true;
+ fireContentClosed(null);
+ }
}
public boolean canChangeSelectionTo(Content content, boolean implicit) {
@@ -674,14 +963,25 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
}
public void dispose() {
-
+ if (myOriginal != null) {
+ myOriginal.myChildren.remove(this);
+ }
}
public void restoreLayout() {
- Content[] all = myManager.getContents();
+ final RunnerContentUi[] children = myChildren.toArray(new RunnerContentUi[myChildren.size()]);
+ final List contents = new ArrayList();
+ Collections.addAll(contents, myManager.getContents());
+ for (RunnerContentUi child : children) {
+ Collections.addAll(contents, child.myManager.getContents());
+ }
+ Content[] all = contents.toArray(new Content[contents.size()]);
setStateIsBeingRestored(true, this);
try {
+ for (RunnerContentUi child : children) {
+ child.myManager.removeAllContents(false);
+ }
myManager.removeAllContents(false);
myMinimizedViewActions.removeAll();
}
@@ -730,7 +1030,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
}
public boolean isMinimizeActionEnabled() {
- return myMinimizeActionEnabled;
+ return myMinimizeActionEnabled && myOriginal == null;
}
public boolean isMoveToGridActionEnabled() {
@@ -820,12 +1120,12 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
public void addNotify() {
super.addNotify();
- if (!myUiLastStateWasRestored) {
+ if (!myUiLastStateWasRestored && myOriginal == null) {
myUiLastStateWasRestored = true;
- //noinspection SSBasedInspection
// [kirillk] this is done later since restoreUiState doesn't work properly in the addNotify call chain
//todo to investigate and to fix (may cause extra flickering)
+ //noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
public void run() {
restoreLastUiState().doWhenDone(new Runnable() {
@@ -946,90 +1246,6 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
updateTabsUI(false);
}
- private static boolean willBeEmptyOnRemove(GridImpl grid, List toRemove) {
- List attachedToGrid = grid.getAttachedContents();
- for (Content each : attachedToGrid) {
- if (!toRemove.contains(each)) return false;
- }
-
- return true;
- }
-
-
- public CellTransform.Restore detach(final Content[] content) {
- List contents = Arrays.asList(content);
-
- for (Content each : content) {
- GridImpl eachGrid = getGridFor(each, false);
- if (willBeEmptyOnRemove(eachGrid, contents)) {
- TabInfo info = myTabs.findInfo(eachGrid);
- if (info != null) {
- info.setHidden(true);
- }
- }
- }
-
- updateTabsUI(true);
-
- return new CellTransform.Restore() {
- public ActionCallback restoreInGrid() {
- showHiddenTabs();
- updateTabsUI(true);
- return new ActionCallback.Done();
- }
- };
- }
-
- private void showHiddenTabs() {
- List tabs = myTabs.getTabs();
- for (TabInfo eachInfos : tabs) {
- GridImpl eachGrid = (GridImpl)eachInfos.getComponent();
- if (!eachGrid.getAttachedContents().isEmpty()) {
- eachInfos.setHidden(false);
- }
- }
- }
-
- public void moveToTab(final Content content) {
- saveUiState();
-
- setStateIsBeingRestored(true, this);
- try {
- myManager.removeContent(content, false);
- getStateFor(content).assignTab(myLayoutSettings.createNewTab());
- getStateFor(content).setPlaceInGrid(PlaceInGrid.center);
- myManager.addContent(content);
- }
- finally {
- setStateIsBeingRestored(false, this);
- }
-
- saveUiState();
- }
-
- public void moveToGrid(final Content content) {
- saveUiState();
-
- setStateIsBeingRestored(true, this);
-
- try {
- myManager.removeContent(content, false);
- getStateFor(content).assignTab(myLayoutSettings.getDefaultTab());
- getStateFor(content).setPlaceInGrid(myLayoutSettings.getDefaultGridPlace(content));
- myManager.addContent(content);
- }
- finally {
- setStateIsBeingRestored(false, this);
- }
-
- select(content, true).doWhenDone(new Runnable() {
- public void run() {
- saveUiState();
- }
- });
- }
-
-
public Project getProject() {
return myProject;
}
@@ -1055,7 +1271,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
}
public boolean isHorizontalToolbar() {
- return myLayoutSettings.isToolbarHorizontal();
+ return false;
}
public ActionCallback select(final Content content, final boolean requestFocus) {
@@ -1068,18 +1284,12 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
final ActionCallback result = new ActionCallback();
- if (grid.isDetached(content)) {
- if (requestFocus) {
+ myTabs.select(info, false).doWhenDone(new Runnable() {
+ public void run() {
grid.select(content, requestFocus).notifyWhenDone(result);
}
- }
- else {
- myTabs.select(info, false).doWhenDone(new Runnable() {
- public void run() {
- grid.select(content, requestFocus).notifyWhenDone(result);
- }
- });
- }
+ });
+
return result;
}
@@ -1233,4 +1443,142 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
return result;
}
+
+
+ private int findFreeWindow() {
+ int i;
+ for (i = 1; i < Integer.MAX_VALUE; i++) {
+ if (!isUsed(i)) {
+ return i;
+ }
+ }
+ return i;
+ }
+
+ private boolean isUsed(int i) {
+ for (RunnerContentUi child : myChildren) {
+ if (child.getWindow() == i) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private DockManagerImpl getDockManager() {
+ return (DockManagerImpl)DockManager.getInstance(myProject);
+ }
+
+ class MyDragOutDelegate implements TabInfo.DragOutDelegate {
+ private DragSession mySession;
+
+ @Override
+ public void dragOutStarted(MouseEvent mouseEvent, TabInfo info) {
+ final JComponent component = info.getComponent();
+ final Content[] data = CONTENT_KEY.getData((DataProvider)component);
+ final List contents = Arrays.asList(data);
+
+ storeDefaultIndices(data);
+
+ final Dimension size = info.getComponent().getSize();
+ final Image image = myTabs.getComponentImage(info);
+ if (component instanceof Grid) {
+ info.setHidden(true);
+ }
+
+ Presentation presentation = new Presentation(info.getText());
+ presentation.setIcon(info.getIcon());
+ mySession = getDockManager().createDragSession(mouseEvent, new DockableGrid(image, presentation,
+ size,
+ contents, 0));
+ }
+
+ @Override
+ public void processDragOut(MouseEvent event, TabInfo source) {
+ mySession.process(event);
+ }
+
+ @Override
+ public void dragOutFinished(MouseEvent event, TabInfo source) {
+ final Component component = event.getComponent();
+ final IdeFrame window = UIUtil.getParentOfType(IdeFrame.class, component);
+ if (window != null) {
+
+ }
+ mySession.process(event);
+ mySession = null;
+ }
+ }
+
+ class DockableGrid implements DockableContent> {
+ final Image myImg;
+ private Presentation myPresentation;
+ private final Dimension myPreferredSize;
+ private final List myContents;
+ private final int myWindow;
+
+ public DockableGrid(Image img, Presentation presentation, final Dimension size, List contents, int window) {
+ myImg = img;
+ myPresentation = presentation;
+ myPreferredSize = size;
+ myContents = contents;
+ myWindow = window;
+ }
+
+ @Override
+ public List getKey() {
+ return myContents;
+ }
+
+ @Override
+ public Image getPreviewImage() {
+ return myImg;
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ return myPreferredSize;
+ }
+
+ @Override
+ public String getDockContainerType() {
+ return DockableGridContainerFactory.TYPE;
+ }
+
+ @Override
+ public Presentation getPresentation() {
+ return myPresentation;
+ }
+
+ public RunnerContentUi getRunnerUi() {
+ return RunnerContentUi.this;
+ }
+
+ public RunnerContentUi getOriginalRunnerUi() {
+ return myOriginal != null ? myOriginal : RunnerContentUi.this;
+ }
+
+ public List getContents() {
+ return myContents;
+ }
+
+ @Override
+ public void close() {
+ }
+
+ public int getWindow() {
+ return myWindow;
+ }
+ }
+
+ void fireContentOpened(Content content) {
+ for (Listener each : myDockingListeners) {
+ each.contentAdded(content);
+ }
+ }
+
+ void fireContentClosed(Content content) {
+ for (Listener each : myDockingListeners) {
+ each.contentRemoved(content);
+ }
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayout.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayout.java
index 5cc040503267..b336d791e504 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayout.java
+++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayout.java
@@ -20,6 +20,7 @@ import com.intellij.execution.ui.layout.LayoutAttractionPolicy;
import com.intellij.execution.ui.layout.PlaceInGrid;
import com.intellij.execution.ui.layout.Tab;
import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.content.Content;
@@ -33,7 +34,8 @@ import javax.swing.*;
import java.util.*;
public class RunnerLayout {
-
+ public static final Key DEFAULT_INDEX = Key.create("RunnerLayoutDefaultIndex");
+ public static final Key DROP_INDEX = Key.create("RunnerLayoutDropIndex");
private final String myID;
protected Map myViews = new HashMap();
@@ -64,10 +66,6 @@ public class RunnerLayout {
return tab;
}
- public TabImpl getDefaultTab() {
- return getOrCreateTab(0);
- }
-
private TabImpl createNewTab(final int index) {
final TabImpl tab;
@@ -153,7 +151,9 @@ public class RunnerLayout {
}
for (TabImpl eachTab : myTabs) {
- eachTab.write(parentNode);
+ if (isUsed(eachTab)) {
+ eachTab.write(parentNode);
+ }
}
parentNode.addContent(XmlSerializer.serialize(myGeneral));
@@ -166,13 +166,13 @@ public class RunnerLayout {
myViews.clear();
for (TabImpl each : myTabs) {
- final TabImpl.Default defaultTab = getOrCreateDefaultTab(each.getIndex());
+ final TabImpl.Default defaultTab = getOrCreateDefaultTab(each.getDefaultIndex());
each.copyFrom(defaultTab);
}
}
public boolean isToolbarHorizontal() {
- return myGeneral.horizontalToolbar;
+ return false;
}
public void setToolbarHorizontal(boolean horizontal) {
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/TabImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/TabImpl.java
index 268029f68165..673c7bbe9898 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/TabImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/TabImpl.java
@@ -40,6 +40,10 @@ public class TabImpl extends AbstractTab implements Tab {
return myIndex;
}
+ public int getDefaultIndex() {
+ return myDefaultIndex >= 0 ? myDefaultIndex : myIndex;
+ }
+
public String getDisplayName() {
return myDisplayName;
}
@@ -52,6 +56,10 @@ public class TabImpl extends AbstractTab implements Tab {
myIndex = index;
}
+ public void setDefaultIndex(final int index) {
+ myDefaultIndex = index;
+ }
+
public void setDisplayName(final String displayName) {
myDisplayName = displayName;
}
@@ -161,6 +169,7 @@ public class TabImpl extends AbstractTab implements Tab {
public Default(final int index, final String displayName, final Icon icon) {
myIndex = index;
+ myDefaultIndex = index;
myDisplayName = displayName;
myIcon = icon;
}
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/ViewContextEx.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/ViewContextEx.java
index 13d0e593c255..84282337391b 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/ViewContextEx.java
+++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/ViewContextEx.java
@@ -16,14 +16,19 @@
package com.intellij.execution.ui.layout.impl;
+import com.intellij.execution.ui.layout.GridCell;
import com.intellij.execution.ui.layout.ViewContext;
import com.intellij.openapi.actionSystem.ActionGroup;
+import com.intellij.openapi.util.ActionCallback;
public interface ViewContextEx extends ViewContext {
RunnerLayout getLayoutSettings();
ActionGroup getCellPopupGroup(String place);
- void doWhenInitialized(Runnable runnable);
+ boolean isOriginal();
+
+ int getWindow();
+ ActionCallback detachTo(int window, GridCell cell);
}
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/ViewImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/ViewImpl.java
index 89673d9d600d..83b8d0833827 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/ViewImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/ViewImpl.java
@@ -31,16 +31,19 @@ public class ViewImpl implements View {
private Tab myTab;
private int myTabIndex;
+
+ private int myWindow;
private PlaceInGrid myPlaceInGrid;
private boolean myMinimizedInGrid;
- public ViewImpl(String id, TabImpl tab, final PlaceInGrid placeInGrid, boolean minimizedInGrid) {
+ public ViewImpl(String id, TabImpl tab, final PlaceInGrid placeInGrid, boolean minimizedInGrid, int window) {
myID = id;
myTab = tab;
myPlaceInGrid = placeInGrid;
myMinimizedInGrid = minimizedInGrid;
+ myWindow = window;
}
public ViewImpl(RunnerLayout settings, Element element) {
@@ -94,6 +97,16 @@ public class ViewImpl implements View {
myTabIndex = tabIndex;
}
+ @Override
+ public int getWindow() {
+ return myWindow;
+ }
+
+ @Override
+ public void setWindow(int windowNumber) {
+ myWindow = windowNumber;
+ }
+
public static class Default {
private final String myID;
@@ -110,7 +123,7 @@ public class ViewImpl implements View {
public ViewImpl createView(RunnerLayout settings) {
final TabImpl tab = myTabID == Integer.MAX_VALUE ? settings.createNewTab() : settings.getOrCreateTab(myTabID);
- return new ViewImpl(myID, tab, myPlaceInGrid, myMinimizedInGrid);
+ return new ViewImpl(myID, tab, myPlaceInGrid, myMinimizedInGrid, 0);
}
public PlaceInGrid getPlaceInGrid() {
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java
index e60a8ccc09a7..52134b1f406a 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java
@@ -32,6 +32,8 @@ import com.intellij.ui.ColoredListCellRenderer;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.ui.popup.list.ListPopupImpl;
import com.intellij.util.Processor;
+import com.intellij.util.containers.hash.*;
+import com.intellij.util.containers.hash.HashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -39,6 +41,7 @@ import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.*;
+import java.util.HashMap;
import java.util.List;
/**
@@ -207,7 +210,7 @@ public class GotoRelatedFileAction extends AnAction {
}
}
- List items = new ArrayList();
+ Set items = new HashSet ();
for (GotoRelatedProvider provider : Extensions.getExtensions(GotoRelatedProvider.EP_NAME)) {
items.addAll(provider.getItems(contextElement));
@@ -215,7 +218,7 @@ public class GotoRelatedFileAction extends AnAction {
items.addAll(provider.getItems(dataContext));
}
}
- return items;
+ return new ArrayList(items);
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateManagerImpl.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateManagerImpl.java
index 323560f5efff..e39d357b7d34 100644
--- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateManagerImpl.java
@@ -48,6 +48,7 @@ import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.text.MessageFormat;
+import java.text.SimpleDateFormat;
import java.util.*;
/**
@@ -319,10 +320,17 @@ public class FileTemplateManagerImpl extends FileTemplateManager implements Expo
@NonNls Properties props = new Properties();
Calendar calendar = Calendar.getInstance();
+ Date date = new Date(calendar.getTimeInMillis());
+ SimpleDateFormat sdfMonthNameShort = new SimpleDateFormat("MMM");
+ SimpleDateFormat sdfMonthNameFull = new SimpleDateFormat("MMMM");
+ SimpleDateFormat sdfYearFull = new SimpleDateFormat("yyyy");
+
props.setProperty("DATE", DateFormatUtil.formatDate(calendar.getTime()));
props.setProperty("TIME", DateFormatUtil.formatTime(calendar.getTime()));
- props.setProperty("YEAR", Integer.toString(calendar.get(Calendar.YEAR)));
+ props.setProperty("YEAR", sdfYearFull.format(date));
props.setProperty("MONTH", getCalendarValue(calendar, Calendar.MONTH));
+ props.setProperty("MONTH_NAME_SHORT", sdfMonthNameShort.format(date));
+ props.setProperty("MONTH_NAME_FULL", sdfMonthNameFull.format(date));
props.setProperty("DAY", getCalendarValue(calendar, Calendar.DAY_OF_MONTH));
props.setProperty("HOUR", getCalendarValue(calendar, Calendar.HOUR_OF_DAY));
props.setProperty("MINUTE", getCalendarValue(calendar, Calendar.MINUTE));
diff --git a/platform/lang-impl/src/com/intellij/ide/todo/TodoTreeBuilder.java b/platform/lang-impl/src/com/intellij/ide/todo/TodoTreeBuilder.java
index a0c783cfaf65..156ee77bd161 100644
--- a/platform/lang-impl/src/com/intellij/ide/todo/TodoTreeBuilder.java
+++ b/platform/lang-impl/src/com/intellij/ide/todo/TodoTreeBuilder.java
@@ -539,6 +539,7 @@ public abstract class TodoTreeBuilder extends AbstractTreeBuilder {
return null;
}
Object[] children = getTreeStructure().getChildElements(parent);
+ Arrays.sort(children, getUi().getNodeDescriptorComparator());
int idx = -1;
for (int i = 0; i < children.length; i++) {
if (obj.equals(children[i])) {
@@ -584,6 +585,7 @@ public abstract class TodoTreeBuilder extends AbstractTreeBuilder {
return null;
}
Object[] children = getTreeStructure().getChildElements(parent);
+ Arrays.sort(children, getUi().getNodeDescriptorComparator());
int idx = -1;
for (int i = 0; i < children.length; i++) {
if (obj.equals(children[i])) {
diff --git a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java
index 822ec3a804dc..2285504fe806 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java
@@ -228,18 +228,20 @@ public class FileStructurePopup implements Disposable {
for (ObjectWithWeight p : paths) {
final Object last = ((TreePath)p.node).getLastPathComponent();
final List elements = new ArrayList();
- FilteringTreeStructure.FilteringNode node =
- (FilteringTreeStructure.FilteringNode)((DefaultMutableTreeNode)last).getUserObject();
- while (node != null) {
- elements.add(getPsi(node));
- node = node.getParentNode();
- }
- final int size = ContainerUtil.intersection(parents, elements).size();
- if (size > max) {
- max = size;
- cur = p.node;
- } else if (size == max && size == parents.size()) {
- cur = p.node;
+ final Object object = ((DefaultMutableTreeNode)last).getUserObject();
+ if (object instanceof FilteringTreeStructure.FilteringNode) {
+ FilteringTreeStructure.FilteringNode node = (FilteringTreeStructure.FilteringNode)object;
+ while (node != null) {
+ elements.add(getPsi(node));
+ node = node.getParentNode();
+ }
+ final int size = ContainerUtil.intersection(parents, elements).size();
+ if (size > max) {
+ max = size;
+ cur = p.node;
+ } else if (size == max && size == parents.size()) {
+ cur = p.node;
+ }
}
}
diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/SerializedStubTree.java b/platform/lang-impl/src/com/intellij/psi/stubs/SerializedStubTree.java
index abaf63828b69..d7423c8420b2 100644
--- a/platform/lang-impl/src/com/intellij/psi/stubs/SerializedStubTree.java
+++ b/platform/lang-impl/src/com/intellij/psi/stubs/SerializedStubTree.java
@@ -19,7 +19,8 @@
*/
package com.intellij.psi.stubs;
-import java.io.ByteArrayInputStream;
+import com.intellij.util.io.UnsyncByteArrayInputStream;
+
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
@@ -45,7 +46,7 @@ public class SerializedStubTree {
}
public StubElement getStub() {
- return SerializationManager.getInstance().deserialize(new ByteArrayInputStream(myBytes));
+ return SerializationManager.getInstance().deserialize(new UnsyncByteArrayInputStream(myBytes));
}
public boolean equals(final Object that) {
diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java
index 6997d30dbed7..ced3ab62d05d 100644
--- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java
+++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java
@@ -3570,6 +3570,10 @@ public class AbstractTreeUi {
}
}
+ public Comparator getNodeDescriptorComparator() {
+ return myNodeDescriptorComparator;
+ }
+
private void disposeNode(DefaultMutableTreeNode node) {
TreeNode parent = node.getParent();
if (parent instanceof DefaultMutableTreeNode) {
diff --git a/platform/platform-api/src/com/intellij/notification/Notification.java b/platform/platform-api/src/com/intellij/notification/Notification.java
index 91c23432ba70..36ad4145c9e7 100644
--- a/platform/platform-api/src/com/intellij/notification/Notification.java
+++ b/platform/platform-api/src/com/intellij/notification/Notification.java
@@ -18,6 +18,8 @@ package com.intellij.notification;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.Balloon;
+import com.intellij.openapi.ui.popup.JBPopupAdapter;
+import com.intellij.openapi.ui.popup.LightweightWindowEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -97,6 +99,11 @@ public class Notification {
public void expire() {
NotificationsManager.getNotificationsManager().expire(this);
+ hideBalloon();
+ myExpired = true;
+ }
+
+ public void hideBalloon() {
if (myBalloonRef != null) {
final Balloon balloon = myBalloonRef.get();
if (balloon != null) {
@@ -104,15 +111,20 @@ public class Notification {
}
myBalloonRef = null;
}
- myExpired = true;
}
- public void setBalloon(@Nullable final Balloon balloon) {
- if (balloon != null) {
- myBalloonRef = new WeakReference(balloon);
- } else {
- myBalloonRef = null;
- }
+ public void setBalloon(@NotNull final Balloon balloon) {
+ hideBalloon();
+ myBalloonRef = new WeakReference(balloon);
+ balloon.addListener(new JBPopupAdapter() {
+ @Override
+ public void onClosed(LightweightWindowEvent event) {
+ WeakReference ref = myBalloonRef;
+ if (ref != null && ref.get() == balloon) {
+ myBalloonRef = null;
+ }
+ }
+ });
}
@Nullable
diff --git a/platform/platform-api/src/com/intellij/ui/TableScrollingUtil.java b/platform/platform-api/src/com/intellij/ui/TableScrollingUtil.java
index d3fd4590a245..e3993f86206d 100644
--- a/platform/platform-api/src/com/intellij/ui/TableScrollingUtil.java
+++ b/platform/platform-api/src/com/intellij/ui/TableScrollingUtil.java
@@ -272,6 +272,17 @@ public class TableScrollingUtil {
moveEnd(list);
}
}.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0)), list);
+
+ new AnAction() {
+ public void actionPerformed(AnActionEvent e) {
+ moveHome(list);
+ }
+ }.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0)), list);
+ new AnAction() {
+ public void actionPerformed(AnActionEvent e) {
+ moveEnd(list);
+ }
+ }.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_END, 0)), list);
}
}
diff --git a/platform/platform-api/src/com/intellij/ui/docking/DockContainer.java b/platform/platform-api/src/com/intellij/ui/docking/DockContainer.java
index f599a1d8bcd2..25fb02896813 100644
--- a/platform/platform-api/src/com/intellij/ui/docking/DockContainer.java
+++ b/platform/platform-api/src/com/intellij/ui/docking/DockContainer.java
@@ -30,7 +30,7 @@ public interface DockContainer extends Disposable, Activatable {
RelativeRectangle getAcceptArea();
boolean canAccept(DockableContent content, RelativePoint point);
- JComponent getComponent();
+ JComponent getContainerComponent();
void add(DockableContent content, RelativePoint dropTarget);
diff --git a/platform/platform-api/src/com/intellij/ui/docking/DockContainerFactory.java b/platform/platform-api/src/com/intellij/ui/docking/DockContainerFactory.java
index 3dcc059e3de2..6e7e581c61d7 100644
--- a/platform/platform-api/src/com/intellij/ui/docking/DockContainerFactory.java
+++ b/platform/platform-api/src/com/intellij/ui/docking/DockContainerFactory.java
@@ -20,7 +20,7 @@ import org.jdom.Element;
public interface DockContainerFactory extends Disposable {
- DockContainer createContainer();
+ DockContainer createContainer(DockableContent content);
interface Persistent extends DockContainerFactory {
diff --git a/platform/platform-api/src/com/intellij/ui/tabs/TabsListener.java b/platform/platform-api/src/com/intellij/ui/tabs/TabsListener.java
index ff798575ac6a..a9bba15c4d37 100644
--- a/platform/platform-api/src/com/intellij/ui/tabs/TabsListener.java
+++ b/platform/platform-api/src/com/intellij/ui/tabs/TabsListener.java
@@ -22,12 +22,18 @@ public interface TabsListener {
void beforeSelectionChanged(TabInfo oldSelection, TabInfo newSelection);
+ void tabsMoved();
+
class Adapter implements TabsListener {
public void selectionChanged(TabInfo oldSelection, TabInfo newSelection) {
}
public void beforeSelectionChanged(TabInfo oldSelection, TabInfo newSelection) {
}
+
+ @Override
+ public void tabsMoved() {
+ }
}
}
diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java
index f4ae28f9729e..9dcd06843d5a 100644
--- a/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java
+++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java
@@ -30,7 +30,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
-class ActionPanel extends NonOpaquePanel {
+public class ActionPanel extends NonOpaquePanel {
private final ActionGroup myGroup;
private final List myButtons = new ArrayList();
diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java
index 94c737a0ff74..70428d60ca50 100644
--- a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java
+++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java
@@ -253,6 +253,9 @@ class DragHelper extends MouseDragHelper {
myDragRec = null;
myTabs.resetTabsCache();
+ if (!willDragOutStart) {
+ myTabs.fireTabsMoved();
+ }
myTabs.relayout(true, false);
myTabs.revalidate();
diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java
index 3484decdc008..6d49d1718d60 100644
--- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java
+++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java
@@ -163,7 +163,7 @@ public class JBTabsImpl extends JComponent
private boolean myOwnSwitchProvider = true;
private SwitchProvider mySwitchDelegate;
- private TabInfo myDropInfo;
+ protected TabInfo myDropInfo;
private int myDropInfoIndex;
private TabInfo myOldSelection;
@@ -629,7 +629,7 @@ public class JBTabsImpl extends JComponent
}
info.getChangeSupport().addPropertyChangeListener(this);
- final TabLabel label = new TabLabel(this, info);
+ final TabLabel label = createTabLabel(info);
myInfo2Label.put(info, label);
if (!isDropTarget) {
@@ -674,6 +674,9 @@ public class JBTabsImpl extends JComponent
return info;
}
+ protected TabLabel createTabLabel(TabInfo info) {
+ return new TabLabel(this, info);
+ }
@NotNull
public TabInfo addTab(TabInfo info) {
@@ -832,6 +835,14 @@ public class JBTabsImpl extends JComponent
}
}
+ void fireTabsMoved() {
+ for (TabsListener eachListener : myTabListeners) {
+ if (eachListener != null) {
+ eachListener.tabsMoved();
+ }
+ }
+ }
+
private ActionCallback requestFocus(final JComponent toFocus) {
if (toFocus == null) return new ActionCallback.Done();
@@ -1745,17 +1756,18 @@ public class JBTabsImpl extends JComponent
return myInfo2Label.get(getSelectedInfo());
}
- static class ShapeInfo {
- ShapeTransform path;
- ShapeTransform fillPath;
- ShapeTransform labelPath;
- int labelBottomY;
- int labelTopY;
- int labelLeftX;
- int labelRightX;
- Insets insets;
- Color from;
- Color to;
+ protected static class ShapeInfo {
+ public ShapeInfo() {}
+ public ShapeTransform path;
+ public ShapeTransform fillPath;
+ public ShapeTransform labelPath;
+ public int labelBottomY;
+ public int labelTopY;
+ public int labelLeftX;
+ public int labelRightX;
+ public Insets insets;
+ public Color from;
+ public Color to;
}
@@ -2977,7 +2989,7 @@ public class JBTabsImpl extends JComponent
}
}
- public static Rectangle layout(JComponent c, Rectangle bounds) {
+ public Rectangle layout(JComponent c, Rectangle bounds) {
final Rectangle now = c.getBounds();
if (!bounds.equals(now)) {
c.setBounds(bounds);
@@ -2987,7 +2999,7 @@ public class JBTabsImpl extends JComponent
return bounds;
}
- public static Rectangle layout(JComponent c, int x, int y, int width, int height) {
+ public Rectangle layout(JComponent c, int x, int y, int width, int height) {
return layout(c, new Rectangle(x, y, width, height));
}
diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java
index 54dd2366b569..63237e5e51b8 100644
--- a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java
+++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java
@@ -43,7 +43,7 @@ import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
public class TabLabel extends JPanel {
- private final SimpleColoredComponent myLabel = new SimpleColoredComponent() {
+ protected final SimpleColoredComponent myLabel = new SimpleColoredComponent() {
@Override
protected boolean shouldDrawMacShadow() {
return SystemInfo.isMac;
@@ -54,7 +54,7 @@ public class TabLabel extends JPanel {
private Icon myOverlayedIcon;
private final TabInfo myInfo;
- private ActionPanel myActionPanel;
+ protected ActionPanel myActionPanel;
private boolean myCentered;
private final Wrapper myLabelPlaceholder = new Wrapper();
@@ -224,7 +224,7 @@ public class TabLabel extends JPanel {
});
}
- private int getNonSelectedOffset() {
+ protected int getNonSelectedOffset() {
if (myTabs.isEditorTabs()) {
int offset = (TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT / 2);
if (myTabs.isSingleRow()) {
@@ -237,7 +237,7 @@ public class TabLabel extends JPanel {
return 2;
}
- private int getSelectedOffset() {
+ protected int getSelectedOffset() {
return myTabs.isEditorTabs() ? -(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT / 2) + 1 : 1;
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/UndoRedoAction.java b/platform/platform-impl/src/com/intellij/ide/actions/UndoRedoAction.java
index 0fc43b2ee49a..0d09446cef7a 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/UndoRedoAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/UndoRedoAction.java
@@ -53,7 +53,11 @@ public abstract class UndoRedoAction extends DumbAwareAction {
}
UndoManager undoManager = getUndoManager(editor, dataContext);
- presentation.setEnabled(undoManager != null && isAvailable(editor, undoManager));
+ if (undoManager == null) {
+ presentation.setEnabled(false);
+ return;
+ }
+ presentation.setEnabled(isAvailable(editor, undoManager));
Pair pair = getActionNameAndDescription(editor, undoManager);
diff --git a/platform/platform-impl/src/com/intellij/idea/SocketLock.java b/platform/platform-impl/src/com/intellij/idea/SocketLock.java
index d8ab49cb1712..ca9ebb6a06a2 100644
--- a/platform/platform-impl/src/com/intellij/idea/SocketLock.java
+++ b/platform/platform-impl/src/com/intellij/idea/SocketLock.java
@@ -162,13 +162,13 @@ public class SocketLock {
try {
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeUTF(ACTIVATE_COMMAND + StringUtil.join(args, "\0"));
+ out.flush();
String response = in.readUTF();
if (response.equals("ok")) {
return ActivateStatus.ACTIVATED;
}
}
catch(IOException e) {
-
}
return ActivateStatus.CANNOT_ACTIVATE;
}
diff --git a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
index 81e873ae3041..e30f09e9611a 100644
--- a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
+++ b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
@@ -111,7 +111,17 @@ public class StartupUtil {
}
if (activateStatus != SocketLock.ActivateStatus.NO_INSTANCE) {
- showError("Error", "Only one instance of " + ApplicationNamesInfo.getInstance().getFullProductName() + " can be run at a time.");
+ if (isHeadless()) { //team server inspections
+ System.out.println("Only one instance of " + ApplicationNamesInfo.getInstance().getFullProductName() + " can be run at a time.");
+ return false;
+ }
+ if (activateStatus == SocketLock.ActivateStatus.CANNOT_ACTIVATE) {
+ JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
+ "Only one instance of " + ApplicationNamesInfo.getInstance().getFullProductName() +
+ " can be run at a time.",
+ "Error",
+ JOptionPane.INFORMATION_MESSAGE);
+ }
return false;
}
diff --git a/platform/platform-impl/src/com/intellij/notification/EventLog.java b/platform/platform-impl/src/com/intellij/notification/EventLog.java
index 24552d8947ce..2d1e660c2c6d 100644
--- a/platform/platform-impl/src/com/intellij/notification/EventLog.java
+++ b/platform/platform-impl/src/com/intellij/notification/EventLog.java
@@ -133,6 +133,7 @@ public class EventLog implements Notifications {
mainText += content;
}
+ mainText = StringUtil.replace(mainText, " ", " ");
int nlIndex = eolIndex(mainText);
if (nlIndex >= 0) {
mainText = mainText.substring(0, nlIndex);
@@ -329,6 +330,7 @@ public class EventLog implements Notifications {
group.add(new DumbAwareAction("Mark all as read", "Mark all unread notifications as read", IconLoader.getIcon("/general/reset.png")) {
@Override
public void update(AnActionEvent e) {
+ if (project.isDisposed()) return;
e.getPresentation().setEnabled(!getProjectComponent(project).myProjectModel.getNotifications().isEmpty());
}
diff --git a/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java b/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java
index 6870f9459f21..50968d23171b 100644
--- a/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java
@@ -314,13 +314,6 @@ public class NotificationsManagerImpl extends NotificationsManager implements No
.setHideOnKeyOutside(hideOnClickOutside).setHideOnFrameResize(false);
final Balloon balloon = builder.createBalloon();
- balloon.addListener(new JBPopupAdapter() {
- @Override
- public void onClosed(LightweightWindowEvent event) {
- notification.setBalloon(null);
- }
- });
-
notification.setBalloon(balloon);
return balloon;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/CommandProcessorImpl.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/CommandProcessorImpl.java
index 71494e542fac..33596a4f619d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/command/impl/CommandProcessorImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/CommandProcessorImpl.java
@@ -57,6 +57,11 @@ public class CommandProcessorImpl extends CommandProcessorEx {
myUndoConfirmationPolicy = undoConfirmationPolicy;
myDocument = document;
}
+
+ @Override
+ public String toString() {
+ return "'" + myName + "', group: '" + myGroupId + "'";
+ }
}
private CommandDescriptor myCurrentCommand = null;
@@ -219,7 +224,8 @@ public class CommandProcessorImpl extends CommandProcessorEx {
}
public void leaveModal() {
- CommandLog.LOG.assertTrue(myCurrentCommand == null);
+ CommandLog.LOG.assertTrue(myCurrentCommand == null, "Command must not run: " + String.valueOf(myCurrentCommand));
+
myCurrentCommand = myInterruptedCommands.pop();
if (myCurrentCommand != null) {
fireCommandStarted();
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/DockableEditorContainerFactory.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/DockableEditorContainerFactory.java
index f41ac78fee30..e2340d7f1489 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/DockableEditorContainerFactory.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/DockableEditorContainerFactory.java
@@ -22,6 +22,7 @@ import com.intellij.openapi.wm.IdeFrame;
import com.intellij.ui.docking.DockContainer;
import com.intellij.ui.docking.DockContainerFactory;
import com.intellij.ui.docking.DockManager;
+import com.intellij.ui.docking.DockableContent;
import org.jdom.Element;
public class DockableEditorContainerFactory implements DockContainerFactory.Persistent {
@@ -39,7 +40,7 @@ public class DockableEditorContainerFactory implements DockContainerFactory.Pers
}
@Override
- public DockContainer createContainer() {
+ public DockContainer createContainer(DockableContent content) {
return createContainer(false);
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/DockableEditorTabbedContainer.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/DockableEditorTabbedContainer.java
index 2eacfab54920..11c212bc71ca 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/DockableEditorTabbedContainer.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/DockableEditorTabbedContainer.java
@@ -187,7 +187,7 @@ public class DockableEditorTabbedContainer implements DockContainer.Persistent {
}
@Override
- public JComponent getComponent() {
+ public JComponent getContainerComponent() {
return mySplitters;
}
@@ -196,7 +196,7 @@ public class DockableEditorTabbedContainer implements DockContainer.Persistent {
}
public void close(VirtualFile file) {
- mySplitters.getCurrentWindow().closeFile(file);
+ mySplitters.closeFile(file, false);
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java
index 776e61846800..d64dd34acb6c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java
@@ -586,6 +586,31 @@ public class EditorsSplitters extends JPanel {
return null;
}
+ void closeFile(VirtualFile file, boolean moveFocus) {
+ final List windows = findWindows(file);
+ if (!windows.isEmpty()) {
+ final VirtualFile nextFile = findNextFile(file);
+ for (final EditorWindow window : windows) {
+ LOG.assertTrue(window.getSelectedEditor() != null);
+ window.closeFile(file, false, moveFocus);
+ if (window.getTabCount() == 0 && nextFile != null) {
+ EditorWithProviderComposite newComposite = myManager.newEditorComposite(nextFile);
+ window.setEditor(newComposite, moveFocus); // newComposite can be null
+ }
+ }
+ // cleanup windows with no tabs
+ for (final EditorWindow window : windows) {
+ if (window.isDisposed()) {
+ // call to window.unsplit() which might make its sibling disposed
+ continue;
+ }
+ if (window.getTabCount() == 0) {
+ window.unsplit(false);
+ }
+ }
+ }
+ }
+
private final class MyFocusTraversalPolicy extends IdeFocusTraversalPolicy {
public final Component getDefaultComponentImpl(final Container focusCycleRoot) {
if (myCurrentWindow != null) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java
index 582716f561ed..f1881c6cb742 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java
@@ -556,33 +556,12 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
assertDispatchThread();
runChange(new FileEditorManagerChange() {
public void run(EditorsSplitters splitters) {
- final List windows = splitters.findWindows(file);
- if (!windows.isEmpty()) {
- final VirtualFile nextFile = splitters.findNextFile(file);
- for (final EditorWindow window : windows) {
- LOG.assertTrue(window.getSelectedEditor() != null);
- window.closeFile(file, false, moveFocus);
- if (window.getTabCount() == 0 && nextFile != null) {
- EditorWithProviderComposite newComposite = newEditorComposite(nextFile);
- window.setEditor(newComposite, moveFocus); // newComposite can be null
- }
- }
- // cleanup windows with no tabs
- for (final EditorWindow window : windows) {
- if (window.isDisposed()) {
- // call to window.unsplit() which might make its sibling disposed
- continue;
- }
- if (window.getTabCount() == 0) {
- window.unsplit(false);
- }
- }
- }
+ splitters.closeFile(file, moveFocus);
}
}, closeAllCopies ? null : getActiveSplitters(true).getResult());
}
-//-------------------------------------- Open File ----------------------------------------
+ //-------------------------------------- Open File ----------------------------------------
@NotNull
public Pair openFileWithProviders(@NotNull final VirtualFile file,
@@ -865,7 +844,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
@Nullable
- private EditorWithProviderComposite newEditorComposite(final VirtualFile file) {
+ EditorWithProviderComposite newEditorComposite(final VirtualFile file) {
if (file == null) {
return null;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java
index c9f1f5c6ef0e..b5eca8b1f0e4 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java
@@ -220,11 +220,11 @@ public class GlassPaneDialogWrapperPeer extends DialogWrapperPeer implements Foc
}
public boolean isVisible() {
- return myDialog.isVisible();
+ return myDialog != null && myDialog.isVisible();
}
public boolean isShowing() {
- return myDialog.isShowing();
+ return myDialog != null && myDialog.isShowing();
}
public void setSize(final int width, final int height) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java
index 38eeed18a5df..915ca59e82b8 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java
@@ -188,6 +188,7 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
return ioFile;
}
+ // todo[r.sh] use NIO2 API after migration to JDK 7
// returns -1 if could not get attributes
@MagicConstant(flags = {BA_EXISTS, BA_REGULAR, BA_DIRECTORY, BA_HIDDEN})
private static int getBooleanAttributes(@NotNull File f) {
@@ -196,8 +197,7 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
Object flags = JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD.invoke(JAVA_IO_FILESYSTEM, f);
return ((Integer)flags).intValue();
}
- catch (Exception ignored) {
- }
+ catch (Exception ignored) { }
}
return -1;
}
@@ -535,7 +535,9 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
public byte[] contentsToByteArray(@NotNull final VirtualFile file) throws IOException {
final FileInputStream stream = new FileInputStream(convertToIOFileAndCheck(file));
try {
- return FileUtil.loadBytes(stream, (int)file.getLength());
+ final int length = (int)file.getLength();
+ assert length >= 0 : file;
+ return FileUtil.loadBytes(stream, length);
}
finally {
stream.close();
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java
index 9623d30cec49..9a2de59babeb 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -508,7 +508,9 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
}
else {
try {
- return FileUtil.loadBytes(contentStream, (int)file.getLength());
+ final int length = (int)file.getLength();
+ assert length >= 0 : file;
+ return FileUtil.loadBytes(contentStream, length);
}
catch (IOException e) {
throw FSRecords.handleError(e);
diff --git a/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java b/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java
index 9f9700fc1987..b490ba433f58 100644
--- a/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java
@@ -122,7 +122,7 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo
@Override
public IdeFrame getIdeFrame(DockContainer container) {
- Component parent = UIUtil.findUltimateParent(container.getComponent());
+ Component parent = UIUtil.findUltimateParent(container.getContainerComponent());
if (parent instanceof IdeFrame) {
return (IdeFrame)parent;
}
@@ -143,7 +143,7 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo
if (c == null) return null;
for (DockContainer eachContainer : myContainers) {
- if (SwingUtilities.isDescendingFrom(c, eachContainer.getComponent())) {
+ if (SwingUtilities.isDescendingFrom(c, eachContainer.getContainerComponent())) {
return eachContainer;
}
}
@@ -152,7 +152,7 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo
if (parent == null) return null;
for (DockContainer eachContainer : myContainers) {
- if (parent == UIUtil.findUltimateParent(eachContainer.getComponent())) {
+ if (parent == UIUtil.findUltimateParent(eachContainer.getContainerComponent())) {
return eachContainer;
}
}
@@ -354,8 +354,8 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo
return myFactories.get(type);
}
- private void createNewDockContainerFor(DockableContent content, RelativePoint point) {
- DockContainer container = getFactory(content.getDockContainerType()).createContainer();
+ public void createNewDockContainerFor(DockableContent content, RelativePoint point) {
+ DockContainer container = getFactory(content.getDockContainerType()).createContainer(content);
register(container);
final DockWindow window = createWindowFor(null, container);
@@ -424,7 +424,7 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo
center.add(myNorthPanel, BorderLayout.NORTH);
myDockContentUiContainer = new NonOpaquePanel(new BorderLayout());
- myDockContentUiContainer.add(myContainer.getComponent(), BorderLayout.CENTER);
+ myDockContentUiContainer.add(myContainer.getContainerComponent(), BorderLayout.CENTER);
center.add(myDockContentUiContainer, BorderLayout.CENTER);
myUiContainer.add(center, BorderLayout.CENTER);
diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties
index 4b218b9198be..fba31187d44c 100644
--- a/platform/platform-resources-en/src/messages/ActionsBundle.properties
+++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties
@@ -227,7 +227,7 @@ group.reopen.mac.text=Open _Recent
group.$LRU.description=List of recently opened projects
action.CloseProject.text=Close Pro_ject
action.CloseProject.description=Close current project
-action.ShowSettings.text=Se_ttings
+action.ShowSettings.text=Se_ttings...
action.ShowSettings.description=Configure application settings
action.ShowProjectStructureSettings.text=Pro_ject Structure...
action.ShowProjectStructureSettings.description=Configure project structure
@@ -1147,7 +1147,7 @@ group.EditSelectGroup.text=Editor Select Actions
group.EditCreateDeleteGroup.text=Editor Create/Delete Actions
group.CutCopyPasteGroup.text=Cut/Copy/Paste Actions
group.EditSelectWordGroup.text=Select Word Actions
-group.EditBookmarksGroup.text=Bookmarks
+group.EditBookmarksGroup.text=Boo_kmarks
group.OpenProjectGroup.text=Open Project Actions
group.EditSmartGroup.text=Edit Code Actions
group.ProjectViewGroup.text=Project View Actions
diff --git a/platform/platform-resources-en/src/messages/ExecutionBundle.properties b/platform/platform-resources-en/src/messages/ExecutionBundle.properties
index 3be53cf875b1..0181271196aa 100644
--- a/platform/platform-resources-en/src/messages/ExecutionBundle.properties
+++ b/platform/platform-resources-en/src/messages/ExecutionBundle.properties
@@ -133,6 +133,8 @@ tests.passed.with.warnings.message=Tests passed (with warnings)
junit.run.hide.passed.action.name=Hide Passed
junit.run.hide.passed.action.description=Hide passed tests
junit.runing.info.track.test.action.name=Track Running Test
+junit.runing.info.sort.alphabetically.action.name=Sort Alphabetically
+junit.runing.info.sort.alphabetically.action.description=Sort tests or suites alphabetically
junit.runing.info.track.test.action.description=Select currently running test in tree
junit.runing.info.collapse.test.action.name=Collapse all test suites
junit.runing.info.expand.test.action.name=Expand all test suites
diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml
index 83c2df79e895..12a87ccd6ed0 100644
--- a/platform/platform-resources/src/idea/LangActions.xml
+++ b/platform/platform-resources/src/idea/LangActions.xml
@@ -728,18 +728,14 @@
-
-
-
+
+
+