Merge remote-tracking branch 'origin/master'

This commit is contained in:
anna
2012-02-21 08:45:59 +01:00
84 changed files with 2577 additions and 999 deletions
@@ -280,7 +280,8 @@ public class CompileServerManager implements ApplicationComponent{
continue;
}
final RequestFuture future = submitCompilationTask(project, false, true, Collections.<String>emptyList(), Collections.<String>emptyList(),
Collections.<String>emptyList(), new AutoMakeResponseHandler(project));
Collections.<String>emptyList(), Collections.<String, String>emptyMap(), new AutoMakeResponseHandler(project)
);
if (future != null) {
futures.add(future);
synchronized (myAutomakeFutures) {
@@ -312,9 +313,10 @@ public class CompileServerManager implements ApplicationComponent{
}
@Nullable
public RequestFuture submitCompilationTask(final Project project, final boolean isRebuild, final boolean isMake,
final Collection<String> modules, final Collection<String> artifacts,
final Collection<String> paths, final JpsServerResponseHandler handler) {
public RequestFuture submitCompilationTask(final Project project, final boolean isRebuild, final boolean isMake,
final Collection<String> modules, final Collection<String> artifacts,
final Collection<String> paths,
final Map<String, String> userData, final JpsServerResponseHandler handler) {
final String projectId = project.getLocation();
final Ref<RequestFuture> futureRef = new Ref<RequestFuture>(null);
final RunnableFuture future = myTaskExecutor.submit(new Runnable() {
@@ -324,7 +326,7 @@ public class CompileServerManager implements ApplicationComponent{
if (client != null) {
final RequestFuture requestFuture = isRebuild ?
client.sendRebuildRequest(projectId, handler) :
client.sendCompileRequest(isMake, projectId, modules, artifacts, paths, handler);
client.sendCompileRequest(isMake, projectId, modules, artifacts, paths, userData, handler);
futureRef.set(requestFuture);
}
else {
@@ -430,7 +430,24 @@ public class CompileDriver {
final CompileServerManager csManager = CompileServerManager.getInstance();
final MessageBus messageBus = myProject.getMessageBus();
csManager.cancelAutoMakeTasks(myProject);
return csManager.submitCompilationTask(myProject, compileContext.isRebuild(), compileContext.isMake(), moduleNames, artifactNames, paths, new JpsServerResponseHandler() {
final CompileScope scope = compileContext.getCompileScope();
final Map<String, String> userData;
// need to pass scope's user data to server
if (scope instanceof UserDataHolderBase) { // hack
userData = new HashMap<String, String>();
((UserDataHolderBase)scope).copyUserDataTo(new UserDataHolderBase() {
@Override
public <T> void putUserData(@NotNull Key<T> key, @Nullable T value) {
final String _key = key.toString();
final String _value = value != null? value.toString() : "";
userData.put(_key, _value);
}
});
}
else {
userData = Collections.emptyMap();
}
return csManager.submitCompilationTask(myProject, compileContext.isRebuild(), compileContext.isMake(), moduleNames, artifactNames, paths, userData, new JpsServerResponseHandler() {
@Override
public void handleCompileMessage(JpsRemoteProto.Message.Response.CompileMessage compilerMessage) {
@@ -50,6 +50,7 @@ public class ResourceCompiler implements TranslatingCompiler {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.resourceCompiler.ResourceCompiler");
private final Project myProject;
private final CompilerConfiguration myConfiguration;
private final ResourceCompilerExtension[] myResourceCompilerExtensions = ResourceCompilerExtension.EP_NAME.getExtensions();
private static final FileTypeManager FILE_TYPE_MANAGER = FileTypeManager.getInstance();
public ResourceCompiler(Project project, CompilerConfiguration compilerConfiguration) {
@@ -68,6 +69,11 @@ public class ResourceCompiler implements TranslatingCompiler {
}
public boolean isCompilableFile(VirtualFile file, CompileContext context) {
final Module module = context.getModuleByFile(file);
if (module != null && skipStandardResourceCompiler(module)) {
return false;
}
return !StdFileTypes.JAVA.equals(file.getFileType()) && myConfiguration.isResourceFile(file);
}
@@ -81,8 +87,6 @@ public class ResourceCompiler implements TranslatingCompiler {
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
OUTER:
for (final VirtualFile file : files) {
if (context.getProgressIndicator().isCanceled()) {
break;
@@ -91,13 +95,6 @@ public class ResourceCompiler implements TranslatingCompiler {
if (module == null) {
continue; // looks like file invalidated
}
for (ResourceCompilerExtension extension : ResourceCompilerExtension.EP_NAME.getExtensions()) {
if (extension.skipStandardResourceCompiler(module)) {
continue OUTER;
}
}
final VirtualFile fileRoot = MakeUtil.getSourceRoot(context, module, file);
if (fileRoot == null) {
continue;
@@ -164,6 +161,15 @@ public class ResourceCompiler implements TranslatingCompiler {
context.getProgressIndicator().popState();
}
private boolean skipStandardResourceCompiler(final Module module) {
for (ResourceCompilerExtension extension : myResourceCompilerExtensions) {
if (extension.skipStandardResourceCompiler(module)) {
return true;
}
}
return false;
}
private static void addToMap(Map<String, Collection<OutputItem>> map, String outputDir, OutputItem item) {
Collection<OutputItem> list = map.get(outputDir);
if (list == null) {
@@ -162,10 +162,7 @@ public class JavaExecutionUtil {
public static String getShortClassName(final String fqName) {
if (fqName == null) return "";
final int dotIndex = fqName.lastIndexOf('.');
if (dotIndex == fqName.length() - 1) return "";
if (dotIndex < 0) return fqName;
return fqName.substring(dotIndex + 1, fqName.length());
return StringUtil.getShortName(fqName);
}
public static void showExecutionErrorMessage(final ExecutionException e, final String title, final Project project) {
@@ -10,6 +10,11 @@ message Message {
required sint64 least_sig_bits = 2;
}
message KeyValuePair {
required string key = 1;
required string value = 2;
}
enum Type {
REQUEST = 1;
RESPONSE = 2;
@@ -44,6 +49,7 @@ message Message {
repeated string module_name = 3;
repeated string file_path = 4;
repeated string artifact_name = 5;
repeated KeyValuePair builder_parameter = 6;
}
message ShutdownCommand {
@@ -56,11 +62,6 @@ message Message {
message SetupCommand {
message PathVariable {
required string name = 1;
required string value = 2;
}
message GlobalLibrary {
required string name = 1;
optional string homePath = 2;
@@ -69,7 +70,7 @@ message Message {
repeated string path = 5;
}
repeated PathVariable path_variable = 1;
repeated KeyValuePair path_variable = 1;
repeated GlobalLibrary global_library = 2;
optional string global_encoding = 3;
}
@@ -359,6 +359,305 @@ public final class JpsRemoteProto {
// @@protoc_insertion_point(class_scope:org.jetbrains.jpsservice.Message.UUID)
}
public static final class KeyValuePair extends
com.google.protobuf.GeneratedMessageLite {
// Use KeyValuePair.newBuilder() to construct.
private KeyValuePair() {
initFields();
}
private KeyValuePair(boolean noInit) {}
private static final KeyValuePair defaultInstance;
public static KeyValuePair getDefaultInstance() {
return defaultInstance;
}
public KeyValuePair getDefaultInstanceForType() {
return defaultInstance;
}
// required string key = 1;
public static final int KEY_FIELD_NUMBER = 1;
private boolean hasKey;
private java.lang.String key_ = "";
public boolean hasKey() { return hasKey; }
public java.lang.String getKey() { return key_; }
// required string value = 2;
public static final int VALUE_FIELD_NUMBER = 2;
private boolean hasValue;
private java.lang.String value_ = "";
public boolean hasValue() { return hasValue; }
public java.lang.String getValue() { return value_; }
private void initFields() {
}
public final boolean isInitialized() {
if (!hasKey) return false;
if (!hasValue) return false;
return true;
}
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
getSerializedSize();
if (hasKey()) {
output.writeString(1, getKey());
}
if (hasValue()) {
output.writeString(2, getValue());
}
}
private int memoizedSerializedSize = -1;
public int getSerializedSize() {
int size = memoizedSerializedSize;
if (size != -1) return size;
size = 0;
if (hasKey()) {
size += com.google.protobuf.CodedOutputStream
.computeStringSize(1, getKey());
}
if (hasValue()) {
size += com.google.protobuf.CodedOutputStream
.computeStringSize(2, getValue());
}
memoizedSerializedSize = size;
return size;
}
public static org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data).buildParsed();
}
public static org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data, extensionRegistry)
.buildParsed();
}
public static org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data).buildParsed();
}
public static org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data, extensionRegistry)
.buildParsed();
}
public static org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair parseFrom(java.io.InputStream input)
throws java.io.IOException {
return newBuilder().mergeFrom(input).buildParsed();
}
public static org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return newBuilder().mergeFrom(input, extensionRegistry)
.buildParsed();
}
public static org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
Builder builder = newBuilder();
if (builder.mergeDelimitedFrom(input)) {
return builder.buildParsed();
} else {
return null;
}
}
public static org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
Builder builder = newBuilder();
if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
return builder.buildParsed();
} else {
return null;
}
}
public static org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return newBuilder().mergeFrom(input).buildParsed();
}
public static org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return newBuilder().mergeFrom(input, extensionRegistry)
.buildParsed();
}
public static Builder newBuilder() { return Builder.create(); }
public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder(org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair prototype) {
return newBuilder().mergeFrom(prototype);
}
public Builder toBuilder() { return newBuilder(this); }
public static final class Builder extends
com.google.protobuf.GeneratedMessageLite.Builder<
org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair, Builder> {
private org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair result;
// Construct using org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair.newBuilder()
private Builder() {}
private static Builder create() {
Builder builder = new Builder();
builder.result = new org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair();
return builder;
}
protected org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair internalGetResult() {
return result;
}
public Builder clear() {
if (result == null) {
throw new IllegalStateException(
"Cannot call clear() after build().");
}
result = new org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair();
return this;
}
public Builder clone() {
return create().mergeFrom(result);
}
public org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair getDefaultInstanceForType() {
return org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair.getDefaultInstance();
}
public boolean isInitialized() {
return result.isInitialized();
}
public org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair build() {
if (result != null && !isInitialized()) {
throw newUninitializedMessageException(result);
}
return buildPartial();
}
private org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair buildParsed()
throws com.google.protobuf.InvalidProtocolBufferException {
if (!isInitialized()) {
throw newUninitializedMessageException(
result).asInvalidProtocolBufferException();
}
return buildPartial();
}
public org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair buildPartial() {
if (result == null) {
throw new IllegalStateException(
"build() has already been called on this Builder.");
}
org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair returnMe = result;
result = null;
return returnMe;
}
public Builder mergeFrom(org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair other) {
if (other == org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair.getDefaultInstance()) return this;
if (other.hasKey()) {
setKey(other.getKey());
}
if (other.hasValue()) {
setValue(other.getValue());
}
return this;
}
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
while (true) {
int tag = input.readTag();
switch (tag) {
case 0:
return this;
default: {
if (!parseUnknownField(input, extensionRegistry, tag)) {
return this;
}
break;
}
case 10: {
setKey(input.readString());
break;
}
case 18: {
setValue(input.readString());
break;
}
}
}
}
// required string key = 1;
public boolean hasKey() {
return result.hasKey();
}
public java.lang.String getKey() {
return result.getKey();
}
public Builder setKey(java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
result.hasKey = true;
result.key_ = value;
return this;
}
public Builder clearKey() {
result.hasKey = false;
result.key_ = getDefaultInstance().getKey();
return this;
}
// required string value = 2;
public boolean hasValue() {
return result.hasValue();
}
public java.lang.String getValue() {
return result.getValue();
}
public Builder setValue(java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
result.hasValue = true;
result.value_ = value;
return this;
}
public Builder clearValue() {
result.hasValue = false;
result.value_ = getDefaultInstance().getValue();
return this;
}
// @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message.KeyValuePair)
}
static {
defaultInstance = new KeyValuePair(true);
org.jetbrains.jps.api.JpsRemoteProto.internalForceInit();
defaultInstance.initFields();
}
// @@protoc_insertion_point(class_scope:org.jetbrains.jpsservice.Message.KeyValuePair)
}
public static final class Failure extends
com.google.protobuf.GeneratedMessageLite {
// Use Failure.newBuilder() to construct.
@@ -869,11 +1168,26 @@ public final class JpsRemoteProto {
return artifactName_.get(index);
}
// repeated .org.jetbrains.jpsservice.Message.KeyValuePair builder_parameter = 6;
public static final int BUILDER_PARAMETER_FIELD_NUMBER = 6;
private java.util.List<org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair> builderParameter_ =
java.util.Collections.emptyList();
public java.util.List<org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair> getBuilderParameterList() {
return builderParameter_;
}
public int getBuilderParameterCount() { return builderParameter_.size(); }
public org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair getBuilderParameter(int index) {
return builderParameter_.get(index);
}
private void initFields() {
commandType_ = org.jetbrains.jps.api.JpsRemoteProto.Message.Request.CompilationRequest.Type.REBUILD;
}
public final boolean isInitialized() {
if (!hasCommandType) return false;
for (org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair element : getBuilderParameterList()) {
if (!element.isInitialized()) return false;
}
return true;
}
@@ -895,6 +1209,9 @@ public final class JpsRemoteProto {
for (java.lang.String element : getArtifactNameList()) {
output.writeString(5, element);
}
for (org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair element : getBuilderParameterList()) {
output.writeMessage(6, element);
}
}
private int memoizedSerializedSize = -1;
@@ -938,6 +1255,10 @@ public final class JpsRemoteProto {
size += dataSize;
size += 1 * getArtifactNameList().size();
}
for (org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair element : getBuilderParameterList()) {
size += com.google.protobuf.CodedOutputStream
.computeMessageSize(6, element);
}
memoizedSerializedSize = size;
return size;
}
@@ -1087,6 +1408,10 @@ public final class JpsRemoteProto {
result.artifactName_ =
java.util.Collections.unmodifiableList(result.artifactName_);
}
if (result.builderParameter_ != java.util.Collections.EMPTY_LIST) {
result.builderParameter_ =
java.util.Collections.unmodifiableList(result.builderParameter_);
}
org.jetbrains.jps.api.JpsRemoteProto.Message.Request.CompilationRequest returnMe = result;
result = null;
return returnMe;
@@ -1118,6 +1443,12 @@ public final class JpsRemoteProto {
}
result.artifactName_.addAll(other.artifactName_);
}
if (!other.builderParameter_.isEmpty()) {
if (result.builderParameter_.isEmpty()) {
result.builderParameter_ = new java.util.ArrayList<org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair>();
}
result.builderParameter_.addAll(other.builderParameter_);
}
return this;
}
@@ -1160,6 +1491,12 @@ public final class JpsRemoteProto {
addArtifactName(input.readString());
break;
}
case 50: {
org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair.Builder subBuilder = org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair.newBuilder();
input.readMessage(subBuilder, extensionRegistry);
addBuilderParameter(subBuilder.buildPartial());
break;
}
}
}
}
@@ -1327,6 +1664,57 @@ public final class JpsRemoteProto {
return this;
}
// repeated .org.jetbrains.jpsservice.Message.KeyValuePair builder_parameter = 6;
public java.util.List<org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair> getBuilderParameterList() {
return java.util.Collections.unmodifiableList(result.builderParameter_);
}
public int getBuilderParameterCount() {
return result.getBuilderParameterCount();
}
public org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair getBuilderParameter(int index) {
return result.getBuilderParameter(index);
}
public Builder setBuilderParameter(int index, org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair value) {
if (value == null) {
throw new NullPointerException();
}
result.builderParameter_.set(index, value);
return this;
}
public Builder setBuilderParameter(int index, org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair.Builder builderForValue) {
result.builderParameter_.set(index, builderForValue.build());
return this;
}
public Builder addBuilderParameter(org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair value) {
if (value == null) {
throw new NullPointerException();
}
if (result.builderParameter_.isEmpty()) {
result.builderParameter_ = new java.util.ArrayList<org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair>();
}
result.builderParameter_.add(value);
return this;
}
public Builder addBuilderParameter(org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair.Builder builderForValue) {
if (result.builderParameter_.isEmpty()) {
result.builderParameter_ = new java.util.ArrayList<org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair>();
}
result.builderParameter_.add(builderForValue.build());
return this;
}
public Builder addAllBuilderParameter(
java.lang.Iterable<? extends org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair> values) {
if (result.builderParameter_.isEmpty()) {
result.builderParameter_ = new java.util.ArrayList<org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair>();
}
super.addAll(values, result.builderParameter_);
return this;
}
public Builder clearBuilderParameter() {
result.builderParameter_ = java.util.Collections.emptyList();
return this;
}
// @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message.Request.CompilationRequest)
}
@@ -1656,305 +2044,6 @@ public final class JpsRemoteProto {
return defaultInstance;
}
public static final class PathVariable extends
com.google.protobuf.GeneratedMessageLite {
// Use PathVariable.newBuilder() to construct.
private PathVariable() {
initFields();
}
private PathVariable(boolean noInit) {}
private static final PathVariable defaultInstance;
public static PathVariable getDefaultInstance() {
return defaultInstance;
}
public PathVariable getDefaultInstanceForType() {
return defaultInstance;
}
// required string name = 1;
public static final int NAME_FIELD_NUMBER = 1;
private boolean hasName;
private java.lang.String name_ = "";
public boolean hasName() { return hasName; }
public java.lang.String getName() { return name_; }
// required string value = 2;
public static final int VALUE_FIELD_NUMBER = 2;
private boolean hasValue;
private java.lang.String value_ = "";
public boolean hasValue() { return hasValue; }
public java.lang.String getValue() { return value_; }
private void initFields() {
}
public final boolean isInitialized() {
if (!hasName) return false;
if (!hasValue) return false;
return true;
}
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
getSerializedSize();
if (hasName()) {
output.writeString(1, getName());
}
if (hasValue()) {
output.writeString(2, getValue());
}
}
private int memoizedSerializedSize = -1;
public int getSerializedSize() {
int size = memoizedSerializedSize;
if (size != -1) return size;
size = 0;
if (hasName()) {
size += com.google.protobuf.CodedOutputStream
.computeStringSize(1, getName());
}
if (hasValue()) {
size += com.google.protobuf.CodedOutputStream
.computeStringSize(2, getValue());
}
memoizedSerializedSize = size;
return size;
}
public static org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data).buildParsed();
}
public static org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data, extensionRegistry)
.buildParsed();
}
public static org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data).buildParsed();
}
public static org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return newBuilder().mergeFrom(data, extensionRegistry)
.buildParsed();
}
public static org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable parseFrom(java.io.InputStream input)
throws java.io.IOException {
return newBuilder().mergeFrom(input).buildParsed();
}
public static org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return newBuilder().mergeFrom(input, extensionRegistry)
.buildParsed();
}
public static org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
Builder builder = newBuilder();
if (builder.mergeDelimitedFrom(input)) {
return builder.buildParsed();
} else {
return null;
}
}
public static org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
Builder builder = newBuilder();
if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
return builder.buildParsed();
} else {
return null;
}
}
public static org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return newBuilder().mergeFrom(input).buildParsed();
}
public static org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return newBuilder().mergeFrom(input, extensionRegistry)
.buildParsed();
}
public static Builder newBuilder() { return Builder.create(); }
public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder(org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable prototype) {
return newBuilder().mergeFrom(prototype);
}
public Builder toBuilder() { return newBuilder(this); }
public static final class Builder extends
com.google.protobuf.GeneratedMessageLite.Builder<
org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable, Builder> {
private org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable result;
// Construct using org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable.newBuilder()
private Builder() {}
private static Builder create() {
Builder builder = new Builder();
builder.result = new org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable();
return builder;
}
protected org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable internalGetResult() {
return result;
}
public Builder clear() {
if (result == null) {
throw new IllegalStateException(
"Cannot call clear() after build().");
}
result = new org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable();
return this;
}
public Builder clone() {
return create().mergeFrom(result);
}
public org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable getDefaultInstanceForType() {
return org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable.getDefaultInstance();
}
public boolean isInitialized() {
return result.isInitialized();
}
public org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable build() {
if (result != null && !isInitialized()) {
throw newUninitializedMessageException(result);
}
return buildPartial();
}
private org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable buildParsed()
throws com.google.protobuf.InvalidProtocolBufferException {
if (!isInitialized()) {
throw newUninitializedMessageException(
result).asInvalidProtocolBufferException();
}
return buildPartial();
}
public org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable buildPartial() {
if (result == null) {
throw new IllegalStateException(
"build() has already been called on this Builder.");
}
org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable returnMe = result;
result = null;
return returnMe;
}
public Builder mergeFrom(org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable other) {
if (other == org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable.getDefaultInstance()) return this;
if (other.hasName()) {
setName(other.getName());
}
if (other.hasValue()) {
setValue(other.getValue());
}
return this;
}
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
while (true) {
int tag = input.readTag();
switch (tag) {
case 0:
return this;
default: {
if (!parseUnknownField(input, extensionRegistry, tag)) {
return this;
}
break;
}
case 10: {
setName(input.readString());
break;
}
case 18: {
setValue(input.readString());
break;
}
}
}
}
// required string name = 1;
public boolean hasName() {
return result.hasName();
}
public java.lang.String getName() {
return result.getName();
}
public Builder setName(java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
result.hasName = true;
result.name_ = value;
return this;
}
public Builder clearName() {
result.hasName = false;
result.name_ = getDefaultInstance().getName();
return this;
}
// required string value = 2;
public boolean hasValue() {
return result.hasValue();
}
public java.lang.String getValue() {
return result.getValue();
}
public Builder setValue(java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
result.hasValue = true;
result.value_ = value;
return this;
}
public Builder clearValue() {
result.hasValue = false;
result.value_ = getDefaultInstance().getValue();
return this;
}
// @@protoc_insertion_point(builder_scope:org.jetbrains.jpsservice.Message.Request.SetupCommand.PathVariable)
}
static {
defaultInstance = new PathVariable(true);
org.jetbrains.jps.api.JpsRemoteProto.internalForceInit();
defaultInstance.initFields();
}
// @@protoc_insertion_point(class_scope:org.jetbrains.jpsservice.Message.Request.SetupCommand.PathVariable)
}
public static final class GlobalLibrary extends
com.google.protobuf.GeneratedMessageLite {
// Use GlobalLibrary.newBuilder() to construct.
@@ -2415,15 +2504,15 @@ public final class JpsRemoteProto {
// @@protoc_insertion_point(class_scope:org.jetbrains.jpsservice.Message.Request.SetupCommand.GlobalLibrary)
}
// repeated .org.jetbrains.jpsservice.Message.Request.SetupCommand.PathVariable path_variable = 1;
// repeated .org.jetbrains.jpsservice.Message.KeyValuePair path_variable = 1;
public static final int PATH_VARIABLE_FIELD_NUMBER = 1;
private java.util.List<org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable> pathVariable_ =
private java.util.List<org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair> pathVariable_ =
java.util.Collections.emptyList();
public java.util.List<org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable> getPathVariableList() {
public java.util.List<org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair> getPathVariableList() {
return pathVariable_;
}
public int getPathVariableCount() { return pathVariable_.size(); }
public org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable getPathVariable(int index) {
public org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair getPathVariable(int index) {
return pathVariable_.get(index);
}
@@ -2449,7 +2538,7 @@ public final class JpsRemoteProto {
private void initFields() {
}
public final boolean isInitialized() {
for (org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable element : getPathVariableList()) {
for (org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair element : getPathVariableList()) {
if (!element.isInitialized()) return false;
}
for (org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.GlobalLibrary element : getGlobalLibraryList()) {
@@ -2461,7 +2550,7 @@ public final class JpsRemoteProto {
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
getSerializedSize();
for (org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable element : getPathVariableList()) {
for (org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair element : getPathVariableList()) {
output.writeMessage(1, element);
}
for (org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.GlobalLibrary element : getGlobalLibraryList()) {
@@ -2478,7 +2567,7 @@ public final class JpsRemoteProto {
if (size != -1) return size;
size = 0;
for (org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable element : getPathVariableList()) {
for (org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair element : getPathVariableList()) {
size += com.google.protobuf.CodedOutputStream
.computeMessageSize(1, element);
}
@@ -2644,7 +2733,7 @@ public final class JpsRemoteProto {
if (other == org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.getDefaultInstance()) return this;
if (!other.pathVariable_.isEmpty()) {
if (result.pathVariable_.isEmpty()) {
result.pathVariable_ = new java.util.ArrayList<org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable>();
result.pathVariable_ = new java.util.ArrayList<org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair>();
}
result.pathVariable_.addAll(other.pathVariable_);
}
@@ -2676,7 +2765,7 @@ public final class JpsRemoteProto {
break;
}
case 10: {
org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable.Builder subBuilder = org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable.newBuilder();
org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair.Builder subBuilder = org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair.newBuilder();
input.readMessage(subBuilder, extensionRegistry);
addPathVariable(subBuilder.buildPartial());
break;
@@ -2696,48 +2785,48 @@ public final class JpsRemoteProto {
}
// repeated .org.jetbrains.jpsservice.Message.Request.SetupCommand.PathVariable path_variable = 1;
public java.util.List<org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable> getPathVariableList() {
// repeated .org.jetbrains.jpsservice.Message.KeyValuePair path_variable = 1;
public java.util.List<org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair> getPathVariableList() {
return java.util.Collections.unmodifiableList(result.pathVariable_);
}
public int getPathVariableCount() {
return result.getPathVariableCount();
}
public org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable getPathVariable(int index) {
public org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair getPathVariable(int index) {
return result.getPathVariable(index);
}
public Builder setPathVariable(int index, org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable value) {
public Builder setPathVariable(int index, org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair value) {
if (value == null) {
throw new NullPointerException();
}
result.pathVariable_.set(index, value);
return this;
}
public Builder setPathVariable(int index, org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable.Builder builderForValue) {
public Builder setPathVariable(int index, org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair.Builder builderForValue) {
result.pathVariable_.set(index, builderForValue.build());
return this;
}
public Builder addPathVariable(org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable value) {
public Builder addPathVariable(org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair value) {
if (value == null) {
throw new NullPointerException();
}
if (result.pathVariable_.isEmpty()) {
result.pathVariable_ = new java.util.ArrayList<org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable>();
result.pathVariable_ = new java.util.ArrayList<org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair>();
}
result.pathVariable_.add(value);
return this;
}
public Builder addPathVariable(org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable.Builder builderForValue) {
public Builder addPathVariable(org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair.Builder builderForValue) {
if (result.pathVariable_.isEmpty()) {
result.pathVariable_ = new java.util.ArrayList<org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable>();
result.pathVariable_ = new java.util.ArrayList<org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair>();
}
result.pathVariable_.add(builderForValue.build());
return this;
}
public Builder addAllPathVariable(
java.lang.Iterable<? extends org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable> values) {
java.lang.Iterable<? extends org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair> values) {
if (result.pathVariable_.isEmpty()) {
result.pathVariable_ = new java.util.ArrayList<org.jetbrains.jps.api.JpsRemoteProto.Message.Request.SetupCommand.PathVariable>();
result.pathVariable_ = new java.util.ArrayList<org.jetbrains.jps.api.JpsRemoteProto.Message.KeyValuePair>();
}
super.addAll(values, result.pathVariable_);
return this;
@@ -28,23 +28,34 @@ public class ProtoUtil {
return builder.build();
}
public static JpsRemoteProto.Message.Request createMakeRequest(String project, Collection<String> modules, Collection<String> artifacts) {
return createCompileRequest(JpsRemoteProto.Message.Request.CompilationRequest.Type.MAKE, project, modules, artifacts, Collections.<String>emptyList());
public static JpsRemoteProto.Message.Request createMakeRequest(String project,
Collection<String> modules,
Collection<String> artifacts,
final Map<String, String> userData) {
return createCompileRequest(JpsRemoteProto.Message.Request.CompilationRequest.Type.MAKE, project, modules, artifacts,
userData, Collections.<String>emptyList());
}
public static JpsRemoteProto.Message.Request createForceCompileRequest(String project,
Collection<String> modules,
Collection<String> artifacts, Collection<String> paths) {
return createCompileRequest(JpsRemoteProto.Message.Request.CompilationRequest.Type.FORCED_COMPILATION, project, modules, artifacts, paths);
Collection<String> artifacts,
Collection<String> paths,
final Map<String, String> userData) {
return createCompileRequest(JpsRemoteProto.Message.Request.CompilationRequest.Type.FORCED_COMPILATION, project, modules, artifacts,
userData, paths);
}
public static JpsRemoteProto.Message.Request createRebuildRequest(String project) {
public static JpsRemoteProto.Message.Request createRebuildRequest(String project, final Map<String, String> userData) {
return createCompileRequest(JpsRemoteProto.Message.Request.CompilationRequest.Type.REBUILD, project, Collections.<String>emptyList(),
Collections.<String>emptyList(), Collections.<String>emptyList());
Collections.<String>emptyList(), userData, Collections.<String>emptyList());
}
public static JpsRemoteProto.Message.Request createCleanRequest(String project, Collection<String> modules, Collection<String> artifacts) {
return createCompileRequest(JpsRemoteProto.Message.Request.CompilationRequest.Type.CLEAN, project, modules, artifacts, Collections.<String>emptyList());
public static JpsRemoteProto.Message.Request createCleanRequest(String project,
Collection<String> modules,
Collection<String> artifacts,
final Map<String, String> userData) {
return createCompileRequest(JpsRemoteProto.Message.Request.CompilationRequest.Type.CLEAN, project, modules, artifacts,
userData, Collections.<String>emptyList());
}
public static JpsRemoteProto.Message.Request createCancelRequest(UUID compileSessionId) {
@@ -53,22 +64,34 @@ public class ProtoUtil {
return JpsRemoteProto.Message.Request.newBuilder().setRequestType(JpsRemoteProto.Message.Request.Type.CANCEL_BUILD_COMMAND).setCancelBuildCommand(builder.build()).build();
}
public static JpsRemoteProto.Message.Request createCompileRequest(final JpsRemoteProto.Message.Request.CompilationRequest.Type command, String project, Collection<String> modules,
Collection<String> artifacts, Collection<String> paths) {
public static JpsRemoteProto.Message.Request createCompileRequest(
final JpsRemoteProto.Message.Request.CompilationRequest.Type command,
String project,
Collection<String> modules,
Collection<String> artifacts, Map<String, String> userData, Collection<String> paths) {
final JpsRemoteProto.Message.Request.CompilationRequest.Builder builder = JpsRemoteProto.Message.Request.CompilationRequest.newBuilder().setCommandType(
command);
builder.setProjectId(project);
if (modules.size() > 0) {
if (!modules.isEmpty()) {
builder.addAllModuleName(modules);
}
if (artifacts.size() > 0) {
if (!artifacts.isEmpty()) {
builder.addAllArtifactName(artifacts);
}
if (paths.size() > 0) {
if (!userData.isEmpty()) {
for (Map.Entry<String, String> entry : userData.entrySet()) {
final String key = entry.getKey();
final String value = entry.getValue();
if (key != null && value != null) {
builder.addBuilderParameter(createPair(key, value));
}
}
}
if (!paths.isEmpty()) {
builder.addAllFilePath(paths);
}
return JpsRemoteProto.Message.Request.newBuilder().setRequestType(JpsRemoteProto.Message.Request.Type.COMPILE_REQUEST).setCompileRequest(
builder.build()).build();
return JpsRemoteProto.Message.Request.newBuilder().setRequestType(JpsRemoteProto.Message.Request.Type.COMPILE_REQUEST).setCompileRequest(builder.build()).build();
}
public static JpsRemoteProto.Message.Request createShutdownRequest(boolean cancelRunningBuilds) {
@@ -101,9 +124,7 @@ public class ProtoUtil {
final String var = entry.getKey();
final String value = entry.getValue();
if (var != null && value != null) {
final JpsRemoteProto.Message.Request.SetupCommand.PathVariable.Builder pathVarBuilder =
JpsRemoteProto.Message.Request.SetupCommand.PathVariable.newBuilder();
cmdBuilder.addPathVariable(pathVarBuilder.setName(var).setValue(value).build());
cmdBuilder.addPathVariable(createPair(var, value));
}
}
}
@@ -131,6 +152,10 @@ public class ProtoUtil {
return JpsRemoteProto.Message.Request.newBuilder().setRequestType(JpsRemoteProto.Message.Request.Type.SETUP_COMMAND).setSetupCommand(cmdBuilder.build()).build();
}
public static JpsRemoteProto.Message.KeyValuePair createPair(String key, String value) {
return JpsRemoteProto.Message.KeyValuePair.newBuilder().setKey(key).setValue(value).build();
}
public static JpsRemoteProto.Message.Response createBuildStartedEvent(@Nullable String description) {
return createBuildEvent(JpsRemoteProto.Message.Response.BuildEvent.Type.BUILD_STARTED, description, null, null);
}
@@ -5,10 +5,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.api.*;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.*;
/**
* @author Eugene Zhuravlev
@@ -28,18 +25,20 @@ public class CompileServerClient extends SimpleProtobufClient<JpsServerResponseH
@NotNull
public RequestFuture sendCompileRequest(boolean isMake, String projectId, Collection<String> modules, final Collection<String> artifacts,
Collection<String> paths, JpsServerResponseHandler handler) throws Exception{
Collection<String> paths,
final Map<String, String> userData,
JpsServerResponseHandler handler) throws Exception{
checkConnected();
final JpsRemoteProto.Message.Request request = isMake?
ProtoUtil.createMakeRequest(projectId, modules, artifacts) :
ProtoUtil.createForceCompileRequest(projectId, modules, artifacts, paths);
ProtoUtil.createMakeRequest(projectId, modules, artifacts, userData) :
ProtoUtil.createForceCompileRequest(projectId, modules, artifacts, paths, userData);
return sendRequest(request, handler);
}
@NotNull
public RequestFuture sendRebuildRequest(String projectId, JpsServerResponseHandler handler) throws Exception{
checkConnected();
return sendRequest(ProtoUtil.createRebuildRequest(projectId), handler);
return sendRequest(ProtoUtil.createRebuildRequest(projectId, Collections.<String, String>emptyMap()), handler);
}
@NotNull
@@ -41,6 +41,7 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler
private volatile boolean myErrorsFound = false;
private final long myCompilationStartStamp;
private final TimestampStorage myTsStorage;
private final Map<String, String> myBuilderParams;
private final CanceledStatus myCancelStatus;
private float myDone = -1.0f;
@@ -49,8 +50,15 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler
boolean isProjectRebuild,
ProjectChunks productionChunks,
ProjectChunks testChunks,
FSState fsState, final BuildDataManager dataManager, TimestampStorage tsStorage, MessageHandler delegateMessageHandler, final ModuleRootsIndex rootsIndex, CanceledStatus cancelStatus) throws ProjectBuildException {
FSState fsState,
final BuildDataManager dataManager,
TimestampStorage tsStorage,
MessageHandler delegateMessageHandler,
final ModuleRootsIndex rootsIndex,
Map<String, String> builderParams,
CanceledStatus cancelStatus) throws ProjectBuildException {
myTsStorage = tsStorage;
myBuilderParams = Collections.unmodifiableMap(builderParams);
myCancelStatus = cancelStatus;
myCompilationStartStamp = System.currentTimeMillis();
myScope = scope;
@@ -82,6 +90,11 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler
return myIsProjectRebuild;
}
@Nullable
public String getBuilderParameter(String paramName) {
return myBuilderParams.get(paramName);
}
public void markDirty(final File file) throws IOException {
final RootDescriptor descriptor = getModuleAndRoot(file);
if (descriptor != null) {
@@ -37,6 +37,7 @@ public class IncProjectBuilder {
private final ProjectDescriptor myProjectDescriptor;
private final BuilderRegistry myBuilderRegistry;
private final Map<String, String> myBuilderParams;
private final CanceledStatus myCancelStatus;
private ProjectChunks myProductionChunks;
private ProjectChunks myTestChunks;
@@ -53,9 +54,10 @@ public class IncProjectBuilder {
private final float myTotalModulesWork;
private final int myTotalModuleLevelBuilderCount;
public IncProjectBuilder(ProjectDescriptor pd, BuilderRegistry builderRegistry, CanceledStatus cs) {
public IncProjectBuilder(ProjectDescriptor pd, BuilderRegistry builderRegistry, Map<String, String> builderParams, CanceledStatus cs) {
myProjectDescriptor = pd;
myBuilderRegistry = builderRegistry;
myBuilderParams = builderParams;
myCancelStatus = cs;
myProductionChunks = new ProjectChunks(pd.project, ClasspathKind.PRODUCTION_COMPILE);
myTestChunks = new ProjectChunks(pd.project, ClasspathKind.TEST_COMPILE);
@@ -182,8 +184,10 @@ public class IncProjectBuilder {
final FSState fsState = myProjectDescriptor.fsState;
final ModuleRootsIndex rootsIndex = myProjectDescriptor.rootsIndex;
final BuildDataManager dataManager = myProjectDescriptor.dataManager;
return new CompileContext(scope, isMake, isProjectRebuild, myProductionChunks, myTestChunks, fsState, dataManager, tsStorage,
myMessageDispatcher, rootsIndex, myCancelStatus);
return new CompileContext(
scope, isMake, isProjectRebuild, myProductionChunks, myTestChunks, fsState, dataManager, tsStorage, myMessageDispatcher, rootsIndex,
myBuilderParams, myCancelStatus
);
}
private void cleanOutputRoots(CompileContext context) throws ProjectBuildException {
@@ -69,8 +69,8 @@ class ServerMessageHandler extends SimpleChannelHandler {
case SETUP_COMMAND:
final Map<String, String> pathVars = new HashMap<String, String>();
final JpsRemoteProto.Message.Request.SetupCommand setupCommand = request.getSetupCommand();
for (JpsRemoteProto.Message.Request.SetupCommand.PathVariable variable : setupCommand.getPathVariableList()) {
pathVars.put(variable.getName(), variable.getValue());
for (JpsRemoteProto.Message.KeyValuePair variable : setupCommand.getPathVariableList()) {
pathVars.put(variable.getKey(), variable.getValue());
}
final List<GlobalLibrary> libs = new ArrayList<GlobalLibrary>();
for (JpsRemoteProto.Message.Request.SetupCommand.GlobalLibrary library : setupCommand.getGlobalLibraryList()) {
@@ -187,8 +187,14 @@ class ServerMessageHandler extends SimpleChannelHandler {
case REBUILD: {
channelContext.setAttachment(sessionId);
final BuildType buildType = convertCompileType(compileType);
final CompilationTask task = new CompilationTask(sessionId, channelContext, projectId, buildType, compileRequest.getModuleNameList(),
compileRequest.getArtifactNameList(), compileRequest.getFilePathList());
final List<String> modules = compileRequest.getModuleNameList();
final List<String> artifacts = compileRequest.getArtifactNameList();
final List<String> paths = compileRequest.getFilePathList();
final Map<String, String> builderParams = new HashMap<String, String>();
for (JpsRemoteProto.Message.KeyValuePair pair : compileRequest.getBuilderParameterList()) {
builderParams.put(pair.getKey(), pair.getValue());
}
final CompilationTask task = new CompilationTask(sessionId, channelContext, projectId, buildType, modules, artifacts, builderParams, paths);
final RunnableFuture future = getCompileTaskExecutor(projectId).submit(task);
myBuildsInProgress.add(new Pair<RunnableFuture, CompilationTask>(future, task));
return null;
@@ -230,6 +236,7 @@ class ServerMessageHandler extends SimpleChannelHandler {
private final String myProjectPath;
private final BuildType myBuildType;
private final Collection<String> myArtifacts;
private final Map<String, String> myBuilderParams;
private final Collection<String> myPaths;
private final Set<String> myModules;
private volatile boolean myCanceled = false;
@@ -240,12 +247,13 @@ class ServerMessageHandler extends SimpleChannelHandler {
BuildType buildType,
Collection<String> modules,
Collection<String> artifacts,
Collection<String> paths) {
Map<String, String> builderParams, Collection<String> paths) {
mySessionId = sessionId;
myChannelContext = channelContext;
myProjectPath = projectId;
myBuildType = buildType;
myArtifacts = artifacts;
myBuilderParams = builderParams;
myPaths = paths;
myModules = new HashSet<String>(modules);
}
@@ -264,7 +272,7 @@ class ServerMessageHandler extends SimpleChannelHandler {
final Ref<Boolean> hasErrors = new Ref<Boolean>(false);
final Ref<Boolean> markedFilesUptodate = new Ref<Boolean>(false);
try {
ServerState.getInstance().startBuild(myProjectPath, myBuildType, myModules, myArtifacts, myPaths, new MessageHandler() {
ServerState.getInstance().startBuild(myProjectPath, myBuildType, myModules, myArtifacts, myBuilderParams, myPaths, new MessageHandler() {
public void processMessage(BuildMessage buildMessage) {
final JpsRemoteProto.Message.Response response;
if (buildMessage instanceof FileGeneratedEvent) {
@@ -124,7 +124,7 @@ class ServerState {
}
public void startBuild(String projectPath, BuildType buildType, Set<String> modules, Collection<String> artifacts,
Collection<String> paths, final MessageHandler msgHandler, CanceledStatus cs) throws Throwable{
Map<String, String> builderParams, Collection<String> paths, final MessageHandler msgHandler, CanceledStatus cs) throws Throwable{
final String projectName = getProjectName(projectPath);
@@ -167,7 +167,7 @@ class ServerState {
try {
final CompileScope compileScope = createCompilationScope(buildType, pd, modules, artifacts, paths);
final IncProjectBuilder builder = new IncProjectBuilder(pd, BuilderRegistry.getInstance(), cs);
final IncProjectBuilder builder = new IncProjectBuilder(pd, BuilderRegistry.getInstance(), builderParams, cs);
if (msgHandler != null) {
builder.addMessageHandler(msgHandler);
}
@@ -325,7 +325,7 @@ public abstract class IncrementalTestCase extends TestCase {
try {
new IncProjectBuilder(
projectDescriptor, BuilderRegistry.getInstance(), CanceledStatus.NULL
projectDescriptor, BuilderRegistry.getInstance(), Collections.<String, String>emptyMap(), CanceledStatus.NULL
).build(
new AllProjectScope(project, Collections.<Artifact>emptySet(), true), false, true
);
@@ -337,7 +337,7 @@ public abstract class IncrementalTestCase extends TestCase {
}
new IncProjectBuilder(
projectDescriptor, BuilderRegistry.getInstance(), CanceledStatus.NULL
projectDescriptor, BuilderRegistry.getInstance(), Collections.<String, String>emptyMap(), CanceledStatus.NULL
).build(
new AllProjectScope(project, Collections.<Artifact>emptySet(), false), true, false
);
@@ -111,6 +111,7 @@ public class FileStructurePopup implements Disposable {
private PsiElement myInitialPsiElement;
private Map<Class, JCheckBox> myCheckBoxes = new HashMap<Class, JCheckBox>();
private String myTestSearchFilter;
private final ActionCallback myTreeHasBuilt = new ActionCallback();
public FileStructurePopup(StructureViewModel structureViewModel,
@Nullable Editor editor,
@@ -119,6 +120,7 @@ public class FileStructurePopup implements Disposable {
final boolean applySortAndFilter) {
myProject = project;
myEditor = editor;
IdeFocusManager.getInstance(myProject).typeAheadUntil(myTreeHasBuilt);
myBaseTreeModel = structureViewModel;
Disposer.register(this, auxDisposable);
if (applySortAndFilter) {
@@ -210,8 +212,6 @@ public class FileStructurePopup implements Disposable {
public void show() {
//final long time = System.currentTimeMillis();
final ActionCallback treeHasBuilt = new ActionCallback();
IdeFocusManager.getInstance(myProject).typeAheadUntil(treeHasBuilt);
JComponent panel = createCenterPanel();
new MnemonicHelper().register(panel);
boolean shouldSetWidth = DimensionService.getInstance().getSize(getDimensionServiceKey(), myProject) == null;
@@ -250,8 +250,8 @@ public class FileStructurePopup implements Disposable {
Disposer.register(myPopup, new Disposable() {
@Override
public void dispose() {
if (!treeHasBuilt.isDone()) {
treeHasBuilt.setRejected();
if (!myTreeHasBuilt.isDone()) {
myTreeHasBuilt.setRejected();
}
}
});
@@ -275,7 +275,7 @@ public class FileStructurePopup implements Disposable {
@Override
public void run() {
selectPsiElement(myInitialPsiElement);
treeHasBuilt.setDone();
myTreeHasBuilt.setDone();
//long t = System.currentTimeMillis() - time;
//System.out.println("Shown in " + t + "ms");
}
@@ -434,13 +434,6 @@ public class FileStructurePopup implements Disposable {
}
}.registerCustomShortcutSet(shortcutSet, panel);
new AnAction() {
@Override
public void actionPerformed(AnActionEvent e) {
mySpeedSearch.setEnteredPrefix("");
}
}.registerCustomShortcutSet(CustomShortcutSet.fromString(SystemInfo.isMac ? "meta BACK_SPACE" : "control BACK_SPACE"), myTree);
new AnAction() {
public void actionPerformed(AnActionEvent e) {
if (mySpeedSearch != null && mySpeedSearch.isPopupActive()) {
@@ -178,10 +178,11 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel {
}
protected static Color defaultActionForeground(boolean isSelected, Presentation presentation) {
return isSelected ? UIUtil.getListSelectionForeground()
: presentation.isEnabled() && presentation.isVisible()
? UIUtil.getListForeground()
: UIUtil.getInactiveTextColor();
if (!presentation.isEnabled() || !presentation.isVisible()) {
return UIUtil.getInactiveTextColor();
}
return isSelected ? UIUtil.getListSelectionForeground() : UIUtil.getListForeground();
}
public String[] getNames(boolean checkBoxState) {
@@ -115,6 +115,7 @@ public abstract class MouseDragHelper implements MouseListener, MouseMotionListe
myPressPointScreen = new RelativePoint(e).getScreenPoint();
myPressPointComponent = e.getPoint();
processMousePressed(e);
myDelta = new Dimension();
if (myDragComponent.isShowing()) {
@@ -209,6 +210,9 @@ public abstract class MouseDragHelper implements MouseListener, MouseMotionListe
return true;
}
protected void processMousePressed(MouseEvent event) {
}
protected void processDragCancel() {
}
@@ -86,6 +86,12 @@ public final class TabInfo implements Queryable, PlaceProvider<String> {
private Queryable myQueryable;
private DragOutDelegate myDragOutDelegate;
/**
* The tab which was selected before the mouse was pressed on this tab. Focus will be transferred to that tab if this tab is dragged
* out of its container. (IDEA-61536)
*/
private WeakReference<TabInfo> myPreviousSelection = new WeakReference<TabInfo>(null);
public TabInfo(final JComponent component) {
myComponent = component;
myPreferredFocusableComponent = component;
@@ -371,6 +377,15 @@ public final class TabInfo implements Queryable, PlaceProvider<String> {
return myDragOutDelegate;
}
public void setPreviousSelection(@Nullable TabInfo previousSelection) {
myPreviousSelection = new WeakReference<TabInfo>(previousSelection);
}
@Nullable
public TabInfo getPreviousSelection() {
return myPreviousSelection.get();
}
public interface DragOutDelegate {
void dragOutStarted(MouseEvent mouseEvent, TabInfo info);
@@ -18,6 +18,7 @@ package com.intellij.ui.tabs.impl;
import com.intellij.ui.InplaceButton;
import com.intellij.ui.MouseDragHelper;
import com.intellij.ui.ScreenUtil;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.tabs.TabInfo;
import org.jetbrains.annotations.Nullable;
@@ -38,6 +39,7 @@ class DragHelper extends MouseDragHelper {
Measurer myVertical = new Measurer.Height();
private TabInfo myDragOutSource;
private TabLabel myPressedTabLabel;
public DragHelper(JBTabsImpl tabs) {
super(tabs, tabs);
@@ -81,19 +83,25 @@ class DragHelper extends MouseDragHelper {
myDragOutSource.getDragOutDelegate().dragOutCancelled(myDragOutSource);
}
@Override
protected void processMousePressed(MouseEvent event) {
// since selection change can cause tabs to be reordered, we need to remember the tab on which the mouse was pressed, otherwise
// we'll end up dragging the wrong tab (IDEA-65073)
myPressedTabLabel = findLabel(new RelativePoint(event).getPoint(myTabs));
}
protected void processDrag(MouseEvent event, Point targetScreenPoint, Point startPointScreen) {
if (!myTabs.isTabDraggingEnabled()) return;
SwingUtilities.convertPointFromScreen(startPointScreen, myTabs);
if (isDragJustStarted()) {
final TabLabel label = findLabel(startPointScreen);
if (label == null) return;
if (myPressedTabLabel == null) return;
final Rectangle labelBounds = label.getBounds();
final Rectangle labelBounds = myPressedTabLabel.getBounds();
myHoldDelta = new Dimension(startPointScreen.x - labelBounds.x, startPointScreen.y - labelBounds.y);
myDragSource = label.getInfo();
myDragSource = myPressedTabLabel.getInfo();
myDragRec = new Rectangle(startPointScreen, labelBounds.getSize());
myDragOriginalRec = (Rectangle)myDragRec.clone();
@@ -147,7 +147,7 @@ public class JBTabsImpl extends JComponent
private TimedDeadzone.Length myTabActionsMouseDeadzone = TimedDeadzone.DEFAULT;
private long myRemoveDefferredRequest;
private long myRemoveDeferredRequest;
private boolean myTestMode;
private JBTabsPosition myPosition = JBTabsPosition.top;
@@ -156,8 +156,6 @@ public class JBTabsImpl extends JComponent
private BaseNavigationAction myNextAction;
private BaseNavigationAction myPrevAction;
private boolean myWasEverShown;
private boolean myTabDraggingEnabled;
private DragHelper myDragHelper;
private boolean myNavigationActionsEnabled = true;
@@ -884,11 +882,11 @@ public class JBTabsImpl extends JComponent
private ActionCallback removeDeferred() {
final ActionCallback callback = new ActionCallback();
final long executionRequest = ++myRemoveDefferredRequest;
final long executionRequest = ++myRemoveDeferredRequest;
final Runnable onDone = new Runnable() {
public void run() {
if (myRemoveDefferredRequest == executionRequest) {
if (myRemoveDeferredRequest == executionRequest) {
removeDeferredNow();
}
@@ -1468,11 +1466,6 @@ public class JBTabsImpl extends JComponent
return insets;
}
private int fixInset(int inset, int addin) {
return inset + addin;
}
public int getToolbarInset() {
return getArcSize() + 1;
}
@@ -2903,7 +2896,7 @@ public class JBTabsImpl extends JComponent
return mySingleRowLayout;
}
public JBTabsPresentation setUiDecorator(UiDecorator decorator) {
public JBTabsPresentation setUiDecorator(@Nullable UiDecorator decorator) {
myUiDecorator = decorator == null ? ourDefaultDecorator : decorator;
applyDecoration();
return this;
@@ -2989,9 +2982,7 @@ public class JBTabsImpl extends JComponent
ActionGroup group = selection.getGroup();
if (group != null) {
AnAction[] children = group.getChildren(null);
for (int i = 0; i < children.length; i++) {
result.add(children[i]);
}
Collections.addAll(result, children);
}
}
@@ -34,6 +34,7 @@ import com.intellij.ui.tabs.UiDecorator;
import com.intellij.ui.tabs.impl.table.TableLayout;
import com.intellij.util.PairConsumer;
import com.intellij.util.ui.Centerizer;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
@@ -87,6 +88,10 @@ public class TabLabel extends JPanel {
addMouseListener(new MouseAdapter() {
public void mousePressed(final MouseEvent e) {
if (myTabs.isSelectionClick(e, false) && myInfo.isEnabled()) {
final TabInfo selectedInfo = myTabs.getSelectedInfo();
if (selectedInfo != myInfo) {
myInfo.setPreviousSelection(selectedInfo);
}
Component c = SwingUtilities.getDeepestComponentAt(e.getComponent(), e.getX(), e.getY());
if (c instanceof InplaceButton) return;
myTabs.select(info, true);
@@ -101,6 +106,7 @@ public class TabLabel extends JPanel {
}
public void mouseReleased(final MouseEvent e) {
myInfo.setPreviousSelection(null);
handlePopup(e);
}
});
@@ -385,8 +391,8 @@ public class TabLabel extends JPanel {
}
}
private static int getValue(int curentValue, int newValue) {
return newValue != -1 ? newValue : curentValue;
private static int getValue(int currentValue, int newValue) {
return newValue != -1 ? newValue : currentValue;
}
public void setTabActions(ActionGroup group) {
@@ -530,6 +536,7 @@ public class TabLabel extends JPanel {
}
@Nullable
public BufferedImage getInactiveStateImage(Rectangle effectiveBounds) {
BufferedImage img = null;
if (myLastPaintedInactiveImageBounds != null && myLastPaintedInactiveImageBounds.getSize().equals(effectiveBounds.getSize())) {
@@ -541,7 +548,7 @@ public class TabLabel extends JPanel {
return img;
}
public void setInactiveStateImage(BufferedImage img) {
public void setInactiveStateImage(@Nullable BufferedImage img) {
if (myInactiveStateImage != null && img != myInactiveStateImage) {
myInactiveStateImage.flush();
}
@@ -100,6 +100,7 @@ public class FilteringTreeStructure extends AbstractTreeStructure {
}
private void setUnknown(FilteringNode node) {
if (node.state == State.UNKNOWN) return;
node.state = State.UNKNOWN;
List<FilteringNode> nodes = myNodesCache.get(node);
if (nodes != null) {
@@ -121,7 +121,7 @@ public class EventLog implements Notifications {
return getLogModel(project).getStatusMessage();
}
public static LogEntry formatForLog(@NotNull final Notification notification) {
public static LogEntry formatForLog(@NotNull final Notification notification, String indent) {
DocumentImpl logDoc = new DocumentImpl(true);
AtomicBoolean showMore = new AtomicBoolean(false);
Map<RangeMarker, HyperlinkInfo> links = new LinkedHashMap<RangeMarker, HyperlinkInfo>();
@@ -141,7 +141,7 @@ public class EventLog implements Notifications {
String status = getStatusText(logDoc, showMore, lineSeparators, hasHtml);
indentNewLines(logDoc, lineSeparators, afterTitle, hasHtml);
indentNewLines(logDoc, lineSeparators, afterTitle, hasHtml, indent);
ArrayList<Pair<TextRange, HyperlinkInfo>> list = new ArrayList<Pair<TextRange, HyperlinkInfo>>();
for (RangeMarker marker : links.keySet()) {
@@ -165,7 +165,7 @@ public class EventLog implements Notifications {
return new LogEntry(logDoc.getText(), status, list);
}
private static void indentNewLines(DocumentImpl logDoc, List<RangeMarker> lineSeparators, RangeMarker afterTitle, boolean hasHtml) {
private static void indentNewLines(DocumentImpl logDoc, List<RangeMarker> lineSeparators, RangeMarker afterTitle, boolean hasHtml, String indent) {
if (!hasHtml) {
int i = -1;
while (true) {
@@ -187,8 +187,8 @@ public class EventLog implements Notifications {
continue;
}
logDoc.replaceString(start, separator.getEndOffset(), "\n\t");
nextLineStart = start + 2;
logDoc.replaceString(start, separator.getEndOffset(), "\n" + indent);
nextLineStart = start + 1 + indent.length();
while (nextLineStart < logDoc.getTextLength() && Character.isWhitespace(logDoc.getCharsSequence().charAt(nextLineStart))) {
logDoc.deleteString(nextLineStart, nextLineStart + 1);
}
@@ -234,8 +234,9 @@ public class EventLog implements Notifications {
int linkEnd = content.indexOf(A_CLOSING, tagMatcher.end());
if (linkEnd > 0) {
String linkText = content.substring(tagMatcher.end(), linkEnd).replaceAll(TAG_PATTERN.pattern(), "");
int linkStart = document.getTextLength();
appendText(document, linkText);
links.put(document.createRangeMarker(new TextRange(document.getTextLength() - linkText.length(), document.getTextLength())),
links.put(document.createRangeMarker(new TextRange(linkStart, document.getTextLength())),
new NotificationHyperlinkInfo(notification, href));
content = content.substring(linkEnd + A_CLOSING.length());
continue;
@@ -38,6 +38,7 @@ import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.EditorPopupHandler;
import com.intellij.util.text.DateFormatUtil;
@@ -137,10 +138,11 @@ class EventLogConsole {
if (notificationTime == null) {
return;
}
append(document, DateFormatUtil.formatTimeWithSeconds(notificationTime) + " ");
EventLog.LogEntry pair = EventLog.formatForLog(notification);
String date = DateFormatUtil.formatTimeWithSeconds(notificationTime) + " ";
append(document, date);
EventLog.LogEntry pair = EventLog.formatForLog(notification, StringUtil.repeatSymbol(' ', date.length()));
final NotificationType type = notification.getType();
TextAttributesKey key = type == NotificationType.ERROR
@@ -61,7 +61,7 @@ public class NotificationTestAction extends AnAction implements DumbAware {
};
final Notification notification = new Notification(TEST_GROUP_ID, "This is a test notification", //"a",
"You can close this very very very very long notification by clicking <a href=\"close\">this link</a>. Long long long long. It should be long. Very long. Too long. And even longer.",
"You can<br> close this very<p> very very very long notification by clicking <a href=\"close\">this link</a>. Long long long long. It should be long. Very long. Too long. And even longer.",
type, listener);
messageBus.syncPublisher(Notifications.TOPIC).notify(notification);
@@ -212,7 +212,12 @@ final class EditorTabbedContainer implements Disposable, CloseAction.CloseTarget
public ActionCallback removeTabAt(final int componentIndex, int indexToSelect, boolean transferFocus) {
TabInfo toSelect = indexToSelect >= 0 && indexToSelect < myTabs.getTabCount() ? myTabs.getTabAt(indexToSelect) : null;
final ActionCallback callback = myTabs.removeTab(myTabs.getTabAt(componentIndex), toSelect, transferFocus);
final TabInfo info = myTabs.getTabAt(componentIndex);
// removing hidden tab happens on end of drag-out, we've already selected the correct tab for this case in dragOutStarted
if (info.isHidden()) {
toSelect = null;
}
final ActionCallback callback = myTabs.removeTab(info, toSelect, transferFocus);
return myProject.isOpen() ? callback : new ActionCallback.Done();
}
@@ -554,8 +559,12 @@ final class EditorTabbedContainer implements Disposable, CloseAction.CloseTarget
@Override
public void dragOutStarted(MouseEvent mouseEvent, TabInfo info) {
final TabInfo previousSelection = info.getPreviousSelection();
final Image img = myTabs.getComponentImage(info);
info.setHidden(true);
if (previousSelection != null) {
myTabs.select(previousSelection, true);
}
myFile = (VirtualFile)info.getObject();
Presentation presentation = new Presentation(info.getText());
@@ -161,7 +161,7 @@ class StatusPanel extends JPanel {
@Override
public void run() {
assert statusMessage != null;
String text = EventLog.formatForLog(statusMessage.first).status;
String text = EventLog.formatForLog(statusMessage.first, "").status;
if (myDirty || System.currentTimeMillis() - statusMessage.second >= DateFormatUtil.MINUTE) {
myTimeStart = text.length() + 1;
text += " (" + StringUtil.decapitalize(DateFormatUtil.formatPrettyDateTime(statusMessage.second)) + ")";
@@ -17,16 +17,21 @@ package com.intellij.ui;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CustomShortcutSet;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.openapi.wm.ex.ToolWindowManagerAdapter;
import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
import com.intellij.openapi.wm.ex.ToolWindowManagerListener;
import com.intellij.psi.codeStyle.NameUtil;
import com.intellij.ui.speedSearch.SpeedSearchSupply;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
@@ -78,6 +83,23 @@ public abstract class SpeedSearchBase<Comp extends JComponent> extends SpeedSear
}
});
new AnAction() {
@Override
public void actionPerformed(AnActionEvent e) {
final String prefix = getEnteredPrefix();
assert prefix != null;
final String[] strings = NameUtil.splitNameIntoWords(prefix);
final String last = strings[strings.length - 1];
final int i = prefix.lastIndexOf(last);
mySearchPopup.mySearchField.setText(prefix.substring(0, i).trim());
}
@Override
public void update(AnActionEvent e) {
e.getPresentation().setEnabled(isPopupActive() && !StringUtil.isEmpty(getEnteredPrefix()));
}
}.registerCustomShortcutSet(CustomShortcutSet.fromString(SystemInfo.isMac ? "meta BACK_SPACE" : "control BACK_SPACE"), myComponent);
installSupplyTo(component);
}
@@ -276,13 +298,6 @@ public abstract class SpeedSearchBase<Comp extends JComponent> extends SpeedSear
return mySearchPopup != null ? mySearchPopup.mySearchField.getText() : null;
}
public void setEnteredPrefix(@NotNull String text) {
if (mySearchPopup != null) {
mySearchPopup.mySearchField.setText(text);
mySearchPopup.refreshSelection();
}
}
public void refreshSelection() {
if ( mySearchPopup != null ) mySearchPopup.refreshSelection();
}
@@ -269,7 +269,7 @@ templates.surround.no.defined=No surround templates defined in this context
templates.no.defined.with.prefix=No templates starting with ''{0}'' defined in this context
templates.settings.page.title=Live Templates
templates.select.template.chooser.title=Select Template
templates.export.display.name=Code templates
templates.export.display.name=Live templates
templates.dialog.edit.variables.title=Edit Template Variables
templates.dialog.edit.variables.border.title=Variables
templates.dialog.edit.variables.action.move.up=Move &Up
@@ -116,7 +116,7 @@ debugger.valueTooltipAutoShow=true
debugger.valueTooltipAutoShow.description=Auto show tooltip on mouse over
debugger.mayBringFrameToFrontOnBreakpoint=true
debugger.breakpoint.message.full.trace=false
debugger.breakpoint.message.full.trace.description='Log message to console' breakpoint action will out full stacktrace for the trhread that hit the breakpoint
debugger.breakpoint.message.full.trace.description='Log message to console' breakpoint action will out full stacktrace for the thread that hit the breakpoint
filesystem.useNative=true
@@ -30,17 +30,17 @@ class EventLogTest extends LightPlatformTestCase {
}
public void testHtmlEntities() {
def entry = EventLog.formatForLog(new Notification("xxx", "Title", "Hello&nbsp;world&laquo;&raquo;", NotificationType.ERROR))
def entry = format("Title", "Hello&nbsp;world&laquo;&raquo;")
assert entry.message == 'Title: Hello world<<>>'
}
public void testParseMultilineText() {
def entry = EventLog.formatForLog(new Notification("xxx", "Title", "<html><body> " +
def entry = format("Title", "<html><body> " +
"<font size=\"3\">first line<br>" +
"second line<br>" +
"third<br>" +
"<a href=\"create\">Action</a><br>" +
"</body></html>", NotificationType.ERROR))
"</body></html>")
assert entry.status == 'Title: first line second line third // Action'
assert entry.message == '''Title
\tfirst line
@@ -52,13 +52,13 @@ class EventLogTest extends LightPlatformTestCase {
}
public void testInParagraph() {
def entry = EventLog.formatForLog(new Notification("xxx", "Title", "<p>message</p>", NotificationType.ERROR))
def entry = format("Title", "<p>message</p>")
assert entry.message == 'Title: message'
assert entry.status == 'Title: message'
}
public void testJavaSeparators() {
def entry = EventLog.formatForLog(new Notification("xxx", "Title", "fst\nsnd", NotificationType.ERROR))
def entry = format("Title", "fst\nsnd")
assert entry.message == '''Title
\tfst
\tsnd'''
@@ -71,7 +71,7 @@ class EventLogTest extends LightPlatformTestCase {
}
public void testMalformedLink() throws Exception {
def entry = EventLog.formatForLog(new Notification("xxx", '<a href="a">link<a/>', "content", NotificationType.ERROR))
def entry = format('<a href="a">link<a/>', "content")
assert entry.message == 'link: content (show balloon)'
}
@@ -96,7 +96,7 @@ class EventLogTest extends LightPlatformTestCase {
}
EventLog.LogEntry format(String title, String content) {
EventLog.formatForLog(new Notification("xxx", title, content, NotificationType.ERROR))
EventLog.formatForLog(new Notification("xxx", title, content, NotificationType.ERROR), '\t')
}
public void testManyNewlines() throws Exception {
@@ -107,4 +107,14 @@ class EventLogTest extends LightPlatformTestCase {
\tbar'''
}
public void testTeamCityLink() {
def entry = format('title', '''<p>You are assigned for investigation of a test failure<br/>FtlFixesTest.testToplevelVariableLocal (IDEA Trunk), assigned by Roman Shevchenko<br/></p>
<p><a href='#'>Details &raquo;</a></p>''')
assert entry.message == '''title
\tYou are assigned for investigation of a test failure
\tFtlFixesTest.testToplevelVariableLocal (IDEA Trunk), assigned by Roman Shevchenko
\tDetails >>'''
assert entry.links.collect { it.first } == [new TextRange(144, 154)]
}
}
@@ -1,13 +1,17 @@
package com.intellij.openapi.vcs.checkin;
import com.intellij.openapi.vcs.changes.CommitExecutor;
/**
* @author irengrig
* Date: 5/24/11
* Time: 7:23 PM
*/
public interface BeforeCheckinDialogHandler {
public abstract class BeforeCheckinDialogHandler {
/**
* @return false to cancel commit
* @param executors
* @param showVcsCommit
*/
boolean beforeCommitDialogShownCallback();
public abstract boolean beforeCommitDialogShownCallback(Iterable<CommitExecutor> executors, boolean showVcsCommit);
}
@@ -143,8 +143,8 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj
CheckinHandlersManager.getInstance().getMatchingVcsFactories(Arrays.<AbstractVcs>asList(allActiveVcss));
for (BaseCheckinHandlerFactory factory : factoryList) {
final BeforeCheckinDialogHandler handler = factory.createSystemReadyHandler(project);
if (handler != null) {
if (! handler.beforeCommitDialogShownCallback()) return false;
if (handler != null && !handler.beforeCommitDialogShownCallback(Collections.unmodifiableList(executors), showVcsCommit)) {
return false;
}
}
@@ -0,0 +1,40 @@
/*
* 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.android.designer.designSurface;
import com.intellij.android.designer.model.RadViewComponent;
import com.intellij.designer.componentTree.TreeEditOperation;
import com.intellij.designer.designSurface.OperationContext;
import com.intellij.designer.model.RadComponent;
/**
* @author Alexander Lobas
*/
public class TreeOperation extends TreeEditOperation {
public TreeOperation(RadComponent host, OperationContext context) {
super(host, context);
}
@Override
protected boolean canExecute(RadComponent insertBefore) {
return !"TableRow".equals(((RadViewComponent)myHost).getTitle());
}
@Override
protected void execute(RadComponent insertBefore) throws Exception {
System.out.println("Execute(" + myHost + ") insert " + myComponents + " before " + insertBefore);
}
}
@@ -51,6 +51,11 @@ public class RadViewComponent extends RadComponent {
return myTitle;
}
@Override
public String toString() {
return super.toString() + " - " + myTitle;
}
@Override
public Rectangle getBounds() {
return myBounds;
@@ -17,6 +17,8 @@ package com.intellij.android.designer.model;
import com.intellij.android.designer.designSurface.CreateOperation;
import com.intellij.android.designer.designSurface.MoveOperation;
import com.intellij.android.designer.designSurface.TreeOperation;
import com.intellij.designer.componentTree.TreeEditOperation;
import com.intellij.designer.designSurface.ComponentDecorator;
import com.intellij.designer.designSurface.EditOperation;
import com.intellij.designer.designSurface.OperationContext;
@@ -43,6 +45,15 @@ public class RadViewLayout extends RadLayout {
@Override
public EditOperation processChildOperation(OperationContext context) {
if (context.getArea().isTree()) {
if (!myContainer.getChildren().isEmpty() && TreeEditOperation.isTarget(myContainer, context)) {
/*if ("TableRow".equals(myContainer.getTitle())) {
return null;
}*/
return new TreeOperation(myContainer, context);
}
return null;
}
if (context.isMove()) {
return new MoveOperation(context);
}
@@ -55,6 +55,7 @@ gradle.sync.change.type.conflict=Settings conflict
gradle.sync.change.type.unchanged=Unchanged setting
gradle.sync.change.type.confirmed=Confirmed settings diff
gradle.sync.change.entity.type.module=module
gradle.sync.change.entity.type.module.dependency=module dependency
gradle.sync.change.entity.type.library.dependency=library dependency
gradle.sync.change.library.path=library ''{0}'' binary path
gradle.sync.change.project.name.text=project name
+1
View File
@@ -38,6 +38,7 @@
<applicationService serviceInterface="org.jetbrains.plugins.gradle.diff.GradleStructureChangesCalculator"
serviceImplementation="org.jetbrains.plugins.gradle.diff.GradleProjectStructureChangesCalculator"/>
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.diff.GradleModuleStructureChangesCalculator"/>
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.diff.GradleModuleDependencyStructureChangesCalculator"/>
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.diff.GradleLibraryStructureChangesCalculator"/>
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.diff.GradleLibraryDependencyStructureChangesCalculator"/>
@@ -0,0 +1,24 @@
package org.jetbrains.plugins.gradle.diff;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.model.gradle.GradleEntity;
/**
* Manages common dependency properties like 'scope', 'exported'.
* <p/>
* Thread-safe.
*
* @author Denis Zhdanov
* @since 2/20/12 11:17 AM
*/
public abstract class GradleAbstractDependencyStructureChangesCalculator<G extends GradleEntity, I>
implements GradleStructureChangesCalculator<G, I>
{
@Override
public void calculate(@NotNull G gradleEntity, @NotNull I intellijEntity, @NotNull GradleChangesCalculationContext context) {
// TODO den process common dependency properties here.
doCalculate(gradleEntity, intellijEntity, context);
}
protected abstract void doCalculate(@NotNull G gradleEntity, @NotNull I intellijEntity, @NotNull GradleChangesCalculationContext context);
}
@@ -0,0 +1,53 @@
package org.jetbrains.plugins.gradle.diff;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
/**
* <code>'Parameter object'</code> to use during project structure changes calculations.
* <p/>
* Thread-safe.
*/
public class GradleChangesCalculationContext {
@NotNull private final Set<GradleProjectStructureChange> myKnownChanges = new HashSet<GradleProjectStructureChange>();
@NotNull private final Set<GradleProjectStructureChange> myCurrentChanges = new HashSet<GradleProjectStructureChange>();
@NotNull private final PlatformFacade myPlatformFacade;
/**
* @param knownChanges changes between the gradle and intellij project structure that has been known up until now
* @param platformFacade platform facade to use during the calculations
*/
public GradleChangesCalculationContext(@NotNull Set<GradleProjectStructureChange> knownChanges,
@NotNull PlatformFacade platformFacade)
{
myKnownChanges.addAll(knownChanges);
myPlatformFacade = platformFacade;
}
@NotNull
public Set<GradleProjectStructureChange> getKnownChanges() {
return myKnownChanges;
}
@NotNull
public Set<GradleProjectStructureChange> getCurrentChanges() {
return myCurrentChanges;
}
public void register(@NotNull GradleProjectStructureChange change) {
myCurrentChanges.add(change);
}
public boolean hasNewChanges() {
return !myKnownChanges.equals(myCurrentChanges);
}
@NotNull
public PlatformFacade getPlatformFacade() {
return myPlatformFacade;
}
}
@@ -1,11 +1,17 @@
package org.jetbrains.plugins.gradle.diff;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.LibraryOrderEntry;
import com.intellij.openapi.roots.ModuleOrderEntry;
import com.intellij.openapi.roots.OrderEntry;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.model.gradle.*;
import org.jetbrains.plugins.gradle.model.intellij.IntellijEntityVisitor;
import org.jetbrains.plugins.gradle.util.GradleUtil;
import java.util.*;
import java.util.HashMap;
import java.util.Map;
/**
* Contains various utility methods for building changes between the gradle and intellij project structures.
@@ -25,10 +31,10 @@ public class GradleDiffUtil {
* Example: particular module has been added at the gradle side. We want to mark that module, its content root(s), dependencies etc
* as gradle-local changes.
*
* @param entity target gradle-local entity
* @param currentChanges holder for the changes built during the current call
* @param entity target gradle-local entity
* @param context changes calculation context to use
*/
public static void buildLocalChanges(@NotNull GradleEntity entity, @NotNull final Set<GradleProjectStructureChange> currentChanges) {
public static void buildLocalChanges(@NotNull GradleEntity entity, @NotNull final GradleChangesCalculationContext context) {
entity.invite(new GradleEntityVisitor() {
@Override
public void visit(@NotNull GradleProject project) {
@@ -37,7 +43,7 @@ public class GradleDiffUtil {
@Override
public void visit(@NotNull GradleModule module) {
currentChanges.add(new GradleModulePresenceChange(module, null));
context.register(new GradleModulePresenceChange(module, null));
for (GradleDependency dependency : module.getDependencies()) {
dependency.invite(this);
}
@@ -55,59 +61,56 @@ public class GradleDiffUtil {
@Override
public void visit(@NotNull GradleModuleDependency dependency) {
// TODO den implement
context.register(new GradleModuleDependencyPresenceChange(dependency, null));
}
@Override
public void visit(@NotNull GradleLibraryDependency dependency) {
currentChanges.add(new GradleLibraryDependencyPresenceChange(dependency, null));
context.register(new GradleLibraryDependencyPresenceChange(dependency, null));
}
});
}
/**
* Analogues to {@link #buildLocalChanges} but targets intellij entity.
*
* @param module target intellij-local module that doesn't present at the gradle side
* @param currentChanges holder for the changes built during the current call
*/
public static void buildLocalChanges(@NotNull Module module,
@NotNull Set<GradleProjectStructureChange> currentChanges)
{
currentChanges.add(new GradleModulePresenceChange(null, module));
// TODO den process module sub-entities here (content roots and dependencies).
}
/**
* Analogues to {@link #buildLocalChanges} but targets intellij entity.
*
* @param libraryDependency target intellij-local library dependency that doesn't present at the gradle side
* @param currentChanges holder for the changes built during the current call
*/
public static void buildLocalChanges(@NotNull LibraryOrderEntry libraryDependency,
@NotNull Set<GradleProjectStructureChange> currentChanges)
{
final String libraryName = libraryDependency.getLibraryName();
if (libraryName != null) {
currentChanges.add(new GradleLibraryDependencyPresenceChange(null, libraryDependency));
}
}
/**
* Performs argument type-based dispatch and delegates to one of strongly typed <code>'buildLocalChanges()'</code> methods.
*
* @param entity target intellij-local entity that doesn't present at the gradle side
* @param currentChanges holder for the changes built during the current call
* @param entity target intellij-local entity that doesn't present at the gradle side
* @param context changes calculation context to use
*/
public static void buildLocalChanges(@NotNull Object entity, @NotNull Set<GradleProjectStructureChange> currentChanges) {
public static void buildLocalChanges(@NotNull Object entity, @NotNull final GradleChangesCalculationContext context) {
if (entity instanceof GradleEntity) {
buildLocalChanges((GradleEntity)entity, currentChanges);
buildLocalChanges((GradleEntity)entity, context);
}
else if (entity instanceof Module) {
buildLocalChanges((Module)entity, currentChanges);
}
else if (entity instanceof LibraryOrderEntry) {
buildLocalChanges((LibraryOrderEntry)entity, currentChanges);
else {
GradleUtil.dispatch(entity, new IntellijEntityVisitor() {
@Override
public void visit(@NotNull Project project) {
}
@Override
public void visit(@NotNull Module module) {
context.register(new GradleModulePresenceChange(null, module));
for (OrderEntry entry : context.getPlatformFacade().getOrderEntries(module)) {
GradleUtil.dispatch(entry, this);
}
}
@Override
public void visit(@NotNull LibraryOrderEntry libraryDependency) {
final String libraryName = libraryDependency.getLibraryName();
if (libraryName != null) {
context.register(new GradleLibraryDependencyPresenceChange(null, libraryDependency));
}
}
@Override
public void visit(@NotNull ModuleOrderEntry moduleDependency) {
final Module module = moduleDependency.getModule();
if (module != null) {
context.register(new GradleModuleDependencyPresenceChange(null, moduleDependency));
}
}
});
}
}
@@ -120,8 +123,7 @@ public class GradleDiffUtil {
* @param calculator comparison strategy that works with the single entities (not collection of entities)
* @param gradleEntities entities available at the gradle side
* @param intellijEntities entities available at the intellij side
* @param knownChanges collection that contains known changes about the entities
* @param currentChanges holder for the changes discovered during the current call
* @param context changes calculation context
* @param <I> target intellij entity type
* @param <G> target gradle entity type
*/
@@ -129,8 +131,7 @@ public class GradleDiffUtil {
@NotNull GradleStructureChangesCalculator<G, I> calculator,
@NotNull Iterable<? extends G> gradleEntities,
@NotNull Iterable<? extends I> intellijEntities,
@NotNull Set<GradleProjectStructureChange> knownChanges,
@NotNull Set<GradleProjectStructureChange> currentChanges)
@NotNull GradleChangesCalculationContext context)
{
Map<Object, I> intellijEntitiesByKeys = new HashMap<Object, I>();
for (I entity : intellijEntities) {
@@ -138,17 +139,17 @@ public class GradleDiffUtil {
assert previous == null;
}
for (G gradleEntity: gradleEntities) {
I intellijEntity = intellijEntitiesByKeys.remove(calculator.getGradleKey(gradleEntity, knownChanges));
I intellijEntity = intellijEntitiesByKeys.remove(calculator.getGradleKey(gradleEntity, context));
if (intellijEntity == null) {
buildLocalChanges(gradleEntity, currentChanges);
buildLocalChanges(gradleEntity, context);
}
else {
calculator.calculate(gradleEntity, intellijEntity, knownChanges, currentChanges);
calculator.calculate(gradleEntity, intellijEntity, context);
}
}
for (I entity : intellijEntitiesByKeys.values()) {
buildLocalChanges(entity, currentChanges);
buildLocalChanges(entity, context);
}
}
}
@@ -5,14 +5,12 @@ import com.intellij.openapi.roots.libraries.Library;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.model.gradle.GradleLibraryDependency;
import java.util.Set;
/**
* @author Denis Zhdanov
* @since 1/24/12 1:37 PM
*/
public class GradleLibraryDependencyStructureChangesCalculator
implements GradleStructureChangesCalculator<GradleLibraryDependency, LibraryOrderEntry>
extends GradleAbstractDependencyStructureChangesCalculator<GradleLibraryDependency, LibraryOrderEntry>
{
private final GradleLibraryStructureChangesCalculator myLibraryCalculator;
@@ -22,28 +20,30 @@ public class GradleLibraryDependencyStructureChangesCalculator
}
@Override
public void calculate(@NotNull GradleLibraryDependency gradleEntity,
@NotNull LibraryOrderEntry intellijEntity,
@NotNull Set<GradleProjectStructureChange> knownChanges,
@NotNull Set<GradleProjectStructureChange> currentChanges)
public void doCalculate(@NotNull GradleLibraryDependency gradleEntity,
@NotNull LibraryOrderEntry intellijEntity,
@NotNull GradleChangesCalculationContext context)
{
final Library library = intellijEntity.getLibrary();
if (library == null) {
return;
}
myLibraryCalculator.calculate(gradleEntity.getTarget(), library, knownChanges, currentChanges);
myLibraryCalculator.calculate(gradleEntity.getTarget(), library, context);
}
@NotNull
@Override
public Object getIntellijKey(@NotNull LibraryOrderEntry entity) {
final String result = entity.getLibraryName();
return result == null ? "" : result;
final Library library = entity.getLibrary();
if (library == null) {
return "";
}
return myLibraryCalculator.getIntellijKey(library);
}
@NotNull
@Override
public Object getGradleKey(@NotNull GradleLibraryDependency entity, @NotNull Set<GradleProjectStructureChange> knownChanges) {
return myLibraryCalculator.getGradleKey(entity.getTarget(), knownChanges);
public Object getGradleKey(@NotNull GradleLibraryDependency entity, @NotNull GradleChangesCalculationContext context) {
return myLibraryCalculator.getGradleKey(entity.getTarget(), context);
}
}
@@ -25,20 +25,20 @@ public class GradleLibraryStructureChangesCalculator implements GradleStructureC
@Override
public void calculate(@NotNull GradleLibrary gradleEntity,
@NotNull Library intellijEntity,
@NotNull Set<GradleProjectStructureChange> knownChanges,
@NotNull Set<GradleProjectStructureChange> currentChanges)
@NotNull GradleChangesCalculationContext context)
{
final Set<String> gradleBinaryPaths = new HashSet<String>(gradleEntity.getPaths(LibraryPathType.BINARY));
final Set<String> intellijBinaryPaths = new HashSet<String>();
for (VirtualFile file : intellijEntity.getFiles(OrderRootType.CLASSES)) {
final String path = myPlatformFacade.getLocalFileSystemPath(file);
if (!gradleBinaryPaths.remove(path)) {
currentChanges.add(new GradleMismatchedLibraryPathChange(intellijEntity, null, path));
intellijBinaryPaths.add(path);
}
}
for (String binaryPath : gradleBinaryPaths) {
currentChanges.add(new GradleMismatchedLibraryPathChange(intellijEntity, binaryPath, null));
}
if (!gradleBinaryPaths.equals(intellijBinaryPaths)) {
context.register(new GradleMismatchedLibraryPathChange(intellijEntity, gradleBinaryPaths, intellijBinaryPaths));
}
}
@NotNull
@@ -49,7 +49,7 @@ public class GradleLibraryStructureChangesCalculator implements GradleStructureC
@NotNull
@Override
public Object getGradleKey(@NotNull GradleLibrary entity, @NotNull Set<GradleProjectStructureChange> knownChanges) {
public Object getGradleKey(@NotNull GradleLibrary entity, @NotNull GradleChangesCalculationContext context) {
// TODO den consider the known changes
return entity.getName();
}
@@ -5,17 +5,19 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.util.GradleBundle;
import java.util.Set;
/**
* @author Denis Zhdanov
* @since 2/2/12 1:32 PM
*/
public class GradleMismatchedLibraryPathChange extends GradleAbstractConflictingPropertyChange<String> {
public class GradleMismatchedLibraryPathChange extends GradleAbstractConflictingPropertyChange<Set<String>> {
private final String myLibraryName;
public GradleMismatchedLibraryPathChange(@NotNull Library entity,
@Nullable String gradleValue,
@Nullable String intellijValue)
@Nullable Set<String> gradleValue,
@Nullable Set<String> intellijValue)
throws IllegalArgumentException
{
super(GradleBundle.message("gradle.sync.change.library.path", entity.getName()), gradleValue, intellijValue);
@@ -0,0 +1,43 @@
package org.jetbrains.plugins.gradle.diff;
import com.intellij.openapi.roots.ModuleOrderEntry;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.model.gradle.GradleModuleDependency;
import org.jetbrains.plugins.gradle.model.id.GradleEntityIdMapper;
import org.jetbrains.plugins.gradle.model.id.GradleModuleDependencyId;
import org.jetbrains.plugins.gradle.util.GradleBundle;
/**
* @author Denis Zhdanov
* @since 2/17/12 3:14 PM
*/
public class GradleModuleDependencyPresenceChange extends GradleEntityPresenceChange<GradleModuleDependencyId> {
public GradleModuleDependencyPresenceChange(@Nullable GradleModuleDependency gradle,
@Nullable ModuleOrderEntry intellij)
{
super(GradleBundle.message("gradle.sync.change.entity.type.module.dependency"), of(gradle), of(intellij));
}
@Override
public void invite(@NotNull GradleProjectStructureChangeVisitor visitor) {
visitor.visit(this);
}
@Nullable
private static GradleModuleDependencyId of(@Nullable GradleModuleDependency dependency) {
if (dependency == null) {
return null;
}
return GradleEntityIdMapper.mapEntityToId(dependency);
}
@Nullable
private static GradleModuleDependencyId of(@Nullable ModuleOrderEntry dependency) {
if (dependency == null) {
return null;
}
return GradleEntityIdMapper.mapEntityToId(dependency);
}
}
@@ -0,0 +1,39 @@
package org.jetbrains.plugins.gradle.diff;
import com.intellij.openapi.roots.ModuleOrderEntry;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.model.gradle.GradleModuleDependency;
/**
* @author Denis Zhdanov
* @since 2/20/12 11:10 AM
*/
public class GradleModuleDependencyStructureChangesCalculator
extends GradleAbstractDependencyStructureChangesCalculator<GradleModuleDependency, ModuleOrderEntry>
{
@Override
public void doCalculate(@NotNull GradleModuleDependency gradleEntity,
@NotNull ModuleOrderEntry intellijEntity,
@NotNull GradleChangesCalculationContext context)
{
// Assuming that the modules referenced by the given dependencies are compared independently.
}
@NotNull
@Override
public Object getIntellijKey(@NotNull ModuleOrderEntry entity) {
final String intellijModuleName = entity.getModuleName();
if (intellijModuleName == null) {
return "";
}
return intellijModuleName;
}
@NotNull
@Override
public Object getGradleKey(@NotNull GradleModuleDependency entity, @NotNull GradleChangesCalculationContext context) {
// TODO den consider known changes here.
return entity.getTarget().getName();
}
}
@@ -16,13 +16,15 @@
package org.jetbrains.plugins.gradle.diff;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.LibraryOrderEntry;
import com.intellij.openapi.roots.ModuleOrderEntry;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.RootPolicy;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.model.gradle.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* Encapsulates functionality of calculating changes between Gradle and IntelliJ IDEA module hierarchies.
@@ -34,25 +36,24 @@ import java.util.Set;
*/
public class GradleModuleStructureChangesCalculator implements GradleStructureChangesCalculator<GradleModule, Module> {
private final GradleLibraryDependencyStructureChangesCalculator myLibraryDependencyCalculator;
private final PlatformFacade myStructureHelper;
@NotNull private final GradleLibraryDependencyStructureChangesCalculator myLibraryDependencyCalculator;
@NotNull private final GradleModuleDependencyStructureChangesCalculator myModuleDependencyCalculator;
public GradleModuleStructureChangesCalculator(@NotNull GradleLibraryDependencyStructureChangesCalculator libraryDependencyCalculator,
@NotNull PlatformFacade structureHelper)
@NotNull GradleModuleDependencyStructureChangesCalculator moduleDependencyCalculator)
{
myLibraryDependencyCalculator = libraryDependencyCalculator;
myStructureHelper = structureHelper;
myModuleDependencyCalculator = moduleDependencyCalculator;
}
@Override
public void calculate(@NotNull GradleModule gradleEntity,
@NotNull Module intellijEntity,
@NotNull Set<GradleProjectStructureChange> knownChanges,
@NotNull Set<GradleProjectStructureChange> currentChanges)
@NotNull GradleChangesCalculationContext context)
{
//TODO den process module-local settings
//TODO den process content roots
checkDependencies(gradleEntity, intellijEntity, knownChanges, currentChanges);
checkDependencies(gradleEntity, intellijEntity, context);
}
@NotNull
@@ -63,15 +64,14 @@ public class GradleModuleStructureChangesCalculator implements GradleStructureCh
@NotNull
@Override
public Object getGradleKey(@NotNull GradleModule entity, @NotNull Set<GradleProjectStructureChange> knownChanges) {
public Object getGradleKey(@NotNull GradleModule entity, @NotNull GradleChangesCalculationContext context) {
// TODO den consider the known changes
return entity.getName();
}
private void checkDependencies(@NotNull GradleModule gradleModule,
@NotNull Module intellijModule,
@NotNull Set<GradleProjectStructureChange> knownChanges,
@NotNull Set<GradleProjectStructureChange> currentChanges)
@NotNull GradleChangesCalculationContext context)
{
// Prepare intellij part.
final List<ModuleOrderEntry> intellijModuleDependencies = new ArrayList<ModuleOrderEntry>();
@@ -89,7 +89,7 @@ public class GradleModuleStructureChangesCalculator implements GradleStructureCh
return libraryOrderEntry;
}
};
for (OrderEntry orderEntry : myStructureHelper.getOrderEntries(intellijModule)) {
for (OrderEntry orderEntry : context.getPlatformFacade().getOrderEntries(intellijModule)) {
orderEntry.accept(policy, null);
}
@@ -112,8 +112,7 @@ public class GradleModuleStructureChangesCalculator implements GradleStructureCh
}
// Calculate changes.
// TODO den process module dependencies here as well.
GradleDiffUtil.calculate(myLibraryDependencyCalculator, gradleLibraryDependencies, intellijLibraryDependencies,
knownChanges, currentChanges);
GradleDiffUtil.calculate(myLibraryDependencyCalculator, gradleLibraryDependencies, intellijLibraryDependencies, context);
GradleDiffUtil.calculate(myModuleDependencyCalculator, gradleModuleDependencies, intellijModuleDependencies, context);
}
}
@@ -28,5 +28,6 @@ public interface GradleProjectStructureChangeVisitor {
void visit(@NotNull GradleLanguageLevelChange change);
void visit(@NotNull GradleModulePresenceChange change);
void visit(@NotNull GradleLibraryDependencyPresenceChange change);
void visit(@NotNull GradleModuleDependencyPresenceChange change);
void visit(@NotNull GradleMismatchedLibraryPathChange change);
}
@@ -1,45 +0,0 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.gradle.diff;
import org.jetbrains.annotations.NotNull;
/**
* @author Denis Zhdanov
* @since 11/16/11 8:49 PM
*/
public class GradleProjectStructureChangeVisitorAdapter implements GradleProjectStructureChangeVisitor {
@Override
public void visit(@NotNull GradleProjectRenameChange change) {
}
@Override
public void visit(@NotNull GradleLanguageLevelChange change) {
}
@Override
public void visit(@NotNull GradleModulePresenceChange change) {
}
@Override
public void visit(@NotNull GradleLibraryDependencyPresenceChange change) {
}
@Override
public void visit(@NotNull GradleMismatchedLibraryPathChange change) {
}
}
@@ -21,25 +21,24 @@ import java.util.Set;
public class GradleProjectStructureChangesCalculator implements GradleStructureChangesCalculator<GradleProject, Project> {
private final GradleModuleStructureChangesCalculator myModuleChangesCalculator;
private final PlatformFacade myStructureHelper;
private final PlatformFacade myPlatformFacade;
public GradleProjectStructureChangesCalculator(@NotNull GradleModuleStructureChangesCalculator moduleCalculator,
@NotNull PlatformFacade structureHelper) {
@NotNull PlatformFacade platformFacade) {
myModuleChangesCalculator = moduleCalculator;
myStructureHelper = structureHelper;
myPlatformFacade = platformFacade;
}
@Override
public void calculate(@NotNull GradleProject gradleEntity,
@NotNull Project intellijEntity,
@NotNull Set<GradleProjectStructureChange> knownChanges,
@NotNull Set<GradleProjectStructureChange> currentChanges)
@NotNull GradleChangesCalculationContext context)
{
calculateProjectChanges(gradleEntity, intellijEntity, currentChanges);
calculateProjectChanges(gradleEntity, intellijEntity, context.getCurrentChanges());
final Set<? extends GradleModule> gradleSubEntities = gradleEntity.getModules();
final Collection<Module> intellijSubEntities = myStructureHelper.getModules(intellijEntity);
GradleDiffUtil.calculate(myModuleChangesCalculator, gradleSubEntities, intellijSubEntities, knownChanges, currentChanges);
final Collection<Module> intellijSubEntities = myPlatformFacade.getModules(intellijEntity);
GradleDiffUtil.calculate(myModuleChangesCalculator, gradleSubEntities, intellijSubEntities, context);
}
@NotNull
@@ -50,7 +49,7 @@ public class GradleProjectStructureChangesCalculator implements GradleStructureC
@NotNull
@Override
public Object getGradleKey(@NotNull GradleProject entity, @NotNull Set<GradleProjectStructureChange> knownChanges) {
public Object getGradleKey(@NotNull GradleProject entity, @NotNull GradleChangesCalculationContext context) {
// TODO den consider the known changes
return entity.getName();
}
@@ -79,7 +78,7 @@ public class GradleProjectStructureChangesCalculator implements GradleStructureC
@NotNull Set<GradleProjectStructureChange> currentChanges)
{
LanguageLevel gradleLevel = gradleProject.getLanguageLevel();
LanguageLevel intellijLevel = myStructureHelper.getLanguageLevel(intellijProject);
LanguageLevel intellijLevel = myPlatformFacade.getLanguageLevel(intellijProject);
if (gradleLevel != intellijLevel) {
currentChanges.add(new GradleLanguageLevelChange(gradleLevel, intellijLevel));
}
@@ -3,8 +3,6 @@ package org.jetbrains.plugins.gradle.diff;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.model.gradle.GradleEntity;
import java.util.Set;
/**
* Defines common interface to the strategy that calculates difference between the corresponding gradle and intellij entities
* (e.g. between the gradle and intellij module).
@@ -20,18 +18,12 @@ public interface GradleStructureChangesCalculator<G extends GradleEntity, I> {
/**
* Calculates changes between the given entities.
*
*
* @param gradleEntity target gradle entity
* @param intellijEntity target intellij entity
* @param knownChanges changes between the gradle and intellij project structure that has been known up until now
* @param currentChanges holder for the changes between the given entities discovered by the current call. Note that
* it must contain the change objects that have been known (contained at the <code>'knownChanges'</code>)
* but are still in place
* @param context target diff calculation context
*/
void calculate(@NotNull G gradleEntity,
@NotNull I intellijEntity,
@NotNull Set<GradleProjectStructureChange> knownChanges,
@NotNull Set<GradleProjectStructureChange> currentChanges);
void calculate(@NotNull G gradleEntity, @NotNull I intellijEntity, @NotNull GradleChangesCalculationContext context);
/**
* There are three possible situations when we compare a set of gradle entities with a set of intellij entities:
@@ -43,16 +35,16 @@ public interface GradleStructureChangesCalculator<G extends GradleEntity, I> {
* </ul>
* </pre>
* <p/>
* The general idea is to map evey item at the given sets of gradle and intellij entities to particular key (both gradle and
* The general idea is to map every item at the given sets of gradle and intellij entities to particular key (both gradle and
* intellij keys are expected to belong to the same class) and then compare them. Matched keys shows that corresponding
* entities should be {@link #calculate(GradleEntity, Object, Set, Set)} compared to each other}; non-matched indicate that corresponding
* entities are gradle- or intellij-local.
* entities should be {@link #calculate(GradleEntity, Object, GradleChangesCalculationContext) compared to each other};
* non-matched indicate that corresponding entities are gradle- or intellij-local.
* <p/>
* This method allows to match intellij entity to the target key.
*
* @param entity intellij entity to match
* @return key for the given entity
* @see #getGradleKey(GradleEntity, Set)
* @see #getGradleKey(GradleEntity, GradleChangesCalculationContext)
*/
@NotNull
Object getIntellijKey(@NotNull I entity);
@@ -68,10 +60,10 @@ public interface GradleStructureChangesCalculator<G extends GradleEntity, I> {
* So, we take into consideration the known changes only during {@code gradle-entity -> key} processing.
*
* @param entity target gradle entity that should be mapped to a key
* @param knownChanges known changes between the gradle and intellij structures
* @param context changes calculation context
* @return key for the given entity
* @see #getIntellijKey(Object)
*/
@NotNull
Object getGradleKey(@NotNull G entity, @NotNull Set<GradleProjectStructureChange> knownChanges);
Object getGradleKey(@NotNull G entity, @NotNull GradleChangesCalculationContext context);
}
@@ -11,7 +11,7 @@ import javax.swing.*;
*/
public enum GradleEntityType {
PROJECT(GradleIcons.PROJECT_ICON), MODULE(GradleIcons.MODULE_ICON), MODULE_DEPENDENCY(GradleIcons.MODULE_ICON),
LIBRARY_DEPENDENCY(GradleIcons.LIB_ICON), CONTENT_ROOT(GradleIcons.CONTENT_ROOT_ICON), SYNTHETIC(null);
LIBRARY(GradleIcons.LIB_ICON), LIBRARY_DEPENDENCY(GradleIcons.LIB_ICON), CONTENT_ROOT(GradleIcons.CONTENT_ROOT_ICON), SYNTHETIC(null);
@Nullable private final Icon myIcon;
@@ -89,6 +89,10 @@ public class GradleModule extends AbstractNamedGradleEntity implements Named {
myDependencies.add(dependency);
}
public void clearDependencies() {
myDependencies.clear();
}
@Override
public void invite(@NotNull GradleEntityVisitor visitor) {
visitor.visit(this);
@@ -0,0 +1,55 @@
package org.jetbrains.plugins.gradle.model.id;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.model.GradleEntityOwner;
import org.jetbrains.plugins.gradle.model.GradleEntityType;
/**
* @author Denis Zhdanov
* @since 2/20/12 12:01 PM
*/
public abstract class GradleAbstractDependencyId extends GradleAbstractEntityId {
@NotNull private final String myOwnerModuleName;
@NotNull private final String myDependencyName;
public GradleAbstractDependencyId(@NotNull GradleEntityType type,
@NotNull GradleEntityOwner owner,
@NotNull String ownerModuleName,
@NotNull String dependencyName)
{
super(type, owner);
myOwnerModuleName = ownerModuleName;
myDependencyName = dependencyName;
}
@NotNull
public String getOwnerModuleName() {
return myOwnerModuleName;
}
@NotNull
public String getDependencyName() {
return myDependencyName;
}
@NotNull
public GradleModuleId getOwnerModuleId() {
return new GradleModuleId(getOwner(), myOwnerModuleName);
}
@Override
public int hashCode() {
int result = 31 * super.hashCode() + myOwnerModuleName.hashCode();
return 31 * result + myDependencyName.hashCode();
}
@Override
public boolean equals(Object o) {
if (!super.equals(o)) {
return false;
}
GradleAbstractDependencyId that = (GradleAbstractDependencyId)o;
return myOwnerModuleName.equals(that.myOwnerModuleName) && myDependencyName.equals(that.myDependencyName);
}
}
@@ -59,7 +59,7 @@ public class GradleEntityIdMapper {
@Override
public void visit(@NotNull GradleModuleDependency dependency) {
result.set(new GradleLibraryDependencyId(GradleEntityOwner.GRADLE, dependency.getOwnerModule().getName(), dependency.getName()));
result.set(new GradleModuleDependencyId(GradleEntityOwner.GRADLE, dependency.getOwnerModule().getName(), dependency.getName()));
}
@Override
@@ -74,7 +74,7 @@ public class GradleEntityIdMapper {
@Override
public void visit(@NotNull GradleLibrary library) {
// TODO den implement
result.set(new GradleLibraryId(GradleEntityOwner.GRADLE, library.getName()));
}
});
}
@@ -8,60 +8,26 @@ import org.jetbrains.plugins.gradle.model.GradleEntityType;
* @author Denis Zhdanov
* @since 2/14/12 1:59 PM
*/
public class GradleLibraryDependencyId extends GradleAbstractEntityId {
public class GradleLibraryDependencyId extends GradleAbstractDependencyId {
@NotNull private final String myModuleName;
@NotNull private final String myLibraryName;
public GradleLibraryDependencyId(@NotNull GradleEntityOwner owner, @NotNull String moduleName, @NotNull String libraryName) {
super(GradleEntityType.LIBRARY_DEPENDENCY, owner);
myModuleName = moduleName;
myLibraryName = libraryName;
super(GradleEntityType.LIBRARY_DEPENDENCY, owner, moduleName, libraryName);
}
@NotNull
public String getModuleName() {
return myModuleName;
}
@NotNull
public String getLibraryName() {
return myLibraryName;
}
@NotNull
public GradleModuleId getModuleId() {
return new GradleModuleId(getOwner(), myModuleName);
}
@Override
public Object mapToEntity(@NotNull GradleEntityMappingContext context) {
switch (getOwner()) {
case GRADLE: return context.getProjectStructureHelper().findGradleLibraryDependency(myModuleName, myLibraryName);
case INTELLIJ: return context.getProjectStructureHelper().findIntellijLibraryDependency(myModuleName, myLibraryName);
case GRADLE: return context.getProjectStructureHelper().findGradleLibraryDependency(getOwnerModuleName(), getDependencyName());
case INTELLIJ: return context.getProjectStructureHelper().findIntellijLibraryDependency(getOwnerModuleName(), getDependencyName());
}
throw new IllegalStateException(String.format(
"Can't map id to the target library dependency. Owner: %s, module: '%s', library: '%s'", getOwner(), myModuleName, myLibraryName
"Can't map id to the target library dependency. Owner: %s, module: '%s', library: '%s'",
getOwner(), getOwnerModuleName(), getDependencyName()
));
}
@Override
public int hashCode() {
int result = 31 * super.hashCode() + myModuleName.hashCode();
return 31 * result + myLibraryName.hashCode();
}
@Override
public boolean equals(Object o) {
if (!super.equals(o)) {
return false;
}
GradleLibraryDependencyId that = (GradleLibraryDependencyId)o;
return myModuleName.equals(that.myModuleName) && myLibraryName.equals(that.myLibraryName);
}
@Override
public String toString() {
return String.format("library dependency:owner module='%s'|library='%s'", myModuleName, myLibraryName);
return String.format("library dependency:owner module='%s'|library='%s'", getOwnerModuleName(), getDependencyName());
}
}
@@ -0,0 +1,49 @@
package org.jetbrains.plugins.gradle.model.id;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.model.GradleEntityOwner;
import org.jetbrains.plugins.gradle.model.GradleEntityType;
/**
* @author Denis Zhdanov
* @since 2/20/12 7:12 PM
*/
public class GradleLibraryId extends GradleAbstractEntityId {
@NotNull private final String myLibraryName;
public GradleLibraryId(@NotNull GradleEntityOwner owner, @NotNull String libraryName) {
super(GradleEntityType.LIBRARY, owner);
myLibraryName = libraryName;
}
@Override
public Object mapToEntity(@NotNull GradleEntityMappingContext context) {
switch (getOwner()) {
case GRADLE: return context.getProjectStructureHelper().findGradleLibrary(myLibraryName);
case INTELLIJ: return context.getProjectStructureHelper().findIntellijLibrary(myLibraryName);
}
throw new IllegalStateException(String.format(
"Can't map library id to the target library. Id owner: %s, name: '%s'", getOwner(), myLibraryName
));
}
@Override
public int hashCode() {
return 31 * super.hashCode() + myLibraryName.hashCode();
}
@Override
public boolean equals(Object o) {
if (!super.equals(o)) {
return false;
}
GradleLibraryId that = (GradleLibraryId)o;
return myLibraryName.equals(that.myLibraryName);
}
@Override
public String toString() {
return "library '" + myLibraryName + "'";
}
}
@@ -8,46 +8,26 @@ import org.jetbrains.plugins.gradle.model.GradleEntityType;
* @author Denis Zhdanov
* @since 2/14/12 2:06 PM
*/
public class GradleModuleDependencyId extends GradleAbstractEntityId {
public class GradleModuleDependencyId extends GradleAbstractDependencyId {
@NotNull private final String myOwnerModuleName;
@NotNull private final String myDependencyModuleName;
public GradleModuleDependencyId(@NotNull GradleEntityOwner owner, @NotNull String ownerModuleName, @NotNull String dependencyModuleName) {
super(GradleEntityType.MODULE, owner);
myOwnerModuleName = ownerModuleName;
myDependencyModuleName = dependencyModuleName;
super(GradleEntityType.MODULE_DEPENDENCY, owner, ownerModuleName, dependencyModuleName);
}
@Override
public Object mapToEntity(@NotNull GradleEntityMappingContext context) {
switch (getOwner()) {
case GRADLE: return context.getProjectStructureHelper().findGradleModuleDependency(myOwnerModuleName, myDependencyModuleName);
case INTELLIJ: return context.getProjectStructureHelper().findIntellijModuleDependency(myOwnerModuleName, myDependencyModuleName);
case GRADLE: return context.getProjectStructureHelper().findGradleModuleDependency(getOwnerModuleName(), getDependencyName());
case INTELLIJ: return context.getProjectStructureHelper().findIntellijModuleDependency(getOwnerModuleName(), getDependencyName());
}
throw new IllegalStateException(String.format(
"Can't map id to the target module dependency. Owner: %s, owner module: '%s', dependency module: '%s'",
getOwner(), myOwnerModuleName, myDependencyModuleName
getOwner(), getOwnerModuleName(), getDependencyName()
));
}
@Override
public int hashCode() {
int result = 31 * super.hashCode() + myOwnerModuleName.hashCode();
return 31 * result + myDependencyModuleName.hashCode();
}
@Override
public boolean equals(Object o) {
if (!super.equals(o)) {
return false;
}
GradleModuleDependencyId that = (GradleModuleDependencyId)o;
return myOwnerModuleName.equals(that.myOwnerModuleName) && myDependencyModuleName.equals(that.myDependencyModuleName);
}
@Override
public String toString() {
return String.format("module dependency:owner module='%s'|dependency module='%s'", myOwnerModuleName, myDependencyModuleName);
return String.format("module dependency:owner module='%s'|dependency module='%s'", getOwnerModuleName(), getDependencyName());
}
}
@@ -46,4 +46,9 @@ public class GradleModuleId extends GradleAbstractEntityId {
GradleModuleId that = (GradleModuleId)o;
return myModuleName.equals(that.myModuleName);
}
@Override
public String toString() {
return "module '" + myModuleName + "'";
}
}
@@ -1,11 +1,13 @@
package org.jetbrains.plugins.gradle.sync;
import com.intellij.ProjectTopics;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootEvent;
import com.intellij.openapi.roots.ModuleRootListener;
import com.intellij.util.Alarm;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.util.GradleUtil;
@@ -59,10 +61,25 @@ public class GradleProjectStructureChangesDetector extends AbstractProjectCompon
myAlarm.cancelAllRequests();
final long diff = System.currentTimeMillis() - myStartRefreshTime.get();
if (diff < 0) {
myAlarm.cancelAllRequests();
myAlarm.addRequest(this, (int)-diff);
return;
}
GradleUtil.refreshProject(myProject);
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
if (ModalityState.current() != ModalityState.NON_MODAL) {
// There is a possible case that user performs intellij project structure modification and 'project settings' dialog
// is open. We want to perform the refresh when the editing is completely finished then.
myAlarm.cancelAllRequests();
myAlarm.addRequest(RefreshRequest.this, REFRESH_DELAY_MILLIS);
return;
}
GradleUtil.refreshProject(myProject);
}
});
}
}
}
@@ -4,8 +4,10 @@ import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.diff.GradleChangesCalculationContext;
import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChange;
import org.jetbrains.plugins.gradle.diff.GradleStructureChangesCalculator;
import org.jetbrains.plugins.gradle.diff.PlatformFacade;
import org.jetbrains.plugins.gradle.model.gradle.GradleProject;
import java.util.HashSet;
@@ -28,14 +30,17 @@ public class GradleProjectStructureChangesModel extends AbstractProjectComponent
= new AtomicReference<Set<GradleProjectStructureChange>>(new HashSet<GradleProjectStructureChange>());
private final AtomicReference<GradleProject> myGradleProject = new AtomicReference<GradleProject>();
private final GradleStructureChangesCalculator<GradleProject, Project> myChangesCalculator;
@NotNull private final GradleStructureChangesCalculator<GradleProject, Project> myChangesCalculator;
@NotNull private final PlatformFacade myPlatformFacade;
public GradleProjectStructureChangesModel(@NotNull Project project,
@NotNull GradleStructureChangesCalculator<GradleProject, Project> changesCalculator)
@NotNull GradleStructureChangesCalculator<GradleProject, Project> changesCalculator,
@NotNull PlatformFacade platformFacade)
{
super(project);
myChangesCalculator = changesCalculator;
myPlatformFacade = platformFacade;
}
/**
@@ -58,15 +63,14 @@ public class GradleProjectStructureChangesModel extends AbstractProjectComponent
*/
public void update(@NotNull GradleProject gradleProject) {
myGradleProject.set(gradleProject);
Set<GradleProjectStructureChange> knownChanges = new HashSet<GradleProjectStructureChange>(myChanges.get());
Set<GradleProjectStructureChange> currentChanges = new HashSet<GradleProjectStructureChange>();
myChangesCalculator.calculate(gradleProject, myProject, knownChanges, currentChanges);
if (currentChanges.equals(knownChanges)) {
GradleChangesCalculationContext context = new GradleChangesCalculationContext(myChanges.get(), myPlatformFacade);
myChangesCalculator.calculate(gradleProject, myProject, context);
if (!context.hasNewChanges()) {
return;
}
myChanges.set(currentChanges);
myChanges.set(context.getCurrentChanges());
for (GradleProjectStructureChangeListener listener : myListeners) {
listener.onChanges(knownChanges, currentChanges);
listener.onChanges(context.getKnownChanges(), context.getCurrentChanges());
}
}
@@ -49,8 +49,8 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
myTreeModel.update(currentChanges);
myTreeModel.processObsoleteChanges(ContainerUtil.subtract(oldChanges, currentChanges));
myTreeModel.processCurrentChanges(currentChanges);
}
});
}
@@ -15,6 +15,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.diff.PlatformFacade;
import org.jetbrains.plugins.gradle.model.gradle.*;
import org.jetbrains.plugins.gradle.model.id.GradleLibraryDependencyId;
import org.jetbrains.plugins.gradle.model.id.GradleModuleDependencyId;
/**
* Thread-safe.
@@ -49,23 +50,7 @@ public class GradleProjectStructureHelper extends AbstractProjectComponent {
* <code>false</code> otherwise
*/
public boolean isIntellijLibraryDependencyExist(@NotNull final GradleLibraryDependencyId id) {
final Module module = findIntellijModule(id.getModuleName());
if (module == null) {
return false;
}
RootPolicy<Boolean> visitor = new RootPolicy<Boolean>() {
@Override
public Boolean visitLibraryOrderEntry(LibraryOrderEntry libraryOrderEntry, Boolean value) {
return id.getLibraryName().equals(libraryOrderEntry.getLibraryName());
}
};
for (OrderEntry entry : myFacade.getOrderEntries(module)) {
if (entry.accept(visitor, false)) {
return true;
}
}
return false;
return findIntellijLibraryDependency(id.getOwnerModuleName(), id.getDependencyName()) != null;
}
/**
@@ -76,7 +61,15 @@ public class GradleProjectStructureHelper extends AbstractProjectComponent {
* <code>false</code> otherwise
*/
public boolean isGradleLibraryDependencyExist(@NotNull final GradleLibraryDependencyId id) {
return findGradleLibraryDependency(id.getModuleName(), id.getLibraryName()) != null;
return findGradleLibraryDependency(id.getOwnerModuleName(), id.getDependencyName()) != null;
}
public boolean isIntellijModuleDependencyExist(@NotNull final GradleModuleDependencyId id) {
return findIntellijModuleDependency(id.getOwnerModuleName(), id.getDependencyName()) != null;
}
public boolean isGradleModuleDependencyExist(@NotNull final GradleModuleDependencyId id) {
return findIntellijModuleDependency(id.getOwnerModuleName(), id.getDependencyName()) != null;
}
@Nullable
@@ -111,10 +104,15 @@ public class GradleProjectStructureHelper extends AbstractProjectComponent {
@Nullable
public Library findIntellijLibrary(@NotNull final GradleLibrary library) {
return findIntellijLibrary(library.getName());
}
@Nullable
public Library findIntellijLibrary(@NotNull String libraryName) {
final LibraryTable libraryTable = myFacade.getProjectLibraryTable(myProject);
for (Library intellijLibrary : libraryTable.getLibraries()) {
// TODO den consider 'merged libraries' at the registered project structure changes here.
if (library.getName().equals(intellijLibrary.getName())) {
if (libraryName.equals(intellijLibrary.getName())) {
return intellijLibrary;
}
}
@@ -145,6 +143,20 @@ public class GradleProjectStructureHelper extends AbstractProjectComponent {
}
return null;
}
@Nullable
public GradleLibrary findGradleLibrary(@NotNull final String libraryName) {
final GradleProject project = myModel.getGradleProject();
if (project == null) {
return null;
}
for (GradleLibrary library : project.getLibraries()) {
if (libraryName.equals(library.getName())) {
return library;
}
}
return null;
}
@Nullable
public GradleLibraryDependency findGradleLibraryDependency(@NotNull final String moduleName, @NotNull final String libraryName) {
@@ -92,7 +92,7 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
return value;
}
GradleLibraryDependencyId id = GradleEntityIdMapper.mapEntityToId(libraryOrderEntry);
dependencies.add(buildNode(id, id.getLibraryName()));
dependencies.add(buildNode(id, id.getDependencyName()));
return value;
}
};
@@ -137,6 +137,7 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
GradleProjectStructureNode<GradleModuleId> moduleNode = getModuleNode(id);
GradleProjectStructureNode<GradleSyntheticId> result
= new GradleProjectStructureNode<GradleSyntheticId>(GradleConstants.DEPENDENCIES_NODE_DESCRIPTOR);
result.addListener(myNodeListener);
moduleNode.add(result);
myModuleDependencies.put(id.getModuleName(), result);
@@ -159,7 +160,7 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
*
* @param changes collections that contains all changes between the current gradle and intellij project structures
*/
public void update(@NotNull Collection<GradleProjectStructureChange> changes) {
public void processCurrentChanges(@NotNull Collection<GradleProjectStructureChange> changes) {
for (GradleProjectStructureChange change : changes) {
change.invite(myNewChangesDispatcher);
}
@@ -196,7 +197,7 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
for (GradleProjectStructureNode<GradleSyntheticId> holder : myModuleDependencies.values()) {
for (GradleProjectStructureNode<GradleLibraryDependencyId> dependencyNode : holder.getChildren(GradleLibraryDependencyId.class)) {
final GradleLibraryDependencyId id = dependencyNode.getDescriptor().getElement();
if (change.getLibraryName().equals(id.getLibraryName())) {
if (change.getLibraryName().equals(id.getDependencyName())) {
dependencyNode.addConflictChange(change);
break;
}
@@ -205,26 +206,31 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
}
private void processNewLibraryDependencyPresenceChange(@NotNull GradleLibraryDependencyPresenceChange change) {
GradleLibraryDependencyId id = change.getGradleEntity();
processNewDependencyPresenceChange(change);
}
private void processNewModuleDependencyPresenceChange(@NotNull GradleModuleDependencyPresenceChange change) {
processNewDependencyPresenceChange(change);
}
private <I extends GradleAbstractDependencyId> void processNewDependencyPresenceChange(@NotNull GradleEntityPresenceChange<I> change) {
I id = change.getGradleEntity();
TextAttributesKey attributes = GradleTextAttributes.GRADLE_LOCAL_CHANGE;
if (id == null) {
id = change.getIntellijEntity();
attributes = GradleTextAttributes.INTELLIJ_LOCAL_CHANGE;
}
assert id != null;
final GradleProjectStructureNode<GradleSyntheticId> dependenciesNode = getDependenciesNode(id.getModuleId());
for (GradleProjectStructureNode<GradleLibraryDependencyId> node : dependenciesNode.getChildren(GradleLibraryDependencyId.class)) {
GradleProjectStructureNodeDescriptor<GradleLibraryDependencyId> d = node.getDescriptor();
if (id.equals(d.getElement())) {
d.setAttributes(attributes);
nodeStructureChanged(node);
final GradleProjectStructureNode<GradleSyntheticId> dependenciesNode = getDependenciesNode(id.getOwnerModuleId());
for (GradleProjectStructureNode<? extends GradleAbstractDependencyId> node : dependenciesNode.getChildren(id.getClass())) {
if (id.equals(node.getDescriptor().getElement())) {
node.setAttributes(attributes);
return;
}
}
GradleProjectStructureNode<GradleLibraryDependencyId> newNode = buildNode(id, id.getLibraryName());
newNode.getDescriptor().setAttributes(attributes);
GradleProjectStructureNode<I> newNode = buildNode(id, id.getDependencyName());
dependenciesNode.add(newNode);
nodeStructureChanged(dependenciesNode);
newNode.setAttributes(attributes);
}
private void processNewModulePresenceChange(@NotNull GradleModulePresenceChange change) {
@@ -255,7 +261,7 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
for (GradleProjectStructureNode<GradleSyntheticId> holder : myModuleDependencies.values()) {
for (GradleProjectStructureNode<GradleLibraryDependencyId> node : holder.getChildren(GradleLibraryDependencyId.class)) {
final GradleLibraryDependencyId id = node.getDescriptor().getElement();
if (id.getLibraryName().equals(change.getLibraryName())) {
if (id.getDependencyName().equals(change.getLibraryName())) {
node.removeConflictChange(change);
break;
}
@@ -275,7 +281,25 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
else {
removeNode = !myProjectStructureHelper.isGradleLibraryDependencyExist(id);
}
final GradleProjectStructureNode<GradleSyntheticId> holder = myModuleDependencies.get(id.getModuleName());
processObsoleteDependencyPresenceChange(id, removeNode);
}
private void processObsoleteModuleDependencyPresenceChange(@NotNull GradleModuleDependencyPresenceChange change) {
GradleModuleDependencyId id = change.getGradleEntity();
boolean removeNode;
if (id == null) {
id = change.getIntellijEntity();
assert id != null;
removeNode = !myProjectStructureHelper.isIntellijModuleDependencyExist(id);
}
else {
removeNode = !myProjectStructureHelper.isGradleModuleDependencyExist(id);
}
processObsoleteDependencyPresenceChange(id, removeNode);
}
private void processObsoleteDependencyPresenceChange(@NotNull GradleAbstractDependencyId id, boolean removeNode) {
final GradleProjectStructureNode<GradleSyntheticId> holder = myModuleDependencies.get(id.getOwnerModuleName());
if (holder == null) {
return;
}
@@ -286,8 +310,8 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
// We should distinguish between those situations because we need to mark the node as 'synced' at one case and
// completely removed at another one.
for (GradleProjectStructureNode<GradleLibraryDependencyId> node : holder.getChildren(GradleLibraryDependencyId.class)) {
GradleProjectStructureNodeDescriptor<GradleLibraryDependencyId> descriptor = node.getDescriptor();
for (GradleProjectStructureNode<? extends GradleAbstractDependencyId> node : holder.getChildren(id.getClass())) {
GradleProjectStructureNodeDescriptor<? extends GradleAbstractDependencyId> descriptor = node.getDescriptor();
if (!id.equals(descriptor.getElement())) {
continue;
}
@@ -304,13 +328,32 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
private void processObsoleteModulePresenceChange(@NotNull GradleModulePresenceChange change) {
GradleModuleId id = change.getGradleEntity();
boolean removeNode;
if (id == null) {
id = change.getIntellijEntity();
assert id != null;
removeNode = myProjectStructureHelper.findIntellijModule(id.getModuleName()) == null;
}
assert id != null;
else {
removeNode = myProjectStructureHelper.findGradleModule(id.getModuleName()) == null;
}
// There are two possible cases why 'module presence' change is obsolete:
// 1. Corresponding module has been added at the counterparty;
// 2. The 'local module' has been removed;
// We should distinguish between those situations because we need to mark the node as 'synced' at one case and
// completely removed at another one.
final GradleProjectStructureNode<GradleModuleId> moduleNode = myModules.get(id.getModuleName());
if (moduleNode != null) {
moduleNode.getDescriptor().setAttributes(GradleTextAttributes.GRADLE_NO_CHANGE);
if (moduleNode == null) {
return;
}
if (removeNode) {
moduleNode.removeFromParent();
}
else {
moduleNode.setAttributes(GradleTextAttributes.GRADLE_NO_CHANGE);
}
}
@@ -323,10 +366,13 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
}
@Override
public void onNodeRemoved(@NotNull GradleProjectStructureNode<?> node, int index) {
myIndexHolder[0] = index;
myNodeHolder[0] = node;
nodesWereRemoved(node.getParent(), myIndexHolder, myNodeHolder);
public void onNodeRemoved(@NotNull GradleProjectStructureNode<?> parent,
@NotNull GradleProjectStructureNode<?> removedChild,
int removedChildIndex)
{
myIndexHolder[0] = removedChildIndex;
myNodeHolder[0] = removedChild;
nodesWereRemoved(parent, myIndexHolder, myNodeHolder);
}
@Override
@@ -340,6 +386,7 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
@Override public void visit(@NotNull GradleLanguageLevelChange change) { processNewLanguageLevelChange(change); }
@Override public void visit(@NotNull GradleModulePresenceChange change) { processNewModulePresenceChange(change); }
@Override public void visit(@NotNull GradleLibraryDependencyPresenceChange change) { processNewLibraryDependencyPresenceChange(change); }
@Override public void visit(@NotNull GradleModuleDependencyPresenceChange change) { processNewModuleDependencyPresenceChange(change); }
@Override public void visit(@NotNull GradleMismatchedLibraryPathChange change) { processNewMismatchedLibraryPathChange(change); }
}
@@ -350,6 +397,9 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
@Override public void visit(@NotNull GradleLibraryDependencyPresenceChange change) {
processObsoleteLibraryDependencyPresenceChange(change);
}
@Override public void visit(@NotNull GradleModuleDependencyPresenceChange change) {
processObsoleteModuleDependencyPresenceChange(change);
}
@Override public void visit(@NotNull GradleMismatchedLibraryPathChange change) { processObsoleteMismatchedLibraryPathChange(change); }
}
}
@@ -39,7 +39,7 @@ public class GradleResolveProjectTask extends AbstractGradleTask {
final GradleProject project = resolver.resolveProjectInfo(getId(), myProjectPath, myResolveLibraries);
myGradleProject.set(project);
setState(GradleTaskState.FINISHED);
if (myIntellijProject == null) {
if (myIntellijProject == null || myIntellijProject.isDisposed()) {
return;
}
final GradleProjectStructureChangesModel model = myIntellijProject.getComponent(GradleProjectStructureChangesModel.class);
@@ -70,13 +70,11 @@ public class GradleProjectStructureNode<T extends GradleEntityId> extends Defaul
for (int i = 0; i < getChildCount(); i++) {
GradleProjectStructureNode<?> node = getChildAt(i);
if (NODE_COMPARATOR.compare((GradleProjectStructureNode<?>)newChild, node) <= 0) {
insert(newChild, i);
onNodeAdded((GradleProjectStructureNode<?>)newChild, i);
insert(newChild, i); // Assuming that the node listeners are notified during the nested call.
return;
}
}
super.add(newChild);
onNodeAdded((GradleProjectStructureNode<?>)newChild, getChildCount() - 1);
super.add(newChild); // Assuming that the node listeners are notified during the nested call to 'insert()'.
}
@Override
@@ -105,26 +103,40 @@ public class GradleProjectStructureNode<T extends GradleEntityId> extends Defaul
* Does nothing if given node is not a child of the current node.
*
* @param child target child node
* @return <code>true</code> if child position was changed; <code>false</code> otherwise
*/
public void correctChildPositionIfNecessary(@NotNull GradleProjectStructureNode<?> child) {
public boolean correctChildPositionIfNecessary(@NotNull GradleProjectStructureNode<?> child) {
int currentPosition = -1;
int desiredPosition = getChildCount() - 1;
int desiredPosition = -1;
for (int i = 0; i < getChildCount(); i++) {
GradleProjectStructureNode<?> node = getChildAt(i);
if (node == child) {
currentPosition = i;
continue;
}
if (NODE_COMPARATOR.compare(child, node) <= 0) {
if (desiredPosition < 0 && NODE_COMPARATOR.compare(child, node) <= 0) {
desiredPosition = i;
if (currentPosition >= 0) {
break;
}
}
}
if (currentPosition < 0) {
// Given node is not a child of the current node.
return;
return false;
}
if (desiredPosition < 0) {
desiredPosition = getChildCount();
}
if (currentPosition < desiredPosition) {
desiredPosition--;
}
if (currentPosition == desiredPosition) {
return false;
}
remove(currentPosition);
insert(child, desiredPosition);
return true;
}
/**
@@ -145,7 +157,12 @@ public class GradleProjectStructureNode<T extends GradleEntityId> extends Defaul
*/
public void addConflictChange(@NotNull GradleProjectStructureChange change) {
myConflictChanges.add(change);
if (myConflictChanges.size() == 1) {
if (myConflictChanges.size() != 1) {
return;
}
final TextAttributesKey key = myDescriptor.getAttributes();
boolean localNode = key == GradleTextAttributes.GRADLE_LOCAL_CHANGE || key == GradleTextAttributes.INTELLIJ_LOCAL_CHANGE;
if (!localNode) {
myDescriptor.setAttributes(GradleTextAttributes.GRADLE_CHANGE_CONFLICT);
onNodeChanged(this);
}
@@ -219,7 +236,15 @@ public class GradleProjectStructureNode<T extends GradleEntityId> extends Defaul
public void setAttributes(@NotNull TextAttributesKey key) {
myDescriptor.setAttributes(key);
onNodeChanged(this);
final GradleProjectStructureNode<?> parent = getParent();
if (parent == null) {
onNodeChanged(this);
return;
}
boolean positionChanged = parent.correctChildPositionIfNecessary(this);
if (!positionChanged) {
onNodeChanged(this);
}
}
public void addListener(@NotNull Listener listener) {
@@ -232,9 +257,9 @@ public class GradleProjectStructureNode<T extends GradleEntityId> extends Defaul
}
}
private void onNodeRemoved(@NotNull GradleProjectStructureNode<?> node, int index) {
private void onNodeRemoved(@NotNull GradleProjectStructureNode<?> node, int removedChildIndex) {
for (Listener listener : myListeners) {
listener.onNodeRemoved(node, index);
listener.onNodeRemoved(this, node, removedChildIndex);
}
}
@@ -246,7 +271,9 @@ public class GradleProjectStructureNode<T extends GradleEntityId> extends Defaul
public interface Listener {
void onNodeAdded(@NotNull GradleProjectStructureNode<?> node, int index);
void onNodeRemoved(@NotNull GradleProjectStructureNode<?> node, int index);
void onNodeRemoved(@NotNull GradleProjectStructureNode<?> parent,
@NotNull GradleProjectStructureNode<?> removedChild,
int removedChildIndex);
void onNodeChanged(@NotNull GradleProjectStructureNode<?> node);
}
}
@@ -157,10 +157,10 @@ public class GradleUtil {
*/
@Nullable
public static GradleProject refreshProject(@NotNull final Project project,
@NotNull final String gradleProjectPath,
@NotNull final Ref<String> errorHolder,
final boolean resolveLibraries,
final boolean modal)
@NotNull final String gradleProjectPath,
@NotNull final Ref<String> errorHolder,
final boolean resolveLibraries,
final boolean modal)
{
final Ref<GradleProject> gradleProject = new Ref<GradleProject>();
final TaskUnderProgress task = new TaskUnderProgress() {
@@ -196,7 +196,7 @@ public class GradleUtil {
task.execute(indicator);
}
});
}
}
}
});
return gradleProject.get();
@@ -6,6 +6,8 @@ import org.jetbrains.plugins.gradle.testutil.AbstractGradleTest
import org.junit.Test
import static org.junit.Assert.assertEquals
import org.jetbrains.plugins.gradle.diff.GradleMismatchedLibraryPathChange
import org.jetbrains.plugins.gradle.diff.GradleLibraryDependencyPresenceChange
/**
* @author Denis Zhdanov
@@ -15,7 +17,7 @@ import static org.junit.Assert.assertEquals
public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
@Test
public void processObsoleteGradleLocalChange() {
public void "obsolete gradle-local modules"() {
// Configure initial projects state.
init(
gradle: {
@@ -32,14 +34,17 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
module {
dependencies {
library("lib1")
} } } }
} } } },
changesSorter: { a, b ->
b.gradleEntity.dependencyName.compareTo(a.gradleEntity.dependencyName)
}
)
// Check that the initial projects state is correctly parsed.
checkChanges {
presence {
library(gradle: gradle.modules.dependencies.flatten().findAll { it.name == "lib2" })
library(gradle: gradle.modules.dependencies.flatten().findAll { it.name == "lib3" })
library(gradle: gradle.libraryDependencies.values().flatten().findAll { it.name == "lib2" })
library(gradle: gradle.libraryDependencies.values().flatten().findAll { it.name == "lib3" })
} }
checkTree {
project {
@@ -61,7 +66,7 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
checkChanges {
presence {
library(gradle: gradle.modules.dependencies.flatten().findAll { it.name == "lib3" })
library(gradle: gradle.libraryDependencies.values().flatten().findAll { it.name == "lib3" })
} }
checkTree {
project {
@@ -93,7 +98,7 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
}
@Test
public void libraryDependenciesWithDifferentPaths() {
public void "library dependencies on binary paths"() {
// Let the model has two differences in a library setup initially.
init(
gradle: {
@@ -114,8 +119,7 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
checkChanges {
libraryConflict(entity: intellij.libraries['lib2']) {
binaryPath(gradle: '1', intellij: null)
binaryPath(gradle: null, intellij: '3')
binaryPath(gradle: '1', intellij: ['3'])
} }
checkTree {
project {
@@ -143,7 +147,7 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
} } } }
)
checkChanges {
libraryConflict(entity: intellij.dependencies.values().flatten().find {it.library.name == 'lib2' }.library) {
libraryConflict(entity: intellij.libraryDependencies.values().flatten().find {it.library.name == 'lib2' }.library) {
binaryPath(gradle: null, intellij: '3')
} }
checkTree {
@@ -182,7 +186,7 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
}
@Test
public void intellijModuleRemoval() {
public void "intellij module removal"() {
Closure initialClosure = {
project {
module('module1')
@@ -208,21 +212,22 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
} } )
checkChanges {
presence {
module(gradle: gradle.modules.find { it.name == 'module2'})
libraryDependency(gradle: gradle.modules.dependencies.flatten())
module(gradle: gradle.modules['module2'])
libraryDependency(gradle: gradle.modules['module2'].dependencies)
} }
checkTree {
project {
module1()
module2('gradle') {
dependencies {
lib1('gradle')
lib2('gradle')
} } } }
} }
module1()
} }
}
@Test
public void gradleModuleIsImported() {
public void "gradle-local module is not treated as 'local' after import"() {
init(
gradle: {
project {
@@ -236,12 +241,12 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
)
checkChanges {
presence {
module(gradle: gradle.modules.find { it.name == 'module2' })
module(gradle: gradle.modules['module2'])
} }
checkTree {
project {
module1()
module2('gradle')
module1()
} }
// Emulate import gradle module to intellij.
@@ -257,4 +262,293 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
module2() // Imported module node is not highlighted anymore.
} }
}
@Test
public void "gradle local library dependency outweighs library path conflict"() {
init(
gradle: {
project {
module('module1') {
dependencies {
library('lib1', bin: ['1'])
} }
module('module2') {
dependencies {
library('lib1')
} } } },
intellij: {
project {
module('module1') {
dependencies {
library('lib1', bin: ['2'])
} } } },
changesSorter: changeByClassSorter([
(GradleMismatchedLibraryPathChange) : 2,
(GradleLibraryDependencyPresenceChange) : 1
])
)
checkChanges {
presence {
module(gradle: gradle.modules['module2'])
libraryDependency(gradle: gradle.libraryDependencies[gradle.modules['module2']].first())
}
libraryConflict(entity: intellij.libraries['lib1']) {
binaryPath(gradle: ['1'], intellij: ['2'])
} }
checkTree {
project {
module2('gradle') {
dependencies {
lib1('gradle') // This is the point of the test. We don't expect to see 'conflict' here.
} }
module1() {
dependencies {
lib1('conflict')
} } } }
}
@Test
public void "mismatched module dependency import"() {
init(
gradle: {
project {
module('module1')
module('module2')
module('module3') {
dependencies {
module('module1')
module('module2')
} } } },
intellij: {
project {
module('module2')
module('module4')
module('module3') {
dependencies {
module('module2')
module('module4')
} } } }
)
checkChanges {
presence {
module(gradle: gradle.modules['module1'])
module(intellij: intellij.modules['module4'])
moduleDependency(gradle: gradle.moduleDependencies[gradle.modules['module3']].find { it.target == gradle.modules['module1']})
moduleDependency(intellij: intellij.moduleDependencies[intellij.modules['module3']].find { it.moduleName == 'module4'})
} }
checkTree {
project {
module1('gradle')
module2()
module3() {
dependencies {
module1('gradle')
module2()
module4('intellij')
} }
module4('intellij')
} }
Closure newProjectState = {
project {
module('module1')
module('module2')
module('module4')
module('module3') {
dependencies {
module('module1')
module('module2')
module('module4')
} } } }
setState(gradle: newProjectState, intellij: newProjectState)
checkChanges { } // No changes
checkTree {
project {
module1()
module2()
module3 {
dependencies {
module1()
module2()
module4()
} }
module4()
} }
}
@Test
public void "mismatched module dependency removal"() {
init(
gradle: {
project {
module('module1')
module('module2')
module('module3') {
dependencies {
module('module1')
module('module2')
} } } },
intellij: {
project {
module('module2')
module('module4')
module('module3') {
dependencies {
module('module2')
module('module4')
} } } }
)
checkChanges {
presence {
module(gradle: gradle.modules['module1'])
module(intellij: intellij.modules['module4'])
moduleDependency(gradle: gradle.moduleDependencies[gradle.modules['module3']].find { it.target == gradle.modules['module1']})
moduleDependency(intellij: intellij.moduleDependencies[intellij.modules['module3']].find { it.moduleName == 'module4'})
} }
checkTree {
project {
module1('gradle')
module2()
module3() {
dependencies {
module1('gradle')
module2()
module4('intellij')
} }
module4('intellij')
} }
Closure newProjectState = {
project {
module('module2')
module('module3') {
dependencies {
module('module2')
} } } }
setState(gradle: newProjectState, intellij: newProjectState)
checkChanges { } // No changes
checkTree {
project {
module2()
module3 {
dependencies {
module2()
} } } }
}
@Test
public void "cycled module dependencies"() {
init(
gradle: {
project {
module('module1') {
dependencies {
module('module2')
} }
module('module2') {
dependencies {
module('module1')
} } } },
intellij: {
project {
module('module2') {
dependencies {
module('module3')
} }
module('module3') {
dependencies {
module('module2')
} } } }
)
checkChanges {
presence {
module(gradle: gradle.modules['module1'])
module(intellij: intellij.modules['module3'])
moduleDependency(gradle: gradle.moduleDependencies.values().flatten())
moduleDependency(intellij: intellij.moduleDependencies.values().flatten())
} }
checkTree {
project {
module1('gradle') {
dependencies {
module2('gradle')
} }
module2() {
dependencies {
module1('gradle')
module3('intellij')
} }
module3('intellij') {
dependencies {
module2('intellij')
} } } }
}
@Test
public void "mismatched library path is highlighted after importing local library dependency"() {
init(
gradle: {
project {
module('module1') {
dependencies {
library('lib1', bin: ['1'])
} }
module('module2') {
dependencies {
library('lib1')
} } } },
intellij: {
project {
module('module1') {
dependencies {
library('lib1', bin: ['2'])
} } } }
)
checkChanges {
presence {
module(gradle: gradle.modules['module2'])
libraryDependency(gradle: gradle.libraryDependencies[gradle.modules['module2']])
}
libraryConflict(entity: intellij.libraries['lib1']) {
binaryPath(gradle: '1', intellij: ['2'])
} }
checkTree {
project {
module2('gradle') {
dependencies {
lib1('gradle')
} }
module1 {
dependencies {
lib1('conflict')
} } } }
// Emulate importing missing module and library dependencies. Expecting to see the newly imported library dependency node
// highlighted as 'conflict' now.
setState(intellij: {
project {
module('module1') {
dependencies {
library('lib1', bin: ['2'])
} }
module('module2') {
dependencies {
library('lib1')
} } } })
checkChanges {
libraryConflict(entity: intellij.libraries['lib1']) {
binaryPath(gradle: '1', intellij: ['2'])
} }
checkTree {
project {
module1 {
dependencies {
lib1('conflict')
} }
module2() {
dependencies {
lib1('conflict')
} } } }
}
}
@@ -1,23 +1,18 @@
package org.jetbrains.plugins.gradle.testutil
import com.intellij.openapi.project.Project
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.plugins.gradle.model.id.GradleEntityIdMapper
import org.jetbrains.plugins.gradle.sync.GradleProjectStructureChangeListener
import org.jetbrains.plugins.gradle.sync.GradleProjectStructureChangesModel
import org.jetbrains.plugins.gradle.sync.GradleProjectStructureHelper
import org.jetbrains.plugins.gradle.sync.GradleProjectStructureTreeModel
import org.junit.Before
import org.picocontainer.defaults.DefaultPicoContainer
import com.intellij.openapi.project.Project
import org.jetbrains.plugins.gradle.diff.PlatformFacade
import org.jetbrains.plugins.gradle.diff.GradleStructureChangesCalculator
import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChangesCalculator
import org.jetbrains.plugins.gradle.diff.GradleModuleStructureChangesCalculator
import org.jetbrains.plugins.gradle.diff.GradleLibraryDependencyStructureChangesCalculator
import org.jetbrains.plugins.gradle.diff.GradleLibraryStructureChangesCalculator
import org.jetbrains.plugins.gradle.sync.GradleProjectStructureHelper
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.plugins.gradle.sync.GradleProjectStructureChangeListener
import static org.junit.Assert.assertEquals
import org.picocontainer.MutablePicoContainer
import org.jetbrains.plugins.gradle.model.id.GradleEntityIdMapper;
import org.picocontainer.defaults.DefaultPicoContainer
import org.jetbrains.plugins.gradle.diff.*
import static org.junit.Assert.fail
/**
* @author Denis Zhdanov
@@ -29,15 +24,16 @@ public abstract class AbstractGradleTest {
GradleProjectStructureTreeModel treeModel
def gradle
def intellij
def changes
def changesBuilder
def treeChecker
def container
private Closure changesComparator
@Before
public void setUp() {
gradle = new GradleProjectBuilder()
intellij = new IntellijProjectBuilder()
changes = new ChangeBuilder()
changesBuilder = new ChangeBuilder()
treeChecker = new ProjectStructureChecker()
container = new DefaultPicoContainer()
container.registerComponentInstance(Project, intellij.project)
@@ -47,6 +43,7 @@ public abstract class AbstractGradleTest {
container.registerComponentImplementation(GradleProjectStructureHelper)
container.registerComponentImplementation(GradleStructureChangesCalculator, GradleProjectStructureChangesCalculator)
container.registerComponentImplementation(GradleModuleStructureChangesCalculator)
container.registerComponentImplementation(GradleModuleDependencyStructureChangesCalculator)
container.registerComponentImplementation(GradleLibraryDependencyStructureChangesCalculator)
container.registerComponentImplementation(GradleLibraryStructureChangesCalculator)
container.registerComponentImplementation(GradleEntityIdMapper)
@@ -62,31 +59,55 @@ public abstract class AbstractGradleTest {
protected def init(map = [:]) {
treeModel = container.getComponentInstance(GradleProjectStructureTreeModel) as GradleProjectStructureTreeModel
changesModel.addListener({ old, current ->
treeModel.update(current)
treeModel.processObsoleteChanges(ContainerUtil.subtract(old, current));
treeModel.processObsoleteChanges(sortChanges(ContainerUtil.subtract(old, current)));
treeModel.processCurrentChanges(sortChanges(current))
} as GradleProjectStructureChangeListener)
setState(map, false)
treeModel.rebuild()
changesModel.update(gradle.project)
}
def sortChanges(changes) {
if (changesComparator) {
return changes.toList().sort(changesComparator)
}
return changes
}
protected def setState(map, update = true) {
map.intellij?.delegate = intellij
map.intellij?.call()
map.gradle?.delegate = gradle
map.gradle?.call()
changesComparator = map.changesSorter
if (update) {
changesModel.update(gradle.project)
}
}
protected def checkChanges(Closure c) {
c.delegate = changes
changesBuilder.changes.clear()
c.delegate = changesBuilder
def expected = c()
if (!expected) {
expected = [].toSet()
}
assertEquals(expected, changesModel.changes)
def actual = new HashSet(changesModel.changes)
if (expected == actual) {
return
}
actual.removeAll(expected)
expected.removeAll(changesModel.changes)
def message = "Project structure changes are mismatched."
if (expected) {
message += "\n Expected but not matched:"
expected.each { message += "\n * $it"}
}
if (actual) {
message += "\n Unexpected:"
actual.each { message += "\n * $it"}
}
fail(message)
}
protected def checkTree(c) {
@@ -95,4 +116,17 @@ public abstract class AbstractGradleTest {
def expected = c()
treeChecker.check(expected, treeModel.root)
}
protected Closure changeByClassSorter(Map<Class<?>, Integer> rules) {
{ a, b ->
def weightA = rules[a.class] ?: Integer.MAX_VALUE
def weightB = rules[b.class] ?: Integer.MAX_VALUE
if (weightA == weightB) {
return a.hashCode() - b.hashCode()
}
else {
return weightA - weightB
}
}
}
}
@@ -1,6 +1,7 @@
package org.jetbrains.plugins.gradle.testutil
import com.intellij.pom.java.LanguageLevel
import com.intellij.openapi.util.text.StringUtil
/**
* @author Denis Zhdanov
@@ -12,16 +13,28 @@ public abstract class AbstractProjectBuilder extends BuilderSupport {
private static int COUNTER
def project
def modules = []
/** [module name; module] */
def modules = [:]
/** Holds (library name; library) pairs for the active configuration. */
def libraries = [:]
/** [module; dependency list] */
def libraryDependencies = [:].withDefault {[]}
/** [module; dependency list] */
def moduleDependencies = [:].withDefault {[]}
/**
* Holds (library name; library) pairs for the whole test. I.e. there is a possible case that we define particular configuration
* initially and the adjust it. We need to use the same library instance then in order to pass hashCode()/equals() checks then.
* This map works as a test-wide storage.
*/
def librariesCache = [:]
def dependencies = [:].withDefault {[]}
/** [module name; module] */
def modulesCache = [:]
@Override
protected void setParent(Object parent, Object child) {
@@ -43,37 +56,54 @@ public abstract class AbstractProjectBuilder extends BuilderSupport {
}
@Override
protected Object createNode(Object name, Map attributes) {
protected Object createNode(name, Map attributes) {
switch (name) {
case "dependencies": return current // Assuming that 'current' is a module object
case "project":
reset()
clear()
return project = createProject(attributes.name?: same, attributes.langLevel?: LanguageLevel.JDK_1_6)
case "module": def module = createModule(attributes.name?: same); modules << module; return module
case "module":
case "library":
def n = StringUtil.capitalize(name)
if (current == project) {
// Library.
return getLibrary(attributes)
}
else {
// Library dependency.
def module = current
def dep = createLibraryDependency(module, getLibrary(attributes))
dependencies[module] << dep
return dep
// Not a dependency.
return "get$n"(attributes)
}
def ownerModule = current
def dep = "create${n}Dependency"(ownerModule, "get$n"(attributes))
"get${n}Dependencies"()[ownerModule] << dep
return dep
}
}
protected abstract def createProject(String name, LanguageLevel languageLevel)
protected abstract def createModule(String name)
protected abstract def registerModule(module)
protected abstract def createLibrary(String name, Map paths)
protected abstract def applyLibraryPaths(library, Map paths)
protected abstract def createLibraryDependency(module, library)
protected abstract def createModuleDependency(ownerModule, targetModule)
protected abstract def reset();
protected String getUnique() { "./${COUNTER++}" }
protected String getSame() { SAME_TOKEN }
private def getModule(Map attributes) {
def name = attributes.name?: same
def result = modules[name]
if (result) return result
result = modulesCache[name]
if (result) {
registerModule(result)
}
else {
result = createModule(name)
modulesCache[name] = result
}
modules[name] = result
result
}
private def getLibrary(Map attributes) {
def name = attributes.name?: same
def result = libraries[name]
@@ -89,8 +119,9 @@ public abstract class AbstractProjectBuilder extends BuilderSupport {
libraries[name] = result
result
}
private def reset() {
[modules, dependencies, libraries]*.clear()
private def clear() {
reset()
[modules, libraryDependencies, libraries, moduleDependencies]*.clear()
}
}
@@ -6,6 +6,7 @@ import org.jetbrains.plugins.gradle.diff.GradleMismatchedLibraryPathChange
import com.intellij.openapi.roots.libraries.Library
import org.jetbrains.plugins.gradle.util.GradleUtil
import org.jetbrains.plugins.gradle.diff.GradleModulePresenceChange
import org.jetbrains.plugins.gradle.diff.GradleModuleDependencyPresenceChange
/**
* @author Denis Zhdanov
@@ -29,14 +30,15 @@ public class ChangeBuilder extends BuilderSupport {
@Override
protected Object createNode(Object name, Map attributes) {
if (current == null) {
changes = []
}
switch (name) {
case "module":
changes.addAll attributes.gradle.collect { new GradleModulePresenceChange(it, null)}
changes.addAll attributes.intellij.collect { new GradleModulePresenceChange(null, it)}
return changes
case "moduleDependency":
changes.addAll attributes.gradle.collect { new GradleModuleDependencyPresenceChange(it, null) }
changes.addAll attributes.intellij.collect { new GradleModuleDependencyPresenceChange(null, it) }
return changes
case "library":
changes.addAll attributes.gradle.collect { new GradleLibraryDependencyPresenceChange(it, null)}
changes.addAll attributes.intellij.collect { new GradleLibraryDependencyPresenceChange(null, it)}
@@ -50,15 +52,12 @@ public class ChangeBuilder extends BuilderSupport {
if (!library) {
throw new IllegalArgumentException("No entity is defined for the library conflict change. Known attributes: $attributes")
}
if (attributes.gradle) {
return register(new GradleMismatchedLibraryPathChange(library, attributes.gradle, attributes.intellij))
}
return library
case "binaryPath":
// Assuming that we're processing library binary path conflict here
register(new GradleMismatchedLibraryPathChange(
current as Library, toCanonicalPath(attributes.gradle), toCanonicalPath(attributes.intellij)
))
current as Library, collectPaths(attributes.gradle), collectPaths(attributes.intellij)
))
}
changes
}
@@ -73,9 +72,16 @@ public class ChangeBuilder extends BuilderSupport {
protected def register(change) {
changes << change
change
changes
}
private def collectPaths(paths) {
if (!paths) {
return [].toSet()
}
paths.collect { toCanonicalPath(it) }.toSet()
}
private def toCanonicalPath(String path) {
path ? GradleUtil.toCanonicalPath(path) : path
}
@@ -6,6 +6,7 @@ import org.jetbrains.plugins.gradle.model.gradle.GradleLibraryDependency
import org.jetbrains.plugins.gradle.model.gradle.GradleLibrary
import org.jetbrains.plugins.gradle.model.gradle.LibraryPathType
import com.intellij.pom.java.LanguageLevel
import org.jetbrains.plugins.gradle.model.gradle.GradleModuleDependency
/**
* @author Denis Zhdanov
@@ -23,8 +24,19 @@ class GradleProjectBuilder extends AbstractProjectBuilder {
@Override
protected createModule(String name) {
def result = new GradleModule(name, unique)
project.addModule(result)
registerModule(new GradleModule(name, unique))
}
@Override
protected registerModule(module) {
project.addModule(module)
module
}
@Override
protected createModuleDependency(ownerModule, targetModule) {
def result = new GradleModuleDependency(ownerModule, targetModule)
ownerModule.addDependency(result)
result
}
@@ -49,4 +61,9 @@ class GradleProjectBuilder extends AbstractProjectBuilder {
key, type -> paths[key]?.each { library.addPath(type, it) }
}
}
@Override
protected reset() {
modulesCache.values().each { it.clearDependencies() }
}
}
@@ -13,6 +13,7 @@ import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.roots.OrderRootType
import org.jetbrains.plugins.gradle.util.GradleUtil
import com.intellij.openapi.roots.libraries.LibraryTable
import com.intellij.openapi.roots.ModuleOrderEntry
/**
* @author Denis Zhdanov
@@ -30,8 +31,8 @@ class IntellijProjectBuilder extends AbstractProjectBuilder {
def projectLibraryTable = projectLibraryTableStub as LibraryTable
def platformFacade = [
getModules: { modules },
getOrderEntries: { dependencies[it] },
getModules: { modules.values() },
getOrderEntries: { libraryDependencies[it] + moduleDependencies[it] },
getProjectIcon: { IconLoader.getIcon("/nodes/ideaProject.png") },
getLocalFileSystemPath: { it.path },
getProjectLibraryTable: { projectLibraryTable }
@@ -42,7 +43,7 @@ class IntellijProjectBuilder extends AbstractProjectBuilder {
@Override
protected createProject(String name, LanguageLevel languageLevel) {
projectStub.getName = { name }
platformFacade.getLanguageLevel = { languageLevel }
platformFacade.getLanguageLevel = { languageLevel } as Closure
project
}
@@ -51,6 +52,20 @@ class IntellijProjectBuilder extends AbstractProjectBuilder {
[ getName: { name } ] as Module
}
@Override
protected registerModule(Object module) { }
@Override
protected createModuleDependency(ownerModule, targetModule) {
def stub = [:]
def result = stub as ModuleOrderEntry
stub.accept = { policy, defaultValue -> policy.visitModuleOrderEntry(result, defaultValue) }
stub.getModule = { targetModule }
stub.getOwnerModule = { ownerModule }
stub.getModuleName = { targetModule.name }
result
}
@Override
protected createLibrary(String name, Map paths) {
libraryPaths[name] = paths
@@ -81,4 +96,7 @@ class IntellijProjectBuilder extends AbstractProjectBuilder {
protected applyLibraryPaths(library, Map paths) {
libraryPaths[library.name] = paths
}
@Override
protected reset() { }
}
@@ -56,7 +56,7 @@ public class GroovyScriptRunConfigurationProducer extends RuntimeConfigurationPr
GroovyFile groovyFile = (GroovyFile)file;
final PsiClass aClass = GroovyRunnerUtil.getRunningClass(location.getPsiElement());
if (aClass != null) {
if (aClass != null && GroovyRunnerUtil.canBeRunByGroovy(aClass)) {
final RunnerAndConfigurationSettings settings = createConfiguration(aClass);
if (settings != null) {
mySourceElement = element;
@@ -15,27 +15,35 @@
*/
package com.intellij.designer.componentTree;
import com.intellij.designer.designSurface.DesignerEditorPanel;
import com.intellij.designer.designSurface.FeedbackTreeLayer;
import com.intellij.designer.model.RadComponent;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.ui.ColoredTreeCellRenderer;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.SideBorder;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import java.awt.*;
/**
* @author Alexander Lobas
*/
public final class ComponentTree extends Tree implements DataProvider {
private TreeComponentDecorator myDecorator;
private RadComponent myMarkComponent;
private int myMarkFeedback;
public ComponentTree() {
newModel();
setScrollsOnExpand(true);
installCellRenderer();
setRootVisible(false);
@@ -50,8 +58,6 @@ public final class ComponentTree extends Tree implements DataProvider {
// TODO: Popup menu
// TODO: F2 should start inplace editing
// TODO: DND
}
public void newModel() {
@@ -60,6 +66,13 @@ public final class ComponentTree extends Tree implements DataProvider {
public void setDecorator(TreeComponentDecorator decorator) {
myDecorator = decorator;
myMarkComponent = null;
}
public void mark(RadComponent component, int feedback) {
myMarkComponent = component;
myMarkFeedback = feedback;
repaint();
}
@Override
@@ -67,6 +80,23 @@ public final class ComponentTree extends Tree implements DataProvider {
return null; //TODO
}
@Nullable
public RadComponent extractComponent(Object value) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
Object userObject = node.getUserObject();
if (myDecorator != null && userObject instanceof TreeNodeDescriptor) {
TreeNodeDescriptor descriptor = (TreeNodeDescriptor)userObject;
Object element = descriptor.getElement();
if (element instanceof RadComponent) {
return (RadComponent)element;
}
}
return null;
}
private void installCellRenderer() {
setCellRenderer(new ColoredTreeCellRenderer() {
@Override
@@ -77,16 +107,64 @@ public final class ComponentTree extends Tree implements DataProvider {
boolean leaf,
int row,
boolean hasFocus) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
if (myDecorator != null && node.getUserObject() instanceof TreeNodeDescriptor) {
TreeNodeDescriptor descriptor = (TreeNodeDescriptor)node.getUserObject();
if (descriptor.getElement() instanceof RadComponent) {
RadComponent component = (RadComponent)descriptor.getElement();
// TODO: support more parameters and attributes
myDecorator.decorate(component, this);
RadComponent component = extractComponent(value);
if (component != null) {
// TODO: support more parameters and attributes
myDecorator.decorate(component, this);
if (myMarkComponent == component) {
if (myMarkFeedback == FeedbackTreeLayer.INSERT_SELECTION) {
setBorder(BorderFactory.createLineBorder(Color.RED, 1));
}
else {
setBorder(new InsertBorder(myMarkFeedback));
}
}
else {
setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
}
}
}
});
}
private static class InsertBorder extends LineBorder {
private final int myMode;
public InsertBorder(int mode) {
super(Color.BLACK, 2);
myMode = mode;
}
@Override
public Insets getBorderInsets(Component component) {
return getBorderInsets(component, new Insets(0, 0, 0, 0));
}
@Override
public Insets getBorderInsets(Component component, Insets insets) {
insets.top = myMode == FeedbackTreeLayer.INSERT_BEFORE ? thickness : 0;
insets.left = insets.right = thickness;
insets.bottom = myMode == FeedbackTreeLayer.INSERT_AFTER ? thickness : 0;
return insets;
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Color oldColor = g.getColor();
g.setColor(getLineColor());
if (myMode == FeedbackTreeLayer.INSERT_BEFORE) {
g.fillRect(x, y, width, thickness);
g.fillRect(x, y, thickness, 2 * thickness);
g.fillRect(x + width - thickness, y, thickness, 2 * thickness);
}
else {
g.fillRect(x, y + height - thickness, width, thickness);
g.fillRect(x, y + height - 2 * thickness, thickness, 2 * thickness);
g.fillRect(x + width - thickness, y + height - 2 * thickness, thickness, 2 * thickness);
}
g.setColor(oldColor);
}
}
}
@@ -18,7 +18,6 @@ package com.intellij.designer.componentTree;
import com.intellij.designer.designSurface.ComponentSelectionListener;
import com.intellij.designer.designSurface.DesignerEditorPanel;
import com.intellij.designer.designSurface.EditableArea;
import com.intellij.designer.model.RadComponent;
import com.intellij.ide.util.treeView.AbstractTreeBuilder;
import javax.swing.event.TreeSelectionEvent;
@@ -30,22 +29,27 @@ import javax.swing.tree.TreeSelectionModel;
* @author Alexander Lobas
*/
public final class ComponentTreeBuilder extends AbstractTreeBuilder implements ComponentSelectionListener, TreeSelectionListener {
private final EditableArea mySurfaceArea;
private final TreeSelectionModel myTreeSelectionModel;
private final EditableArea mySurfaceArea;
private final TreeEditableArea myTreeArea;
private final TreeGlassLayer myGlassLayer;
public ComponentTreeBuilder(ComponentTree tree, DesignerEditorPanel designer) {
super(tree, (DefaultTreeModel)tree.getModel(), new TreeContentProvider(designer), null); // TODO: comparator?
super(tree, (DefaultTreeModel)tree.getModel(), new TreeContentProvider(designer), null);
initRootNode();
mySurfaceArea = designer.getSurfaceArea();
myTreeSelectionModel = getTree().getSelectionModel();
mySurfaceArea = designer.getSurfaceArea();
myTreeArea = new TreeEditableArea(tree, this);
myGlassLayer = new TreeGlassLayer(tree, designer.getToolProvider(), myTreeArea);
// TODO: restore expanded state
setTreeSelection();
select(mySurfaceArea.getSelection().toArray(), null);
addListeners();
}
@Override
public void dispose() {
removeListeners();
myGlassLayer.dispose();
super.dispose();
}
@@ -74,22 +78,17 @@ public final class ComponentTreeBuilder extends AbstractTreeBuilder implements C
handleSelection(new Runnable() {
@Override
public void run() {
queueUpdate();
setTreeSelection();
myTreeArea.setSelection(mySurfaceArea.getSelection());
}
});
}
private void setTreeSelection() {
select(mySurfaceArea.getSelection().toArray(), null);
}
@Override
public void valueChanged(TreeSelectionEvent e) {
handleSelection(new Runnable() {
@Override
public void run() {
mySurfaceArea.setSelection(getSelectedElements(RadComponent.class));
mySurfaceArea.setSelection(myTreeArea.getSelection());
}
});
}
@@ -0,0 +1,146 @@
/*
* 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.designer.componentTree;
import com.intellij.designer.designSurface.EditOperation;
import com.intellij.designer.designSurface.FeedbackTreeLayer;
import com.intellij.designer.designSurface.OperationContext;
import com.intellij.designer.model.RadComponent;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.Collections;
import java.util.List;
/**
* @author Alexander Lobas
*/
public abstract class TreeEditOperation implements EditOperation {
protected final RadComponent myHost;
protected final OperationContext myContext;
protected List<RadComponent> myComponents;
public static boolean isTarget(RadComponent host, OperationContext context) {
Point location = context.getLocation();
RadComponent target = context.getArea().findTarget(location.x, location.y, null);
if (target == host) {
FeedbackTreeLayer layer = context.getArea().getFeedbackTreeLayer();
return !layer.isBeforeLocation(target, location.x, location.y) &&
!layer.isAfterLocation(target, location.x, location.y);
}
return true;
}
public TreeEditOperation(RadComponent host, OperationContext context) {
myHost = host;
myContext = context;
}
@Override
public void setComponent(RadComponent component) {
myComponents = Collections.singletonList(component);
}
@Override
public void setComponents(List<RadComponent> components) {
myComponents = components;
}
@Override
public void showFeedback() {
Point location = myContext.getLocation();
RadComponent target = myContext.getArea().findTarget(location.x, location.y, null);
FeedbackTreeLayer layer = myContext.getArea().getFeedbackTreeLayer();
if (myHost == target) {
layer.mark(target, FeedbackTreeLayer.INSERT_SELECTION);
}
else if (target != null && isChildren(target)) {
layer.mark(target,
layer.isBeforeLocation(target, location.x, location.y) ?
FeedbackTreeLayer.INSERT_BEFORE : FeedbackTreeLayer.INSERT_AFTER);
} else {
eraseFeedback();
}
}
private boolean isChildren(RadComponent component) {
for (Object child : myHost.getTreeChildren()) {
if (child == component) {
return true;
}
}
return false;
}
@Override
public void eraseFeedback() {
myContext.getArea().getFeedbackTreeLayer().mark(null, FeedbackTreeLayer.INSERT_AFTER);
}
@Override
public boolean canExecute() {
RadComponent reference = getReference();
if (reference == null) {
return false;
}
return canExecute(myHost == reference ? null : reference);
}
protected boolean canExecute(RadComponent insertBefore) {
return true;
}
@Override
public void execute() throws Exception {
RadComponent reference = getReference();
execute(myHost == reference ? null : reference);
}
protected abstract void execute(RadComponent insertBefore) throws Exception;
@Nullable
private RadComponent getReference() {
Point location = myContext.getLocation();
RadComponent target = myContext.getArea().findTarget(location.x, location.y, null);
if (myHost == target) {
return myHost;
}
if (target != null) {
Object[] children = myHost.getTreeChildren();
int index = -1;
for (int i = 0; i < children.length; i++) {
if (children[i] == target) {
index = i + 1;
break;
}
}
if (index == -1) {
return null;
}
if (myContext.getArea().getFeedbackTreeLayer().isBeforeLocation(target, location.x, location.y)) {
return target;
}
if (index < children.length) {
return (RadComponent)children[index];
}
return myHost;
}
return null;
}
}
@@ -0,0 +1,211 @@
/*
* 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.designer.componentTree;
import com.intellij.designer.designSurface.*;
import com.intellij.designer.designSurface.tools.InputTool;
import com.intellij.designer.model.RadComponent;
import com.intellij.ide.util.treeView.AbstractTreeBuilder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* @author Alexander Lobas
*/
public final class TreeEditableArea implements EditableArea, FeedbackTreeLayer {
private final ComponentTree myTree;
private final AbstractTreeBuilder myTreeBuilder;
public TreeEditableArea(ComponentTree tree, AbstractTreeBuilder treeBuilder) {
myTree = tree;
myTreeBuilder = treeBuilder;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Selection
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void addSelectionListener(ComponentSelectionListener listener) {
}
@Override
public void removeSelectionListener(ComponentSelectionListener listener) {
}
@NotNull
@Override
public List<RadComponent> getSelection() {
return new ArrayList<RadComponent>(getRawSelection());
}
@Override
public boolean isSelected(@NotNull RadComponent component) {
return getRawSelection().contains(component);
}
@Override
public void select(@NotNull RadComponent component) {
myTreeBuilder.queueUpdate();
myTreeBuilder.select(component);
}
@Override
public void deselect(@NotNull RadComponent component) {
Collection<RadComponent> selection = getRawSelection();
selection.remove(component);
setRawSelection(selection);
}
@Override
public void appendSelection(@NotNull RadComponent component) {
Collection<RadComponent> selection = getRawSelection();
selection.add(component);
setRawSelection(selection);
}
@Override
public void setSelection(@NotNull List<RadComponent> components) {
setRawSelection(components);
}
private void setRawSelection(Collection<RadComponent> components) {
myTreeBuilder.queueUpdate();
myTreeBuilder.select(components.toArray(), null);
}
private Collection<RadComponent> getRawSelection() {
return myTreeBuilder.getSelectedElements(RadComponent.class);
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Visual
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void setCursor(@Nullable Cursor cursor) {
myTree.setCursor(cursor);
}
@NotNull
@Override
public JComponent getNativeComponent() {
return myTree;
}
@Override
public RadComponent findTarget(int x, int y, @Nullable ComponentTargetFilter filter) {
TreePath path = myTree.getPathForLocation(x, y);
if (path != null) {
RadComponent component = myTree.extractComponent(path.getLastPathComponent());
if (filter != null) {
while (component != null) {
if (filter.preFilter(component) && filter.resultFilter(component)) {
break;
}
component = component.getParent();
}
}
return component;
}
return null;
}
@Override
public InputTool findTargetTool(int x, int y) {
return null;
}
@Override
public ComponentDecorator getRootSelectionDecorator() {
return null;
}
@Override
public EditOperation processRootOperation(OperationContext context) {
return null;
}
@Override
public FeedbackLayer getFeedbackLayer() {
return null;
}
@Override
public RadComponent getRootComponent() {
return null;
}
@Override
public boolean isTree() {
return true;
}
@Override
public FeedbackTreeLayer getFeedbackTreeLayer() {
return this;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// FeedbackTreeLayer
//
//////////////////////////////////////////////////////////////////////////////////////////
private TreePath getPath(RadComponent component) {
// TODO: I don't know better way gets tree path for element
return new TreePath(myTreeBuilder.getNodeForElement(component).getPath());
}
@Override
public void mark(RadComponent component, int feedback) {
// TODO: INSERT_BEFORE - ensure visible up component
// TODO: INSERT_AFTER - ensure visible down component
if (component != null && feedback == INSERT_SELECTION) {
TreePath path = getPath(component);
myTree.scrollPathToVisible(path);
if (!myTree.isExpanded(path)) {
myTreeBuilder.expand(component, null);
}
}
myTree.mark(component, feedback);
}
@Override
public boolean isBeforeLocation(RadComponent component, int x, int y) {
Rectangle bounds = myTree.getPathBounds(getPath(component));
return bounds != null && y - bounds.y < 15;
}
@Override
public boolean isAfterLocation(RadComponent component, int x, int y) {
Rectangle bounds = myTree.getPathBounds(getPath(component));
return bounds != null && bounds.getMaxY() - y < 15;
}
}
@@ -0,0 +1,108 @@
/*
* 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.designer.componentTree;
import com.intellij.designer.designSurface.EditableArea;
import com.intellij.designer.designSurface.tools.ToolProvider;
import java.awt.event.*;
/**
* @author Alexander Lobas
*/
public final class TreeGlassLayer implements KeyListener, MouseListener, MouseMotionListener {
private final ComponentTree myTree;
private final ToolProvider myToolProvider;
private final EditableArea myArea;
public TreeGlassLayer(ComponentTree tree, ToolProvider provider, EditableArea area) {
myTree = tree;
myToolProvider = provider;
myArea = area;
myTree.addKeyListener(this);
myTree.addMouseListener(this);
myTree.addMouseMotionListener(this);
}
public void dispose() {
myTree.removeKeyListener(this);
myTree.removeMouseListener(this);
myTree.removeMouseMotionListener(this);
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Keyboard
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void keyTyped(KeyEvent event) {
myToolProvider.processKeyEvent(event, myArea);
}
@Override
public void keyPressed(KeyEvent event) {
myToolProvider.processKeyEvent(event, myArea);
}
@Override
public void keyReleased(KeyEvent event) {
myToolProvider.processKeyEvent(event, myArea);
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Mouse
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void mouseClicked(MouseEvent event) {
myToolProvider.processMouseEvent(event, myArea);
}
@Override
public void mousePressed(MouseEvent event) {
myToolProvider.processMouseEvent(event, myArea);
}
@Override
public void mouseReleased(MouseEvent event) {
myToolProvider.processMouseEvent(event, myArea);
}
@Override
public void mouseEntered(MouseEvent event) {
myToolProvider.processMouseEvent(event, myArea);
}
@Override
public void mouseExited(MouseEvent event) {
myToolProvider.processMouseEvent(event, myArea);
}
@Override
public void mouseDragged(MouseEvent event) {
myToolProvider.processMouseEvent(event, myArea);
}
@Override
public void mouseMoved(MouseEvent event) {
myToolProvider.processMouseEvent(event, myArea);
}
}
@@ -0,0 +1,122 @@
/*
* 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.designer.designSurface;
import com.intellij.designer.model.RadComponent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.EventListenerList;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author Alexander Lobas
*/
public abstract class ComponentEditableArea implements EditableArea {
private final JComponent myComponent;
private final EventListenerList myListenerList = new EventListenerList();
private List<RadComponent> mySelection = new ArrayList<RadComponent>();
public ComponentEditableArea(JComponent component) {
myComponent = component;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Selection
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void addSelectionListener(ComponentSelectionListener listener) {
myListenerList.add(ComponentSelectionListener.class, listener);
}
@Override
public void removeSelectionListener(ComponentSelectionListener listener) {
myListenerList.remove(ComponentSelectionListener.class, listener);
}
protected void fireSelectionChanged() {
for (ComponentSelectionListener listener : myListenerList.getListeners(ComponentSelectionListener.class)) {
listener.selectionChanged(this);
}
}
@Override
@NotNull
public List<RadComponent> getSelection() {
return mySelection;
}
@Override
public boolean isSelected(@NotNull RadComponent component) {
return mySelection.contains(component);
}
@Override
public void select(@NotNull RadComponent component) {
mySelection = new ArrayList<RadComponent>();
mySelection.add(component);
fireSelectionChanged();
}
@Override
public void deselect(@NotNull RadComponent component) {
mySelection.remove(component);
fireSelectionChanged();
}
@Override
public void appendSelection(@NotNull RadComponent component) {
mySelection.remove(component);
mySelection.add(component);
fireSelectionChanged();
}
@Override
public void setSelection(@NotNull List<RadComponent> components) {
mySelection = new ArrayList<RadComponent>(components);
fireSelectionChanged();
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Visual
//
//////////////////////////////////////////////////////////////////////////////////////////
public void setCursor(@Nullable Cursor cursor) {
myComponent.setCursor(cursor);
}
@NotNull
public JComponent getNativeComponent() {
return myComponent;
}
public boolean isTree() {
return false;
}
@Nullable
public FeedbackTreeLayer getFeedbackTreeLayer() {
return null;
}
}
@@ -93,17 +93,7 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
myLayeredPane = new MyLayeredPane();
mySurfaceArea = new EditableArea() {
@Override
public void setCursor(Cursor cursor) {
myLayeredPane.setCursor(cursor);
}
@Override
public JComponent getNativeComponent() {
return myLayeredPane;
}
mySurfaceArea = new ComponentEditableArea(myLayeredPane) {
@Override
protected void fireSelectionChanged() {
super.fireSelectionChanged();
@@ -191,6 +181,10 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
return mySurfaceArea;
}
public ToolProvider getToolProvider() {
return myToolProvider;
}
protected abstract ComponentDecorator getRootSelectionDecorator();
@Nullable
@@ -21,104 +21,64 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.EventListenerList;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* @author Alexander Lobas
*/
public abstract class EditableArea {
public interface EditableArea {
//////////////////////////////////////////////////////////////////////////////////////////
//
// Selection
//
//////////////////////////////////////////////////////////////////////////////////////////
private final EventListenerList myListenerList = new EventListenerList();
private List<RadComponent> mySelection = new ArrayList<RadComponent>();
void addSelectionListener(ComponentSelectionListener listener);
public void addSelectionListener(ComponentSelectionListener listener) {
myListenerList.add(ComponentSelectionListener.class, listener);
}
public void removeSelectionListener(ComponentSelectionListener listener) {
myListenerList.remove(ComponentSelectionListener.class, listener);
}
protected void fireSelectionChanged() {
for (ComponentSelectionListener listener : myListenerList.getListeners(ComponentSelectionListener.class)) {
listener.selectionChanged(this);
}
}
void removeSelectionListener(ComponentSelectionListener listener);
@NotNull
public List<RadComponent> getSelection() {
return mySelection;
}
List<RadComponent> getSelection();
public boolean isSelected(@NotNull RadComponent component) {
return mySelection.contains(component);
}
boolean isSelected(@NotNull RadComponent component);
public void select(@NotNull RadComponent component) {
mySelection = new ArrayList<RadComponent>();
mySelection.add(component);
fireSelectionChanged();
}
void select(@NotNull RadComponent component);
public void deselect(@NotNull RadComponent component) {
mySelection.remove(component);
fireSelectionChanged();
}
void deselect(@NotNull RadComponent component);
public void appendSelection(@NotNull RadComponent component) {
mySelection.remove(component);
mySelection.add(component);
fireSelectionChanged();
}
void appendSelection(@NotNull RadComponent component);
public void setSelection(@NotNull Collection<RadComponent> components) {
mySelection = new ArrayList<RadComponent>(components);
fireSelectionChanged();
}
void setSelection(@NotNull List<RadComponent> components);
//////////////////////////////////////////////////////////////////////////////////////////
//
//
// Visual
//
//////////////////////////////////////////////////////////////////////////////////////////
public abstract void setCursor(@Nullable Cursor cursor);
void setCursor(@Nullable Cursor cursor);
@NotNull
public abstract JComponent getNativeComponent();
JComponent getNativeComponent();
@Nullable
public abstract RadComponent findTarget(int x, int y, @Nullable ComponentTargetFilter filter);
RadComponent findTarget(int x, int y, @Nullable ComponentTargetFilter filter);
@Nullable
public abstract InputTool findTargetTool(int x, int y);
InputTool findTargetTool(int x, int y);
public abstract ComponentDecorator getRootSelectionDecorator();
ComponentDecorator getRootSelectionDecorator();
@Nullable
public EditOperation processRootOperation(OperationContext context) {
return null;
}
EditOperation processRootOperation(OperationContext context);
public abstract FeedbackLayer getFeedbackLayer();
FeedbackLayer getFeedbackLayer();
public abstract RadComponent getRootComponent();
RadComponent getRootComponent();
public boolean isTree() {
return false;
}
boolean isTree();
@Nullable
public FeedbackTreeLayer getFeedbackTreeLayer() {
return null;
}
FeedbackTreeLayer getFeedbackTreeLayer();
}
@@ -15,8 +15,20 @@
*/
package com.intellij.designer.designSurface;
import com.intellij.designer.model.RadComponent;
import org.jetbrains.annotations.Nullable;
/**
* @author Alexander Lobas
*/
public interface FeedbackTreeLayer {
int INSERT_BEFORE = 0;
int INSERT_AFTER = 1;
int INSERT_SELECTION = 2;
void mark(RadComponent component, int feedback);
boolean isBeforeLocation(RadComponent component, int x, int y);
boolean isAfterLocation(RadComponent component, int x, int y);
}
@@ -15,7 +15,6 @@
*/
package com.intellij.designer.designSurface;
import com.intellij.designer.designSurface.tools.InputTool;
import com.intellij.designer.designSurface.tools.ToolProvider;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.ui.popup.PopupOwner;
@@ -37,31 +36,12 @@ public final class GlassLayer extends JComponent implements PopupOwner, DataProv
myToolProvider = provider;
myArea = area;
enableEvents(AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
// TODO: DND
}
@Override
protected void processKeyEvent(KeyEvent event) {
try {
InputTool tool = myToolProvider.getActiveTool();
myToolProvider.processKeyEvent(event, myArea);
if (tool != null) {
switch (event.getID()) {
case KeyEvent.KEY_PRESSED:
tool.keyPressed(event, myArea);
break;
case KeyEvent.KEY_TYPED:
tool.keyTyped(event, myArea);
break;
case KeyEvent.KEY_RELEASED:
tool.keyReleased(event, myArea);
break;
}
}
}
catch (Throwable e) {
handleException(e);
}
if (!event.isConsumed()) {
super.processKeyEvent(event);
}
@@ -72,59 +52,13 @@ public final class GlassLayer extends JComponent implements PopupOwner, DataProv
if (event.getID() == MouseEvent.MOUSE_PRESSED) {
requestFocusInWindow();
}
try {
InputTool tool = myToolProvider.getActiveTool();
if (tool != null) {
switch (event.getID()) {
case MouseEvent.MOUSE_PRESSED:
tool.mouseDown(event, myArea);
break;
case MouseEvent.MOUSE_RELEASED:
tool.mouseUp(event, myArea);
break;
case MouseEvent.MOUSE_ENTERED:
tool.mouseEntered(event, myArea);
break;
case MouseEvent.MOUSE_EXITED:
tool.mouseExited(event, myArea);
break;
case MouseEvent.MOUSE_CLICKED:
if (event.getClickCount() == 2) {
tool.mouseDoubleClick(event, myArea);
}
break;
}
}
}
catch (Throwable e) {
handleException(e);
}
myToolProvider.processMouseEvent(event, myArea);
}
@Override
protected void processMouseMotionEvent(MouseEvent event) {
try {
InputTool tool = myToolProvider.getActiveTool();
if (tool != null) {
switch (event.getID()) {
case MouseEvent.MOUSE_MOVED:
tool.mouseMove(event, myArea);
break;
case MouseEvent.MOUSE_DRAGGED:
tool.mouseDrag(event, myArea);
break;
}
}
}
catch (Throwable e) {
handleException(e);
}
}
private void handleException(Throwable e) {
myToolProvider.showError("Edit error: ", e);
myToolProvider.processMouseEvent(event, myArea);
}
@Override
@@ -19,6 +19,7 @@ import com.intellij.designer.designSurface.EditableArea;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
/**
@@ -29,6 +30,72 @@ public abstract class ToolProvider {
private EditableArea myArea;
private MouseEvent myEvent;
public void processKeyEvent(KeyEvent event, EditableArea area) {
if (myTool != null) {
try {
switch (event.getID()) {
case KeyEvent.KEY_PRESSED:
myTool.keyPressed(event, area);
break;
case KeyEvent.KEY_TYPED:
myTool.keyTyped(event, area);
break;
case KeyEvent.KEY_RELEASED:
myTool.keyReleased(event, area);
break;
}
}
catch (Throwable e) {
showError("Edit error: ", e);
}
}
}
public void processMouseEvent(MouseEvent event, EditableArea area) {
if (myTool != null) {
try {
switch (event.getID()) {
case MouseEvent.MOUSE_PRESSED:
myTool.mouseDown(event, area);
break;
case MouseEvent.MOUSE_RELEASED:
myTool.mouseUp(event, area);
break;
case MouseEvent.MOUSE_ENTERED:
myTool.mouseEntered(event, area);
break;
case MouseEvent.MOUSE_EXITED:
myTool.mouseExited(event, area);
break;
case MouseEvent.MOUSE_CLICKED:
if (event.getClickCount() == 2) {
myTool.mouseDoubleClick(event, area);
}
break;
case MouseEvent.MOUSE_MOVED:
myTool.mouseMove(event, area);
break;
case MouseEvent.MOUSE_DRAGGED:
myTool.mouseDrag(event, area);
break;
}
}
catch (Throwable e) {
showError("Edit error: ", e);
}
}
}
public void setEvent(MouseEvent event) {
myEvent = event;
}
public void setArea(@Nullable EditableArea area) {
myArea = area;
}
public abstract void showError(@NonNls String message, Throwable e);
public InputTool getActiveTool() {
return myTool;
}
@@ -59,14 +126,4 @@ public abstract class ToolProvider {
}
public abstract void loadDefaultTool();
public void setArea(@Nullable EditableArea area) {
myArea = area;
}
public void setEvent(MouseEvent event) {
myEvent = event;
}
public abstract void showError(@NonNls String message, Throwable e);
}