From 067f0fdce7c7a19ed64c6d8a3305ee326b3277d5 Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 10 Sep 2014 10:38:33 +0400 Subject: [PATCH 01/23] android plugin included into community project --- .gitignore | 1 + .idea/libraries/asm_tools.xml | 11 +++++++++++ .idea/libraries/bouncy_castle.xml | 10 ++++++++++ .idea/libraries/builder_model.xml | 11 +++++++++++ .idea/libraries/commons_compress.xml | 9 +++++++++ .idea/libraries/easymock_tools.xml | 10 ++++++++++ .idea/libraries/freemarker_2_3_20.xml | 9 +++++++++ .idea/libraries/guava_tools.xml | 11 +++++++++++ .idea/libraries/javawriter.xml | 11 +++++++++++ .idea/libraries/kxml2.xml | 9 +++++++++ .idea/libraries/lombok_ast.xml | 16 ++++++++++++++++ .idea/libraries/mockito.xml | 11 +++++++++++ .idea/modules.xml | 27 ++++++++++++++++++++++++--- .idea/vcs.xml | 2 ++ build/scripts/layouts.gant | 4 +--- getPlugins.bat | 2 ++ getPlugins.sh | 2 ++ 17 files changed, 150 insertions(+), 6 deletions(-) create mode 100644 .idea/libraries/asm_tools.xml create mode 100644 .idea/libraries/bouncy_castle.xml create mode 100644 .idea/libraries/builder_model.xml create mode 100644 .idea/libraries/commons_compress.xml create mode 100644 .idea/libraries/easymock_tools.xml create mode 100644 .idea/libraries/freemarker_2_3_20.xml create mode 100644 .idea/libraries/guava_tools.xml create mode 100644 .idea/libraries/javawriter.xml create mode 100644 .idea/libraries/kxml2.xml create mode 100644 .idea/libraries/lombok_ast.xml create mode 100644 .idea/libraries/mockito.xml create mode 100644 getPlugins.bat create mode 100755 getPlugins.sh diff --git a/.gitignore b/.gitignore index e1a3e405ef99..3fb1a17163fc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/android /config /system .idea/workspace.xml diff --git a/.idea/libraries/asm_tools.xml b/.idea/libraries/asm_tools.xml new file mode 100644 index 000000000000..9435a42f3c35 --- /dev/null +++ b/.idea/libraries/asm_tools.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/bouncy_castle.xml b/.idea/libraries/bouncy_castle.xml new file mode 100644 index 000000000000..4e4673aa939e --- /dev/null +++ b/.idea/libraries/bouncy_castle.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/builder_model.xml b/.idea/libraries/builder_model.xml new file mode 100644 index 000000000000..e50dabd08689 --- /dev/null +++ b/.idea/libraries/builder_model.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/commons_compress.xml b/.idea/libraries/commons_compress.xml new file mode 100644 index 000000000000..a77ee366b254 --- /dev/null +++ b/.idea/libraries/commons_compress.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/easymock_tools.xml b/.idea/libraries/easymock_tools.xml new file mode 100644 index 000000000000..c9963855dbcf --- /dev/null +++ b/.idea/libraries/easymock_tools.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/freemarker_2_3_20.xml b/.idea/libraries/freemarker_2_3_20.xml new file mode 100644 index 000000000000..831297d1baf3 --- /dev/null +++ b/.idea/libraries/freemarker_2_3_20.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/guava_tools.xml b/.idea/libraries/guava_tools.xml new file mode 100644 index 000000000000..b492cf4758e7 --- /dev/null +++ b/.idea/libraries/guava_tools.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/javawriter.xml b/.idea/libraries/javawriter.xml new file mode 100644 index 000000000000..1d73b23855f5 --- /dev/null +++ b/.idea/libraries/javawriter.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/kxml2.xml b/.idea/libraries/kxml2.xml new file mode 100644 index 000000000000..fe007f5f7a9c --- /dev/null +++ b/.idea/libraries/kxml2.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/lombok_ast.xml b/.idea/libraries/lombok_ast.xml new file mode 100644 index 000000000000..9fe1aa4ea9f2 --- /dev/null +++ b/.idea/libraries/lombok_ast.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/mockito.xml b/.idea/libraries/mockito.xml new file mode 100644 index 000000000000..a1ae9af5cc45 --- /dev/null +++ b/.idea/libraries/mockito.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index 0322352e9df9..f23cddeafc3c 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -10,18 +10,26 @@ + + + + + + + + @@ -39,6 +47,7 @@ + @@ -46,13 +55,16 @@ + + - + + @@ -66,6 +78,7 @@ + @@ -116,12 +129,17 @@ + + + + + @@ -130,7 +148,9 @@ + + @@ -168,6 +188,8 @@ + + @@ -190,6 +212,7 @@ + @@ -220,8 +243,6 @@ - - diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 275077f82558..a1b9ce94e902 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,6 +2,8 @@ + + diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index 7d5698fc9aee..6eb85a76a4ae 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -254,9 +254,7 @@ def layoutFull(String home, String targetDirectory, String patchedDescriptorDir } public def layoutCommunityPlugins(String home) { - if (isDefined("androidPluginHome")) { - layoutAndroid(p("androidPluginHome")) - } + layoutAndroid("$home/android") dir("plugins") { def simplePlugins = ["commander", "copyright", "java-i18n", "hg4idea", "github"] //, "tasks-time-tracking"] diff --git a/getPlugins.bat b/getPlugins.bat new file mode 100644 index 000000000000..3cd8b977612a --- /dev/null +++ b/getPlugins.bat @@ -0,0 +1,2 @@ +call git clone git://git.jetbrains.org/idea/android.git android +call git clone git://git.jetbrains.org/idea/adt-tools-base.git android/tools-base diff --git a/getPlugins.sh b/getPlugins.sh new file mode 100755 index 000000000000..9afcebda7d70 --- /dev/null +++ b/getPlugins.sh @@ -0,0 +1,2 @@ +git clone git://git.jetbrains.org/idea/android.git android +git clone git://git.jetbrains.org/idea/adt-tools-base.git android/tools-base From 421aa0e4ac3d74a3433fd71c6bb699ba8341ed8d Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 8 Sep 2014 14:22:15 +0400 Subject: [PATCH 02/23] github: use avatar_url instead of gravatar_id due to deprecation --- .../org/jetbrains/plugins/github/api/GithubUser.java | 10 +++++----- .../plugins/github/api/GithubUserDetailed.java | 4 ++-- .../jetbrains/plugins/github/api/GithubUserRaw.java | 4 ++-- .../plugins/github/tasks/GithubComment.java | 12 ++++++------ .../plugins/github/tasks/GithubRepository.java | 2 +- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubUser.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubUser.java index 29ef1acdfd78..bf81b8d62502 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubUser.java +++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubUser.java @@ -26,12 +26,12 @@ public class GithubUser { @NotNull private final String myHtmlUrl; - @Nullable private final String myGravatarId; + @Nullable private final String myAvatarUrl; - public GithubUser(@NotNull String login, @NotNull String htmlUrl, @Nullable String gravatarId) { + public GithubUser(@NotNull String login, @NotNull String htmlUrl, @Nullable String avatarUrl) { myLogin = login; myHtmlUrl = htmlUrl; - myGravatarId = gravatarId; + myAvatarUrl = avatarUrl; } @NotNull @@ -45,7 +45,7 @@ public class GithubUser { } @Nullable - public String getGravatarId() { - return myGravatarId; + public String getAvatarUrl() { + return myAvatarUrl; } } diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubUserDetailed.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubUserDetailed.java index 2c82c078e339..3940b80f360a 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubUserDetailed.java +++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubUserDetailed.java @@ -55,13 +55,13 @@ public class GithubUserDetailed extends GithubUser { public GithubUserDetailed(@NotNull String login, @NotNull String htmlUrl, - @Nullable String gravatarId, + @Nullable String avatarUrl, @Nullable String name, @Nullable String email, @Nullable Integer ownedPrivateRepos, @Nullable String type, @Nullable UserPlan plan) { - super(login, htmlUrl, gravatarId); + super(login, htmlUrl, avatarUrl); myName = name; myEmail = email; myOwnedPrivateRepos = ownedPrivateRepos; diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubUserRaw.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubUserRaw.java index 04d642f8eb2e..0bc673299847 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubUserRaw.java +++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubUserRaw.java @@ -74,14 +74,14 @@ class GithubUserRaw implements DataConstructor { @SuppressWarnings("ConstantConditions") @NotNull public GithubUser createUser() { - return new GithubUser(login, htmlUrl, gravatarId); + return new GithubUser(login, htmlUrl, avatarUrl); } @SuppressWarnings("ConstantConditions") @NotNull public GithubUserDetailed createUserDetailed() { GithubUserDetailed.UserPlan plan = this.plan == null ? null : this.plan.create(); - return new GithubUserDetailed(login, htmlUrl, gravatarId, name, email, ownedPrivateRepos, type, plan); + return new GithubUserDetailed(login, htmlUrl, avatarUrl, name, email, ownedPrivateRepos, type, plan); } @SuppressWarnings("unchecked") diff --git a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubComment.java b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubComment.java index d65a95044a9c..e3115f71975c 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubComment.java +++ b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubComment.java @@ -26,16 +26,16 @@ import java.util.Date; * @author Dennis.Ushakov */ public class GithubComment extends SimpleComment { - @Nullable private final String myGravatarId; + @Nullable private final String myAvatarUrl; @NotNull private final String myUserHtmlUrl; public GithubComment(@Nullable Date date, @Nullable String author, @NotNull String text, - @Nullable String gravatarId, + @Nullable String avatarUrl, @NotNull String userHtmlUrl) { super(date, author, text); - myGravatarId = gravatarId; + myAvatarUrl = avatarUrl; myUserHtmlUrl = userHtmlUrl; } @@ -43,9 +43,9 @@ public class GithubComment extends SimpleComment { builder.append("
"); builder.append(""); builder.append("
"); - if (myGravatarId != null) { - builder.append("
"); - } + if (myAvatarUrl != null) { + builder.append("
"); + } builder.append("
"); if (getAuthor() != null) { builder.append("Author: ").append(getAuthor()).append("
"); diff --git a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java index 39a97184fe72..a8445b7f76ac 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java +++ b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java @@ -240,7 +240,7 @@ public class GithubRepository extends BaseRepositoryImpl { @Override public Comment fun(GithubIssueComment comment) { return new GithubComment(comment.getCreatedAt(), comment.getUser().getLogin(), comment.getBodyHtml(), - comment.getUser().getGravatarId(), + comment.getUser().getAvatarUrl(), comment.getUser().getHtmlUrl()); } }); From 07269c76b15a7daa31e95b285d8aa2130b2eac6a Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Wed, 10 Sep 2014 09:29:40 +0200 Subject: [PATCH 03/23] versioning for todo and id index --- .../impl/id/PlatformIdTableBuilding.java | 23 +++++++++++--- .../psi/impl/cache/impl/todo/TodoIndex.java | 31 +++++++++++++++++-- .../cacheBuilder/DefaultWordsScanner.java | 2 +- .../lang/cacheBuilder/SimpleWordsScanner.java | 2 +- .../cacheBuilder/VersionedWordsScanner.java | 22 +++++++++++++ .../impl/cache/impl/id/FileTypeIdIndexer.java | 3 ++ .../impl/cache/impl/id/IdTableBuilding.java | 5 +++ .../impl/todo/LexerBasedTodoIndexer.java | 4 +-- .../cache/impl/todo/VersionedTodoIndexer.java | 25 +++++++++++++++ .../psi/impl/cache/impl/id/IdIndexImpl.java | 29 +++++++++++++++++ 10 files changed, 134 insertions(+), 12 deletions(-) create mode 100644 platform/indexing-api/src/com/intellij/lang/cacheBuilder/VersionedWordsScanner.java create mode 100644 platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/todo/VersionedTodoIndexer.java diff --git a/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.java b/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.java index 6a3dd82b237e..b1669144551a 100644 --- a/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.java +++ b/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.java @@ -23,17 +23,21 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.ex.util.LexerEditorHighlighter; import com.intellij.openapi.editor.highlighter.EditorHighlighter; import com.intellij.openapi.editor.highlighter.HighlighterIterator; -import com.intellij.openapi.fileTypes.*; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.InternalFileType; +import com.intellij.openapi.fileTypes.LanguageFileType; +import com.intellij.openapi.fileTypes.PlainTextFileType; import com.intellij.openapi.fileTypes.impl.CustomSyntaxTableFileType; import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.CustomHighlighterTokenType; -import com.intellij.psi.impl.cache.impl.BaseFilterLexer; import com.intellij.psi.impl.cache.CacheUtil; +import com.intellij.psi.impl.cache.impl.BaseFilterLexer; import com.intellij.psi.impl.cache.impl.IndexPatternUtil; import com.intellij.psi.impl.cache.impl.OccurrenceConsumer; import com.intellij.psi.impl.cache.impl.todo.TodoIndexEntry; import com.intellij.psi.impl.cache.impl.todo.TodoIndexers; +import com.intellij.psi.impl.cache.impl.todo.VersionedTodoIndexer; import com.intellij.psi.search.IndexPattern; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; @@ -116,7 +120,7 @@ public abstract class PlatformIdTableBuilding { return ourTodoIndexers.containsKey(fileType) || TodoIndexers.INSTANCE.forFileType(fileType) != null || fileType instanceof InternalFileType; } - private static class CompositeTodoIndexer implements DataIndexer { + private static class CompositeTodoIndexer extends VersionedTodoIndexer { private final DataIndexer[] indexers; public CompositeTodoIndexer(@NotNull DataIndexer... indexers) { @@ -139,9 +143,18 @@ public abstract class PlatformIdTableBuilding { } return result; } + + @Override + public int getVersion() { + int version = super.getVersion(); + for(DataIndexer dataIndexer:indexers) { + version += dataIndexer instanceof VersionedTodoIndexer ? ((VersionedTodoIndexer)dataIndexer).getVersion() : 0xFF; + } + return version; + } } - private static class TokenSetTodoIndexer implements DataIndexer { + private static class TokenSetTodoIndexer extends VersionedTodoIndexer { @NotNull private final TokenSet myCommentTokens; private final VirtualFile myFile; @@ -201,7 +214,7 @@ public abstract class PlatformIdTableBuilding { } } - public static class PlainTextTodoIndexer implements DataIndexer { + public static class PlainTextTodoIndexer extends VersionedTodoIndexer { @Override @NotNull public Map map(@NotNull final FileContent inputData) { diff --git a/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/todo/TodoIndex.java b/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/todo/TodoIndex.java index d955354cca7f..109ec0c3f971 100644 --- a/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/todo/TodoIndex.java +++ b/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/todo/TodoIndex.java @@ -20,8 +20,10 @@ import com.intellij.lang.Language; import com.intellij.lang.LanguageParserDefinitions; import com.intellij.lang.ParserDefinition; import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.FileTypeRegistry; import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.fileTypes.impl.CustomSyntaxTableFileType; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.impl.cache.impl.id.PlatformIdTableBuilding; import com.intellij.psi.search.IndexPatternProvider; @@ -39,7 +41,9 @@ import java.beans.PropertyChangeListener; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; +import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.Map; /** @@ -49,7 +53,10 @@ import java.util.Map; public class TodoIndex extends FileBasedIndexExtension { @NonNls public static final ID NAME = ID.create("TodoIndex"); - public TodoIndex(MessageBus messageBus) { + private final FileTypeRegistry myFileTypeManager; + + public TodoIndex(MessageBus messageBus, FileTypeRegistry manager) { + myFileTypeManager = manager; messageBus.connect().subscribe(IndexPatternProvider.INDEX_PATTERNS_CHANGED, new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { @@ -127,7 +134,27 @@ public class TodoIndex extends FileBasedIndexExtension @Override public int getVersion() { - return 8; + int version = 8; + FileType[] types = myFileTypeManager.getRegisteredFileTypes(); + Arrays.sort(types, new Comparator() { + @Override + public int compare(FileType o1, FileType o2) { + return Comparing.compare(o1.getName(), o2.getName()); + } + }); + + for(FileType fileType:types) { + DataIndexer indexer = TodoIndexers.INSTANCE.forFileType(fileType); + if (indexer == null) continue; + + if (!(indexer instanceof VersionedTodoIndexer)) { + int a = 1; + } + + int versionFromIndexer = indexer instanceof VersionedTodoIndexer ? (((VersionedTodoIndexer)indexer).getVersion()) : 0xFF; + version = version * 31 + (versionFromIndexer ^ indexer.getClass().getName().hashCode()); + } + return version; } @Override diff --git a/platform/indexing-api/src/com/intellij/lang/cacheBuilder/DefaultWordsScanner.java b/platform/indexing-api/src/com/intellij/lang/cacheBuilder/DefaultWordsScanner.java index c4a306286708..824202fd0807 100644 --- a/platform/indexing-api/src/com/intellij/lang/cacheBuilder/DefaultWordsScanner.java +++ b/platform/indexing-api/src/com/intellij/lang/cacheBuilder/DefaultWordsScanner.java @@ -27,7 +27,7 @@ import org.jetbrains.annotations.NotNull; * @author max */ -public class DefaultWordsScanner implements WordsScanner { +public class DefaultWordsScanner extends VersionedWordsScanner { private final Lexer myLexer; private final TokenSet myIdentifierTokenSet; private final TokenSet myCommentTokenSet; diff --git a/platform/indexing-api/src/com/intellij/lang/cacheBuilder/SimpleWordsScanner.java b/platform/indexing-api/src/com/intellij/lang/cacheBuilder/SimpleWordsScanner.java index 6273654982a9..069c8643ae19 100644 --- a/platform/indexing-api/src/com/intellij/lang/cacheBuilder/SimpleWordsScanner.java +++ b/platform/indexing-api/src/com/intellij/lang/cacheBuilder/SimpleWordsScanner.java @@ -25,7 +25,7 @@ import com.intellij.util.text.CharArrayUtil; * * @author max */ -public class SimpleWordsScanner implements WordsScanner { +public class SimpleWordsScanner extends VersionedWordsScanner { public void processWords(CharSequence fileText, Processor processor) { int index = 0; WordOccurrence occurrence = null; diff --git a/platform/indexing-api/src/com/intellij/lang/cacheBuilder/VersionedWordsScanner.java b/platform/indexing-api/src/com/intellij/lang/cacheBuilder/VersionedWordsScanner.java new file mode 100644 index 000000000000..f8d27825d14e --- /dev/null +++ b/platform/indexing-api/src/com/intellij/lang/cacheBuilder/VersionedWordsScanner.java @@ -0,0 +1,22 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.lang.cacheBuilder; + +public abstract class VersionedWordsScanner implements WordsScanner { + public int getVersion() { + return 1; + } +} diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/FileTypeIdIndexer.java b/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/FileTypeIdIndexer.java index f770ac1d5d97..5c1246c7a50b 100644 --- a/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/FileTypeIdIndexer.java +++ b/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/FileTypeIdIndexer.java @@ -24,4 +24,7 @@ import com.intellij.util.indexing.FileContent; * Date: Jan 16, 2008 */ public abstract class FileTypeIdIndexer implements DataIndexer { + public int getVersion() { + return 1; + } } diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdTableBuilding.java b/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdTableBuilding.java index 8519453e3e6c..c2ea447400cc 100644 --- a/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdTableBuilding.java +++ b/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdTableBuilding.java @@ -161,6 +161,11 @@ public class IdTableBuilding { }); return consumer.getResult(); } + + @Override + public int getVersion() { + return myScanner instanceof VersionedWordsScanner ? ((VersionedWordsScanner)myScanner).getVersion() : -1; + } } public static void scanWords(final ScanWordProcessor processor, final CharSequence chars, final int startOffset, final int endOffset) { diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/todo/LexerBasedTodoIndexer.java b/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/todo/LexerBasedTodoIndexer.java index b05ef6a9853a..04e27e91dc63 100644 --- a/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/todo/LexerBasedTodoIndexer.java +++ b/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/todo/LexerBasedTodoIndexer.java @@ -18,7 +18,6 @@ package com.intellij.psi.impl.cache.impl.todo; import com.intellij.psi.impl.cache.impl.BaseFilterLexerUtil; import com.intellij.psi.impl.cache.impl.IdAndToDoScannerBasedOnFilterLexer; -import com.intellij.util.indexing.DataIndexer; import com.intellij.util.indexing.FileContent; import org.jetbrains.annotations.NotNull; @@ -28,8 +27,7 @@ import java.util.Map; * @author Eugene Zhuravlev * Date: Jan 20, 2008 */ -public abstract class LexerBasedTodoIndexer implements DataIndexer, - IdAndToDoScannerBasedOnFilterLexer { +public abstract class LexerBasedTodoIndexer extends VersionedTodoIndexer implements IdAndToDoScannerBasedOnFilterLexer { @Override @NotNull public Map map(@NotNull final FileContent inputData) { diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/todo/VersionedTodoIndexer.java b/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/todo/VersionedTodoIndexer.java new file mode 100644 index 000000000000..028c24b77eed --- /dev/null +++ b/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/todo/VersionedTodoIndexer.java @@ -0,0 +1,25 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.impl.cache.impl.todo; + +import com.intellij.util.indexing.DataIndexer; +import com.intellij.util.indexing.FileContent; + +public abstract class VersionedTodoIndexer implements DataIndexer { + public int getVersion() { + return 1; + } +} diff --git a/platform/lang-impl/src/com/intellij/psi/impl/cache/impl/id/IdIndexImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/cache/impl/id/IdIndexImpl.java index 537d997e5a50..1773a260a706 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/cache/impl/id/IdIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/cache/impl/id/IdIndexImpl.java @@ -15,6 +15,9 @@ */ package com.intellij.psi.impl.cache.impl.id; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.FileTypeRegistry; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.ThreadLocalCachedIntArray; import com.intellij.util.indexing.CustomInputsIndexFileBasedIndexExtension; import com.intellij.util.io.DataExternalizer; @@ -27,9 +30,35 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Comparator; public class IdIndexImpl extends IdIndex implements CustomInputsIndexFileBasedIndexExtension { private static final ThreadLocalCachedIntArray spareBufferLocal = new ThreadLocalCachedIntArray(); + private final FileTypeRegistry myFileTypeManager; + + public IdIndexImpl(FileTypeRegistry manager) { + myFileTypeManager = manager; + } + + @Override + public int getVersion() { + FileType[] types = myFileTypeManager.getRegisteredFileTypes(); + Arrays.sort(types, new Comparator() { + @Override + public int compare(FileType o1, FileType o2) { + return Comparing.compare(o1.getName(), o2.getName()); + } + }); + + int version = super.getVersion(); + for(FileType fileType:types) { + if (!isIndexable(fileType)) continue; + FileTypeIdIndexer indexer = IdIndexers.INSTANCE.forFileType(fileType); + if (indexer == null) continue; + version = version * 31 + (indexer.getVersion() ^ indexer.getClass().getName().hashCode()); + } + return version; + } @NotNull @Override From 1bdec4df930265e6d3cecfa91dd492117dd945bf Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 10 Sep 2014 11:50:05 +0400 Subject: [PATCH 04/23] IDEA-129614 (unneeded default text dropped) --- .../com/intellij/openapi/updateSettings/impl/NoUpdatesPanel.form | 1 - 1 file changed, 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesPanel.form b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesPanel.form index 2cee5d3e03f9..be22623c2142 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesPanel.form +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesPanel.form @@ -25,7 +25,6 @@ - From ab6a31f40e0a7b6d29f93fab01eb376ce1e8ef31 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 10 Sep 2014 12:02:38 +0400 Subject: [PATCH 05/23] auto detect initial --- .../autodetect/IndentOptionsDetector.java | 100 +++++++++++++ .../codeStyle/autodetect/IndentUsageInfo.java | 39 +++++ .../autodetect/IndentUsageStatistics.java | 140 ++++++++++++++++++ .../codeStyle/autodetect/LineIndentInfo.java | 56 +++++++ .../autodetect/LineIndentInfoBuilder.java | 80 ++++++++++ .../codeStyle/autodetect/manyComments.java | 51 +++++++ .../autodetect/manyZeroRelativeIndent.java | 31 ++++ .../codeStyle/autodetect/simpleIndent.java | 14 ++ .../autodetect/IndentAutoDetectionTest.java | 135 +++++++++++++++++ 9 files changed, 646 insertions(+) create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentOptionsDetector.java create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageInfo.java create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatistics.java create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfo.java create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfoBuilder.java create mode 100644 platform/platform-tests/testData/codeStyle/autodetect/manyComments.java create mode 100644 platform/platform-tests/testData/codeStyle/autodetect/manyZeroRelativeIndent.java create mode 100644 platform/platform-tests/testData/codeStyle/autodetect/simpleIndent.java create mode 100644 platform/platform-tests/testSrc/com/intellij/psi/autodetect/IndentAutoDetectionTest.java diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentOptionsDetector.java b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentOptionsDetector.java new file mode 100644 index 000000000000..f677707ca79c --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentOptionsDetector.java @@ -0,0 +1,100 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.codeStyle.autodetect; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +import static com.intellij.psi.codeStyle.CommonCodeStyleSettings.*; + +public class IndentOptionsDetector { + private static Logger LOG = Logger.getInstance("#com.intellij.psi.codeStyle.CommonCodeStyleSettings.IndentOptionsDetector"); + + private static final double RATE_THRESHOLD = 0.8; + private static final int MIN_LINES_THRESHOLD = 50; + private static int MAX_INDENT_TO_DETECT = 8; + + private final PsiFile myFile; + private final Project myProject; + private final Document myDocument; + + public IndentOptionsDetector(@NotNull PsiFile file) { + myFile = file; + myProject = file.getProject(); + myDocument = PsiDocumentManager.getInstance(myProject).getDocument(myFile); + } + + @NotNull + public IndentOptions getIndentOptions() { + IndentOptions indentOptions = (IndentOptions)CodeStyleSettingsManager.getSettings(myProject).getIndentOptions(myFile.getFileType()).clone(); + + if (myDocument != null) { + List linesInfo = new LineIndentInfoBuilder(myDocument.getCharsSequence()).build(); + IndentUsageStatistics stats = new IndentUsageStatistics(linesInfo); + adjustIndentOptions(indentOptions, stats); + } + + return indentOptions; + } + + private void adjustIndentOptions(@NotNull IndentOptions indentOptions, @NotNull IndentUsageStatistics stats) { + int linesWithTabs = stats.getTotalLinesWithLeadingTabs(); + int linesWithWhiteSpaceIndent = stats.getTotalLinesWithLeadingSpaces(); + + int totalLines = linesWithTabs + linesWithWhiteSpaceIndent; + double lineWithTabsRate = (double)linesWithTabs / totalLines; + + if (linesWithTabs > MIN_LINES_THRESHOLD && lineWithTabsRate > RATE_THRESHOLD) { + if (!indentOptions.USE_TAB_CHARACTER) { + indentOptions.USE_TAB_CHARACTER = true; + LOG.info("Detected tab usage in" + myFile); + } + } + else if (linesWithWhiteSpaceIndent > MIN_LINES_THRESHOLD && (1 - lineWithTabsRate) > RATE_THRESHOLD) { + int newIndentSize = getPositiveIndentSize(stats); + if (newIndentSize > 0 && indentOptions.INDENT_SIZE != newIndentSize) { + indentOptions.INDENT_SIZE = newIndentSize; + LOG.info("Detected indent size: " + newIndentSize + " for file " + myFile); + } + } + } + + private static int getPositiveIndentSize(@NotNull IndentUsageStatistics stats) { + IndentUsageInfo maxUsedIndentInfo = stats.getMaxUsedIndentInfo(0); + int maxIndentSize = maxUsedIndentInfo.getIndentSize(); + if (maxIndentSize == 0) { + maxUsedIndentInfo = stats.getMaxUsedIndentInfo(1); + maxIndentSize = maxUsedIndentInfo.getIndentSize(); + } + + if (maxIndentSize <= MAX_INDENT_TO_DETECT) { + int totalUsagesWithoutZeroIndent = stats.getTotalLinesWithLeadingSpaces() - stats.getTimesUsedIndent(0); + double usageRate = (double)maxUsedIndentInfo.getTimesUsed() / totalUsagesWithoutZeroIndent; + if (usageRate > RATE_THRESHOLD) { + return maxIndentSize; + } + } + + return -1; + } +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageInfo.java b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageInfo.java new file mode 100644 index 000000000000..a600483a07a6 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageInfo.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.codeStyle.autodetect; + +public class IndentUsageInfo { + private final int indentSize; + private final int timesUsed; + + public IndentUsageInfo(int indentSize, int timesUsed) { + this.indentSize = indentSize; + this.timesUsed = timesUsed; + } + + public int getIndentSize() { + return indentSize; + } + + public int getTimesUsed() { + return timesUsed; + } + + @Override + public String toString() { + return "indent: " + indentSize + ", used " + timesUsed; + } +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatistics.java b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatistics.java new file mode 100644 index 000000000000..27cfcdd22341 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatistics.java @@ -0,0 +1,140 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.codeStyle.autodetect; + +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.Stack; +import gnu.trove.TIntIntHashMap; +import gnu.trove.TIntIntIterator; +import org.jetbrains.annotations.NotNull; + +import java.util.Comparator; +import java.util.List; + +public class IndentUsageStatistics { + private static final Comparator DECREASING_ORDER = new Comparator() { + @Override + public int compare(@NotNull IndentUsageInfo o1, @NotNull IndentUsageInfo o2) { + return o1.getTimesUsed() < o2.getTimesUsed() ? 1 : o1.getTimesUsed() == o2.getTimesUsed() ? 0 : -1; + } + }; + + private List myLineInfos; + + private int myPreviousLineIndent; + private int myPreviousRelativeIndent; + + private int myTotalLinesWithTabs = 0; + private int myTotalLinesWithWhiteSpaces = 0; + + private TIntIntHashMap myIndentToUsages = new TIntIntHashMap(); + private List myIndentUsages = ContainerUtil.newArrayList(); + private Stack myParentIndents = ContainerUtil.newStack(new IndentData(0, 0)); + + public IndentUsageStatistics(@NotNull List lineInfos) { + myLineInfos = lineInfos; + buildIndentToUsagesMap(); + myIndentUsages = toIndentUsageList(myIndentToUsages); + ContainerUtil.sort(myIndentUsages, DECREASING_ORDER); + } + + @NotNull + private static List toIndentUsageList(@NotNull TIntIntHashMap indentToUsages) { + List indentUsageInfos = ContainerUtil.newArrayList(); + TIntIntIterator it = indentToUsages.iterator(); + while (it.hasNext()) { + it.advance(); + indentUsageInfos.add(new IndentUsageInfo(it.key(), it.value())); + } + return indentUsageInfos; + } + + public void buildIndentToUsagesMap() { + myPreviousLineIndent = 0; + myPreviousRelativeIndent = 0; + + for (LineIndentInfo lineInfo : myLineInfos) { + if (lineInfo.isLineWithTabs()) { + myTotalLinesWithTabs++; + } + else if (lineInfo.isLineWithWhiteSpaceIndent()) { + handleWhiteSpaceIndent(lineInfo.getIndentSize()); + } + } + } + + @NotNull + private IndentData findParentIndent(int indent) { + while (myParentIndents.size() != 1 && myParentIndents.peek().indent > indent) { + myParentIndents.pop(); + } + return myParentIndents.peek(); + } + + private void handleWhiteSpaceIndent(int currentIndent) { + int relativeIndent = currentIndent - myPreviousLineIndent; + if (relativeIndent < 0) { + IndentData indentData = findParentIndent(currentIndent); + myPreviousLineIndent = indentData.indent; + myPreviousRelativeIndent = indentData.relativeIndent; + relativeIndent = currentIndent - myPreviousLineIndent; + } + + if (relativeIndent == 0) { + relativeIndent = myPreviousRelativeIndent; + } + else { + myParentIndents.push(new IndentData(currentIndent, relativeIndent)); + } + + increaseIndentUsage(relativeIndent); + + myPreviousRelativeIndent = relativeIndent; + myPreviousLineIndent = currentIndent; + myTotalLinesWithWhiteSpaces++; + } + + private void increaseIndentUsage(int relativeIndent) { + int timesUsed = myIndentToUsages.get(relativeIndent); + myIndentToUsages.put(relativeIndent, ++timesUsed); + } + + public int getTotalLinesWithLeadingTabs() { + return myTotalLinesWithTabs; + } + + public int getTotalLinesWithLeadingSpaces() { + return myTotalLinesWithWhiteSpaces; + } + + public IndentUsageInfo getMaxUsedIndentInfo(int rank) { + return myIndentUsages.get(rank); + } + + public int getTimesUsedIndent(int indent) { + return myIndentToUsages.get(indent); + } + + private static class IndentData { + public final int indent; + public final int relativeIndent; + + public IndentData(int indent, int relativeIndent) { + this.indent = indent; + this.relativeIndent = relativeIndent; + } + } +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfo.java b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfo.java new file mode 100644 index 000000000000..67b186504d06 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfo.java @@ -0,0 +1,56 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.codeStyle.autodetect; + +import org.jetbrains.annotations.NotNull; + +public class LineIndentInfo { + public static LineIndentInfo EMPTY_LINE = new LineIndentInfo(LineType.EMPTY_LINE, -1); + public static LineIndentInfo LINE_WITH_COMMENT = new LineIndentInfo(LineType.LINE_WITH_COMMENT, -1); + public static LineIndentInfo LINE_WITH_TABS = new LineIndentInfo(LineType.LINE_WITH_TABS, -1); + + private final int myIndentSize; + private final LineType myType; + + private LineIndentInfo(@NotNull LineType type, int indentSize) { + myType = type; + myIndentSize = indentSize; + } + + @NotNull + public static LineIndentInfo newWhiteSpaceIndent(int indentSize) { + return new LineIndentInfo(LineType.LINE_WITH_WHITESPACE_INDENT, indentSize); + } + + public int getIndentSize() { + return myIndentSize; + } + + public boolean isLineWithWhiteSpaceIndent() { + return myType == LineType.LINE_WITH_WHITESPACE_INDENT; + } + + public boolean isLineWithTabs() { + return myType == LineType.LINE_WITH_TABS; + } + + private enum LineType { + EMPTY_LINE, + LINE_WITH_COMMENT, + LINE_WITH_TABS, + LINE_WITH_WHITESPACE_INDENT + } +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfoBuilder.java b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfoBuilder.java new file mode 100644 index 000000000000..8efbbc495750 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfoBuilder.java @@ -0,0 +1,80 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.codeStyle.autodetect; + +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.text.CharArrayUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class LineIndentInfoBuilder { + private static final int MAX_LINES_TO_PROCESS = 500; + + private final CharSequence myText; + private final int myLength; + + public LineIndentInfoBuilder(@NotNull CharSequence text) { + myText = text; + myLength = text.length(); + } + + @NotNull + public List build() { + List lineIndentInfos = ContainerUtil.newArrayList(); + + int lineStartOffset = 0; + int currentLine = 0; + + while (lineStartOffset < myText.length() && currentLine < MAX_LINES_TO_PROCESS) { + int lineEndOffset = getLineEndOffset(lineStartOffset); + int textStartOffset = CharArrayUtil.shiftForward(myText, lineStartOffset, lineEndOffset, " \t"); + + if (textStartOffset != lineEndOffset) { + lineIndentInfos.add(createInfoFromWhiteSpaceRange(lineStartOffset, textStartOffset)); + } else { + lineIndentInfos.add(LineIndentInfo.EMPTY_LINE); + } + + lineStartOffset = lineEndOffset + 1; + currentLine++; + } + + return lineIndentInfos; + } + + @NotNull + private LineIndentInfo createInfoFromWhiteSpaceRange(int lineStartOffset, int textStartOffset) { + if (myText.charAt(textStartOffset) == '*') { + return LineIndentInfo.LINE_WITH_COMMENT; + } + else if (CharArrayUtil.indexOf(myText, "\t", lineStartOffset, textStartOffset) > 0) { + return LineIndentInfo.LINE_WITH_TABS; + } + else { + int indentSize = textStartOffset - lineStartOffset; + return LineIndentInfo.newWhiteSpaceIndent(indentSize); + } + } + + private int getLineEndOffset(int lineStartOffset) { + int lineEndOffset = CharArrayUtil.indexOf(myText, "\n", lineStartOffset, myLength); + if (lineEndOffset < 0) { + lineEndOffset = myText.length(); + } + return lineEndOffset; + } +} diff --git a/platform/platform-tests/testData/codeStyle/autodetect/manyComments.java b/platform/platform-tests/testData/codeStyle/autodetect/manyComments.java new file mode 100644 index 000000000000..7bc7a3a46982 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/autodetect/manyComments.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +public interface Doable { + + + /* + * + * + * + * + * + * + * + * + * + * + */ + public void count() { + } + + + /* + * + * + * + * + * + * + * + * + * + * + */ + public void test() { + } +} diff --git a/platform/platform-tests/testData/codeStyle/autodetect/manyZeroRelativeIndent.java b/platform/platform-tests/testData/codeStyle/autodetect/manyZeroRelativeIndent.java new file mode 100644 index 000000000000..2ee4c59848ec --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/autodetect/manyZeroRelativeIndent.java @@ -0,0 +1,31 @@ +class Test { + + public void test() { + // boolean function-available(string) + addFunction(decls, new FunctionImpl("function-available", XPathType.BOOLEAN, + new Parameter(XPathType.STRING, Parameter.Kind.REQUIRED))); + + // node-set current() + addFunction(decls, new FunctionImpl("current", XPathType.NODESET)); + + // EXSLT (http://www.exslt.org) extensions supported by Xalan & Saxon + addFunction(decls, EXSLT_DATE_TIME, new FunctionImpl("date", XPathType.STRING, optional_string)); + addFunction(decls, EXSLT_DATE_TIME, new FunctionImpl("date-time", XPathType.STRING)); + addFunction(decls, EXSLT_DATE_TIME, new FunctionImpl("day-abbreviation", XPathType.STRING, optional_string)); + addFunction(decls, EXSLT_DATE_TIME, new FunctionImpl("day-in-month", XPathType.NUMBER, optional_string)); + addFunction(decls, EXSLT_DATE_TIME, new FunctionImpl("day-in-week", XPathType.NUMBER, optional_string)); + addFunction(decls, EXSLT_DATE_TIME, new FunctionImpl("day-in-year", XPathType.NUMBER, optional_string)); + addFunction(decls, EXSLT_DATE_TIME, new FunctionImpl("day-name", XPathType.STRING, optional_string)); + addFunction(decls, EXSLT_DATE_TIME, new FunctionImpl("day-of-week-in-month", XPathType.NUMBER, optional_string)); + addFunction(decls, EXSLT_DATE_TIME, new FunctionImpl("hour-in-day", XPathType.NUMBER, optional_string)); + addFunction(decls, EXSLT_DATE_TIME, new FunctionImpl("leap-year", XPathType.BOOLEAN, optional_string)); + addFunction(decls, EXSLT_DATE_TIME, new FunctionImpl("minute-in-hour", XPathType.NUMBER, optional_string)); + addFunction(decls, EXSLT_DATE_TIME, new FunctionImpl("month-abbreviation", XPathType.STRING, optional_string)); + addFunction(decls, EXSLT_DATE_TIME, new FunctionImpl("month-in-year", XPathType.NUMBER, optional_string)); + addFunction(decls, EXSLT_DATE_TIME, new FunctionImpl("month-name", XPathType.STRING, optional_string)); + addFunction(decls, EXSLT_DATE_TIME, new FunctionImpl("second-in-minute", XPathType.NUMBER, optional_string)); + addFunction(decls, EXSLT_DATE_TIME, new FunctionImpl("time", XPathType.STRING, optional_string)); + addFunction(decls, EXSLT_DATE_TIME, new FunctionImpl("week-in-year", XPathType.NUMBER, optional_string)); + addFunction(decls, EXSLT_DATE_TIME, new FunctionImpl("year", XPathType.NUMBER, optional_string)); + } +} diff --git a/platform/platform-tests/testData/codeStyle/autodetect/simpleIndent.java b/platform/platform-tests/testData/codeStyle/autodetect/simpleIndent.java new file mode 100644 index 000000000000..c4cd369df732 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/autodetect/simpleIndent.java @@ -0,0 +1,14 @@ +public class A { + + public void test() { + int a = 2; + int c = 2; + int r = 3; + int rq = 3; + int rw = 3; + int re = 3; + } + + public void a() { + } +} diff --git a/platform/platform-tests/testSrc/com/intellij/psi/autodetect/IndentAutoDetectionTest.java b/platform/platform-tests/testSrc/com/intellij/psi/autodetect/IndentAutoDetectionTest.java new file mode 100644 index 000000000000..9d76dba6aff8 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/psi/autodetect/IndentAutoDetectionTest.java @@ -0,0 +1,135 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.autodetect; + +import com.intellij.openapi.editor.Document; +import com.intellij.psi.codeStyle.autodetect.*; +import com.intellij.testFramework.LightPlatformCodeInsightTestCase; +import com.intellij.testFramework.PlatformTestCase; +import com.intellij.testFramework.PlatformTestUtil; +import org.jetbrains.annotations.NotNull; +import org.junit.Assert; + +import java.io.File; +import java.util.List; + +public class IndentAutoDetectionTest extends LightPlatformCodeInsightTestCase { + private static final String BASE_PATH = "codeStyle/autodetect/"; + + static { + PlatformTestCase.initPlatformLangPrefix(); + } + + public void testSimpleIndent() { + doTestMaxUsedIndent(2, 6); + } + + public void testManyComments() { + doTestMaxUsedIndent(2, 6); + } + + public void testManyZeroRelativeIndent() { + doTestMaxUsedIndent(2); + } + + public void testSpacesToNumbers() throws Exception { + String text = " i\n" + + " a\n" + + " t\n"; + doTestLineToIndentMapping(text, 5, 4, 10); + } + + public void testEmptyLines() throws Exception { + doTestLineToIndentMapping(" \n\n\n", -1, -1, -1); + } + + public void testSpacesInSimpleClass() { + doTestLineToIndentMapping( + "public class A {\n" + + "\n" + + " public void test() {\n" + + " int a = 2;\n" + + " }\n" + + "\n" + + " public void a() {\n" + + " }\n" + + "}", + 0, -1, 4, 6, 4, -1, 4, 4, 0 + ); + } + + public void testComplexIndents() { + doTestLineToIndentMapping( + "class Test\n" + + "{\n" + + " int a;\n" + + " int b;\n" + + " \n" + + " public void test() {\n" + + " int c;\n" + + " }\n" + + " \n" + + " public void run() {\n" + + " Runnable runnable = new Runnable() {\n" + + " @Override\n" + + " public void run() {\n" + + " System.out.println(\"Hello!\");\n" + + " }\n" + + " };\n" + + " }\n" + + "}", + 0, 0, 2, 2, -1, 2, 4, 2, -1, 2, 4, 6, 6, 8, 6, 4, 2, 0 + ); + } + + public void doTestMaxUsedIndent(int indentExpected, int timesUsedExpected) { + IndentUsageInfo maxIndentExpected = new IndentUsageInfo(indentExpected, timesUsedExpected); + IndentUsageInfo indentInfo = getMaxUsedIndentInfo(); + Assert.assertEquals("Indent size mismatch", maxIndentExpected.getIndentSize(), indentInfo.getIndentSize()); + Assert.assertEquals("Indent size usage number mismatch", maxIndentExpected.getTimesUsed(), indentInfo.getTimesUsed()); + } + + public void doTestMaxUsedIndent(int indentExpected) { + IndentUsageInfo indentInfo = getMaxUsedIndentInfo(); + Assert.assertEquals("Indent size mismatch", indentExpected, indentInfo.getIndentSize()); + } + + @NotNull + private IndentUsageInfo getMaxUsedIndentInfo() { + configureByFile(getTestName(true) + ".java"); + Document document = getDocument(myFile); + List lines = new LineIndentInfoBuilder(document.getCharsSequence()).build(); + IndentUsageStatistics statistics = new IndentUsageStatistics(lines); + return statistics.getMaxUsedIndentInfo(0); + } + + private static void doTestLineToIndentMapping(@NotNull CharSequence text, int... spacesForLine) { + List list = new LineIndentInfoBuilder(text).build(); + Assert.assertEquals(list.size(), spacesForLine.length); + for (int i = 0; i < spacesForLine.length; i++) { + int indentSize = list.get(i).getIndentSize(); + Assert.assertEquals("Mismatch on line " + i, spacesForLine[i], indentSize); + } + } + + @Override + @NotNull + public String getTestDataPath() { + return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + + "/platform/platform-tests/testData/" + + BASE_PATH; + } +} From 884f5932434df925165f7c3dfc2395e1d4ddc504 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 10 Sep 2014 12:51:33 +0400 Subject: [PATCH 06/23] IDEA-129655 Inspections UI: Dragging details pane divider too far right makes it disappear --- .../codeInspection/ui/SingleInspectionProfilePanel.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java index 81d0bf651688..2320d059c146 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java @@ -1005,11 +1005,10 @@ public class SingleInspectionProfilePanel extends JPanel { northPanel.add(createTreeToolbarPanel().getComponent(), new GridBagConstraints(1, 0, 1, 1, 0.5, 1, GridBagConstraints.BASELINE_LEADING, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); treePanel.add(northPanel, BorderLayout.NORTH); - myMainSplitter = new Splitter(false); + myMainSplitter = new Splitter(false, myProperties.getFloat(VERTICAL_DIVIDER_PROPORTION, 0.5f), 0.01f, 0.99f); myMainSplitter.setFirstComponent(treePanel); myMainSplitter.setSecondComponent(myRightSplitter); myMainSplitter.setHonorComponentsMinimumSize(false); - myMainSplitter.setProportion(myProperties.getFloat(VERTICAL_DIVIDER_PROPORTION, 0.5f)); final JPanel panel = new JPanel(new BorderLayout()); panel.add(myMainSplitter, BorderLayout.CENTER); From b768f2177e1aae1aa00ee59c3e09832c4316500d Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 10 Sep 2014 13:05:48 +0400 Subject: [PATCH 07/23] PropertiesImplUtil: PsiDirectory#getFiles() inside read action --- .../intellij/lang/properties/PropertiesImplUtil.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java index 15e73791f8ea..502d9b4dc499 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java @@ -15,7 +15,6 @@ */ package com.intellij.lang.properties; -import com.intellij.lang.HtmlScriptContentProvider; import com.intellij.lang.properties.psi.PropertiesFile; import com.intellij.lang.properties.psi.PropertyKeyIndex; import com.intellij.lang.properties.xml.XmlPropertiesFileImpl; @@ -79,7 +78,13 @@ public class PropertiesImplUtil extends PropertiesUtil { private static ResourceBundle getResourceBundle(@NotNull final String baseName, @NotNull final PsiDirectory baseDirectory) { PropertiesFile defaultPropertiesFile = null; final ResourceBundleManager bundleBaseNameManager = ResourceBundleManager.getInstance(baseDirectory.getProject()); - for (final PsiFile psiFile : baseDirectory.getFiles()) { + final PsiFile[] psiFiles = ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public PsiFile[] compute() { + return baseDirectory.getFiles(); + } + }); + for (final PsiFile psiFile : psiFiles) { if (baseName.equals(bundleBaseNameManager.getBaseName(psiFile))) { final PropertiesFile propertiesFile = getPropertiesFile(psiFile); if (propertiesFile != null) { @@ -147,4 +152,4 @@ public class PropertiesImplUtil extends PropertiesUtil { } return getResourceBundle(baseName, baseDirectory); } -} +} \ No newline at end of file From 645968cec1dbb0a13f300c0b69b92ae1efbe478f Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 10 Sep 2014 13:22:49 +0400 Subject: [PATCH 08/23] InspectionsConfigTreeTable added additional description to LOG.assertTrue --- .../ui/inspectionsTree/InspectionsConfigTreeTable.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java index 5607816ad13c..fe36408cf61a 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java @@ -220,7 +220,7 @@ public class InspectionsConfigTreeTable extends TreeTable { @Override public void setValueAt(final Object aValue, final Object node, final int column) { LOG.assertTrue(column == IS_ENABLED_COLUMN); - LOG.assertTrue(aValue != null); + LOG.assertTrue(aValue != null, "node = " + node); final boolean doEnable = (Boolean) aValue; for (final InspectionConfigTreeNode aNode : InspectionsAggregationUtil.getInspectionsNodes((InspectionConfigTreeNode) node)) { final String toolId = aNode.getKey().toString(); From 4858542bb029786965e2dddd97dbacaa78f066a8 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 10 Sep 2014 13:30:44 +0400 Subject: [PATCH 09/23] extracted interface, eliminated possible exceptions due to small indent size diversity --- .../autodetect/IndentOptionsDetector.java | 24 +-- .../autodetect/IndentUsageStatistics.java | 122 +------------- .../autodetect/IndentUsageStatisticsImpl.java | 149 ++++++++++++++++++ .../autodetect/IndentAutoDetectionTest.java | 4 +- 4 files changed, 172 insertions(+), 127 deletions(-) create mode 100644 platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatisticsImpl.java diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentOptionsDetector.java b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentOptionsDetector.java index f677707ca79c..457a285a9e9c 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentOptionsDetector.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentOptionsDetector.java @@ -50,7 +50,7 @@ public class IndentOptionsDetector { if (myDocument != null) { List linesInfo = new LineIndentInfoBuilder(myDocument.getCharsSequence()).build(); - IndentUsageStatistics stats = new IndentUsageStatistics(linesInfo); + IndentUsageStatistics stats = new IndentUsageStatisticsImpl(linesInfo); adjustIndentOptions(indentOptions, stats); } @@ -80,18 +80,24 @@ public class IndentOptionsDetector { } private static int getPositiveIndentSize(@NotNull IndentUsageStatistics stats) { - IndentUsageInfo maxUsedIndentInfo = stats.getMaxUsedIndentInfo(0); - int maxIndentSize = maxUsedIndentInfo.getIndentSize(); - if (maxIndentSize == 0) { - maxUsedIndentInfo = stats.getMaxUsedIndentInfo(1); - maxIndentSize = maxUsedIndentInfo.getIndentSize(); + int totalIndentSizesDetected = stats.getTotalIndentSizesDetected(); + if (totalIndentSizesDetected == 0) return -1; + + IndentUsageInfo maxUsedIndentInfo = stats.getKMostUsedIndentInfo(0); + int maxUsedIndentSize = maxUsedIndentInfo.getIndentSize(); + + if (maxUsedIndentSize == 0) { + if (totalIndentSizesDetected < 1) return -1; + + maxUsedIndentInfo = stats.getKMostUsedIndentInfo(1); + maxUsedIndentSize = maxUsedIndentInfo.getIndentSize(); } - if (maxIndentSize <= MAX_INDENT_TO_DETECT) { - int totalUsagesWithoutZeroIndent = stats.getTotalLinesWithLeadingSpaces() - stats.getTimesUsedIndent(0); + if (maxUsedIndentSize <= MAX_INDENT_TO_DETECT) { + int totalUsagesWithoutZeroIndent = stats.getTotalLinesWithLeadingSpaces() - stats.getTimesIndentUsed(0); double usageRate = (double)maxUsedIndentInfo.getTimesUsed() / totalUsagesWithoutZeroIndent; if (usageRate > RATE_THRESHOLD) { - return maxIndentSize; + return maxUsedIndentSize; } } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatistics.java b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatistics.java index 27cfcdd22341..7e3bee7221da 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatistics.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatistics.java @@ -15,126 +15,16 @@ */ package com.intellij.psi.codeStyle.autodetect; -import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.Stack; -import gnu.trove.TIntIntHashMap; -import gnu.trove.TIntIntIterator; -import org.jetbrains.annotations.NotNull; +public interface IndentUsageStatistics { -import java.util.Comparator; -import java.util.List; + int getTotalLinesWithLeadingTabs(); -public class IndentUsageStatistics { - private static final Comparator DECREASING_ORDER = new Comparator() { - @Override - public int compare(@NotNull IndentUsageInfo o1, @NotNull IndentUsageInfo o2) { - return o1.getTimesUsed() < o2.getTimesUsed() ? 1 : o1.getTimesUsed() == o2.getTimesUsed() ? 0 : -1; - } - }; + int getTotalLinesWithLeadingSpaces(); - private List myLineInfos; + IndentUsageInfo getKMostUsedIndentInfo(int k); - private int myPreviousLineIndent; - private int myPreviousRelativeIndent; + int getTotalIndentSizesDetected(); - private int myTotalLinesWithTabs = 0; - private int myTotalLinesWithWhiteSpaces = 0; + int getTimesIndentUsed(int indent); - private TIntIntHashMap myIndentToUsages = new TIntIntHashMap(); - private List myIndentUsages = ContainerUtil.newArrayList(); - private Stack myParentIndents = ContainerUtil.newStack(new IndentData(0, 0)); - - public IndentUsageStatistics(@NotNull List lineInfos) { - myLineInfos = lineInfos; - buildIndentToUsagesMap(); - myIndentUsages = toIndentUsageList(myIndentToUsages); - ContainerUtil.sort(myIndentUsages, DECREASING_ORDER); - } - - @NotNull - private static List toIndentUsageList(@NotNull TIntIntHashMap indentToUsages) { - List indentUsageInfos = ContainerUtil.newArrayList(); - TIntIntIterator it = indentToUsages.iterator(); - while (it.hasNext()) { - it.advance(); - indentUsageInfos.add(new IndentUsageInfo(it.key(), it.value())); - } - return indentUsageInfos; - } - - public void buildIndentToUsagesMap() { - myPreviousLineIndent = 0; - myPreviousRelativeIndent = 0; - - for (LineIndentInfo lineInfo : myLineInfos) { - if (lineInfo.isLineWithTabs()) { - myTotalLinesWithTabs++; - } - else if (lineInfo.isLineWithWhiteSpaceIndent()) { - handleWhiteSpaceIndent(lineInfo.getIndentSize()); - } - } - } - - @NotNull - private IndentData findParentIndent(int indent) { - while (myParentIndents.size() != 1 && myParentIndents.peek().indent > indent) { - myParentIndents.pop(); - } - return myParentIndents.peek(); - } - - private void handleWhiteSpaceIndent(int currentIndent) { - int relativeIndent = currentIndent - myPreviousLineIndent; - if (relativeIndent < 0) { - IndentData indentData = findParentIndent(currentIndent); - myPreviousLineIndent = indentData.indent; - myPreviousRelativeIndent = indentData.relativeIndent; - relativeIndent = currentIndent - myPreviousLineIndent; - } - - if (relativeIndent == 0) { - relativeIndent = myPreviousRelativeIndent; - } - else { - myParentIndents.push(new IndentData(currentIndent, relativeIndent)); - } - - increaseIndentUsage(relativeIndent); - - myPreviousRelativeIndent = relativeIndent; - myPreviousLineIndent = currentIndent; - myTotalLinesWithWhiteSpaces++; - } - - private void increaseIndentUsage(int relativeIndent) { - int timesUsed = myIndentToUsages.get(relativeIndent); - myIndentToUsages.put(relativeIndent, ++timesUsed); - } - - public int getTotalLinesWithLeadingTabs() { - return myTotalLinesWithTabs; - } - - public int getTotalLinesWithLeadingSpaces() { - return myTotalLinesWithWhiteSpaces; - } - - public IndentUsageInfo getMaxUsedIndentInfo(int rank) { - return myIndentUsages.get(rank); - } - - public int getTimesUsedIndent(int indent) { - return myIndentToUsages.get(indent); - } - - private static class IndentData { - public final int indent; - public final int relativeIndent; - - public IndentData(int indent, int relativeIndent) { - this.indent = indent; - this.relativeIndent = relativeIndent; - } - } } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatisticsImpl.java b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatisticsImpl.java new file mode 100644 index 000000000000..6578b5faa3e3 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentUsageStatisticsImpl.java @@ -0,0 +1,149 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.codeStyle.autodetect; + +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.Stack; +import gnu.trove.TIntIntHashMap; +import gnu.trove.TIntIntIterator; +import org.jetbrains.annotations.NotNull; + +import java.util.Comparator; +import java.util.List; + +public class IndentUsageStatisticsImpl implements IndentUsageStatistics { + private static final Comparator DECREASING_ORDER = new Comparator() { + @Override + public int compare(@NotNull IndentUsageInfo o1, @NotNull IndentUsageInfo o2) { + return o1.getTimesUsed() < o2.getTimesUsed() ? 1 : o1.getTimesUsed() == o2.getTimesUsed() ? 0 : -1; + } + }; + + private List myLineInfos; + + private int myPreviousLineIndent; + private int myPreviousRelativeIndent; + + private int myTotalLinesWithTabs = 0; + private int myTotalLinesWithWhiteSpaces = 0; + + private TIntIntHashMap myIndentToUsages = new TIntIntHashMap(); + private List myIndentUsages = ContainerUtil.newArrayList(); + private Stack myParentIndents = ContainerUtil.newStack(new IndentData(0, 0)); + + public IndentUsageStatisticsImpl(@NotNull List lineInfos) { + myLineInfos = lineInfos; + buildIndentToUsagesMap(); + myIndentUsages = toIndentUsageList(myIndentToUsages); + ContainerUtil.sort(myIndentUsages, DECREASING_ORDER); + } + + @NotNull + private static List toIndentUsageList(@NotNull TIntIntHashMap indentToUsages) { + List indentUsageInfos = ContainerUtil.newArrayList(); + TIntIntIterator it = indentToUsages.iterator(); + while (it.hasNext()) { + it.advance(); + indentUsageInfos.add(new IndentUsageInfo(it.key(), it.value())); + } + return indentUsageInfos; + } + + public void buildIndentToUsagesMap() { + myPreviousLineIndent = 0; + myPreviousRelativeIndent = 0; + + for (LineIndentInfo lineInfo : myLineInfos) { + if (lineInfo.isLineWithTabs()) { + myTotalLinesWithTabs++; + } + else if (lineInfo.isLineWithWhiteSpaceIndent()) { + handleWhiteSpaceIndent(lineInfo.getIndentSize()); + } + } + } + + @NotNull + private IndentData findParentIndent(int indent) { + while (myParentIndents.size() != 1 && myParentIndents.peek().indent > indent) { + myParentIndents.pop(); + } + return myParentIndents.peek(); + } + + private void handleWhiteSpaceIndent(int currentIndent) { + int relativeIndent = currentIndent - myPreviousLineIndent; + if (relativeIndent < 0) { + IndentData indentData = findParentIndent(currentIndent); + myPreviousLineIndent = indentData.indent; + myPreviousRelativeIndent = indentData.relativeIndent; + relativeIndent = currentIndent - myPreviousLineIndent; + } + + if (relativeIndent == 0) { + relativeIndent = myPreviousRelativeIndent; + } + else { + myParentIndents.push(new IndentData(currentIndent, relativeIndent)); + } + + increaseIndentUsage(relativeIndent); + + myPreviousRelativeIndent = relativeIndent; + myPreviousLineIndent = currentIndent; + myTotalLinesWithWhiteSpaces++; + } + + private void increaseIndentUsage(int relativeIndent) { + int timesUsed = myIndentToUsages.get(relativeIndent); + myIndentToUsages.put(relativeIndent, ++timesUsed); + } + + @Override + public int getTotalLinesWithLeadingTabs() { + return myTotalLinesWithTabs; + } + + @Override + public int getTotalLinesWithLeadingSpaces() { + return myTotalLinesWithWhiteSpaces; + } + + @Override + public IndentUsageInfo getKMostUsedIndentInfo(int k) { + return myIndentUsages.get(k); + } + + @Override + public int getTimesIndentUsed(int indent) { + return myIndentToUsages.get(indent); + } + + @Override + public int getTotalIndentSizesDetected() { + return myIndentToUsages.size(); + } + + private static class IndentData { + public final int indent; + public final int relativeIndent; + + public IndentData(int indent, int relativeIndent) { + this.indent = indent; + this.relativeIndent = relativeIndent; + } + } +} diff --git a/platform/platform-tests/testSrc/com/intellij/psi/autodetect/IndentAutoDetectionTest.java b/platform/platform-tests/testSrc/com/intellij/psi/autodetect/IndentAutoDetectionTest.java index 9d76dba6aff8..4b59416de0d9 100644 --- a/platform/platform-tests/testSrc/com/intellij/psi/autodetect/IndentAutoDetectionTest.java +++ b/platform/platform-tests/testSrc/com/intellij/psi/autodetect/IndentAutoDetectionTest.java @@ -112,8 +112,8 @@ public class IndentAutoDetectionTest extends LightPlatformCodeInsightTestCase { configureByFile(getTestName(true) + ".java"); Document document = getDocument(myFile); List lines = new LineIndentInfoBuilder(document.getCharsSequence()).build(); - IndentUsageStatistics statistics = new IndentUsageStatistics(lines); - return statistics.getMaxUsedIndentInfo(0); + IndentUsageStatistics statistics = new IndentUsageStatisticsImpl(lines); + return statistics.getKMostUsedIndentInfo(0); } private static void doTestLineToIndentMapping(@NotNull CharSequence text, int... spacesForLine) { From 287bddaf63f5ed6ce1e05a13b824df3c67117039 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 10 Sep 2014 13:26:21 +0400 Subject: [PATCH 10/23] extract light method object: remove command from operation on non-phisical elements --- .../ExtractLightMethodObjectHandler.java | 37 ++++++++----------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractLightMethodObjectHandler.java b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractLightMethodObjectHandler.java index a88e4383dc7a..bbfc5fbbeecb 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractLightMethodObjectHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractLightMethodObjectHandler.java @@ -148,31 +148,24 @@ public class ExtractLightMethodObjectHandler { if (extractProcessor.prepare() && CommonRefactoringUtil .checkReadOnlyStatus(project, extractProcessor.getTargetClass().getContainingFile())) { if (extractProcessor.showDialog()) { - CommandProcessor.getInstance().executeCommand(project, new Runnable() { - public void run() { - try { - extractProcessor.doExtract(); - - final UsageInfo[] usages = extractMethodObjectProcessor.findUsages(); - extractMethodObjectProcessor.performRefactoring(usages); - extractMethodObjectProcessor.runChangeSignature(); - } - catch (IncorrectOperationException e) { - LOG.error(e); - } - if (extractMethodObjectProcessor.isCreateInnerClass()) { - extractMethodObjectProcessor.changeInstanceAccess(project); - } - final PsiElement method = extractMethodObjectProcessor.getMethod(); - LOG.assertTrue(method != null); - method.delete(); - } - }, ExtractMethodObjectProcessor.REFACTORING_NAME, ExtractMethodObjectProcessor.REFACTORING_NAME); + try { + extractProcessor.doExtract(); + final UsageInfo[] usages = extractMethodObjectProcessor.findUsages(); + extractMethodObjectProcessor.performRefactoring(usages); + extractMethodObjectProcessor.runChangeSignature(); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + if (extractMethodObjectProcessor.isCreateInnerClass()) { + extractMethodObjectProcessor.changeInstanceAccess(project); + } + final PsiElement method = extractMethodObjectProcessor.getMethod(); + LOG.assertTrue(method != null); + method.delete(); } } - PsiDocumentManager.getInstance(project).commitAllDocuments(); - final String generatedCall = copy.getText().substring(start, outStatement.getTextOffset()); return new ExtractedData(generatedCall, (PsiClass)CodeStyleManager.getInstance(project).reformat(extractMethodObjectProcessor.getInnerClass()), From 0c55ed79f946e74926eefb6c25a92be9a8c18d66 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 10 Sep 2014 13:55:48 +0400 Subject: [PATCH 11/23] extract light method object: do nothing if prepare failed --- .../extractMethodObject/ExtractLightMethodObjectHandler.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractLightMethodObjectHandler.java b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractLightMethodObjectHandler.java index bbfc5fbbeecb..5a7e5ca64ea1 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractLightMethodObjectHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractLightMethodObjectHandler.java @@ -145,8 +145,7 @@ public class ExtractLightMethodObjectHandler { extractMethodObjectProcessor.getExtractProcessor().setShowErrorDialogs(false); final ExtractMethodObjectProcessor.MyExtractMethodProcessor extractProcessor = extractMethodObjectProcessor.getExtractProcessor(); - if (extractProcessor.prepare() && CommonRefactoringUtil - .checkReadOnlyStatus(project, extractProcessor.getTargetClass().getContainingFile())) { + if (extractProcessor.prepare()) { if (extractProcessor.showDialog()) { try { extractProcessor.doExtract(); @@ -164,6 +163,8 @@ public class ExtractLightMethodObjectHandler { LOG.assertTrue(method != null); method.delete(); } + } else { + return null; } final String generatedCall = copy.getText().substring(start, outStatement.getTextOffset()); From e277799073e3d491c761ff7e8754bab85268a947 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Wed, 10 Sep 2014 12:02:00 +0400 Subject: [PATCH 12/23] remove workaround from launcher.py Translating [almost] all arguments into absolute path could be invalid (if some of arguments are not paths) Other launchers should work fine with relative paths now. --- .../actions/CreateLauncherScriptAction.java | 4 +- platform/platform-resources/src/launcher.py | 45 ++++++------------- 2 files changed, 15 insertions(+), 34 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java b/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java index 411f2d9d93bb..0b696c8f4496 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java @@ -134,12 +134,12 @@ public class CreateLauncherScriptAction extends DumbAwareAction { private static File createLauncherScriptFile() throws IOException, ExecutionException { String runPath = PathManager.getHomePath(); + final String productName = ApplicationNamesInfo.getInstance().getProductName().toLowerCase(); if (!SystemInfo.isMac) { // for Macs just use "*.app" - final String productName = ApplicationNamesInfo.getInstance().getProductName().toLowerCase(); runPath += "/bin/" + productName + ".sh"; } else if (runPath.endsWith(CONTENTS)) { - runPath = runPath.substring(0, runPath.length() - CONTENTS.length()); + runPath += "/MacOS/" + productName; } String launcherContents = ExecUtil.loadTemplate(CreateLauncherScriptAction.class.getClassLoader(), "launcher.py", newHashMap(asList("$CONFIG_PATH$", "$RUN_PATH$"), diff --git a/platform/platform-resources/src/launcher.py b/platform/platform-resources/src/launcher.py index f04a26cb2c83..f0d85de12a1a 100644 --- a/platform/platform-resources/src/launcher.py +++ b/platform/platform-resources/src/launcher.py @@ -18,30 +18,19 @@ for i, arg in enumerate(sys.argv[1:]): print(('Usage:\n' + \ ' {0} -h |-? | --help\n' + \ ' {0} [-l|--line line] file[:line]\n' + \ - ' {0} diff \n' + \ - ' {0} merge [base] ').format(sys.argv[0])) + ' {0} diff ' + \ + ' {0} merge [base] ').format(sys.argv[0])) exit(0) - elif arg == 'diff' and i == 0: - args.append(arg) - elif arg == 'merge' and i == 0: - args.append(arg) - elif arg == '-l' or arg == '--line': - args.append(arg) - skip_next = True - elif skip_next: - args.append(arg) - skip_next = False - else: - if ':' in arg: - file_path, line_number = arg.rsplit(':', 1) - if line_number.isdigit(): - args.append('-l') - args.append(line_number) - args.append(os.path.abspath(file_path)) - else: - args.append(os.path.abspath(arg)) + elif ':' in arg: + file_path, line_number = arg.rsplit(':', 1) + if line_number.isdigit(): + args.append('-l') + args.append(line_number) + args.append(file_path) else: - args.append(os.path.abspath(arg)) + args.append(arg) + else: + args.append(arg) def launch_with_port(port): found = False @@ -90,13 +79,5 @@ if port == -1: else: if launch_with_port(port): exit() -if sys.platform == "darwin": - # Mac OS: RUN_PATH is *.app path - if len(args): - args.insert(0, "--args") - os.execvp("open", ["-a", RUN_PATH] + args) -else: - # unix common - bin_dir, bin_file = os.path.split(RUN_PATH) - os.chdir(bin_dir) - os.execv(bin_file, [bin_file] + args) \ No newline at end of file +bin_dir, bin_file = os.path.split(RUN_PATH) +os.execv(RUN_PATH, [bin_file] + args) \ No newline at end of file From 0bec7d37a9d5d31febf42d3f23e0b4b05ffaa837 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Wed, 10 Sep 2014 13:25:43 +0400 Subject: [PATCH 13/23] remove duplicated path transformation --- platform/platform-resources/src/launcher.py | 1 - 1 file changed, 1 deletion(-) diff --git a/platform/platform-resources/src/launcher.py b/platform/platform-resources/src/launcher.py index f0d85de12a1a..440f716f8ebf 100644 --- a/platform/platform-resources/src/launcher.py +++ b/platform/platform-resources/src/launcher.py @@ -46,7 +46,6 @@ def launch_with_port(port): try: path_len = struct.unpack(">h", s.recv(2))[0] path = s.recv(path_len) - path = os.path.abspath(path) if os.path.abspath(path) == os.path.abspath(CONFIG_PATH): found = True break From dcdfe430b32fafe5bc779bee17bb94cb796e127f Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 10 Sep 2014 14:17:45 +0400 Subject: [PATCH 14/23] don't hide java classes from module content if the same directory is added as source and classes root to a library --- .../ide/projectView/impl/ClassesTreeStructureProvider.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/java/java-impl/src/com/intellij/ide/projectView/impl/ClassesTreeStructureProvider.java b/java/java-impl/src/com/intellij/ide/projectView/impl/ClassesTreeStructureProvider.java index 7e0515726610..ef745b3aaa8b 100644 --- a/java/java-impl/src/com/intellij/ide/projectView/impl/ClassesTreeStructureProvider.java +++ b/java/java-impl/src/com/intellij/ide/projectView/impl/ClassesTreeStructureProvider.java @@ -62,8 +62,9 @@ public class ClassesTreeStructureProvider implements SelectableTreeStructureProv if (originalElement instanceof PsiFile) { PsiFile classFile = (PsiFile)originalElement; final VirtualFile virtualClassFile = classFile.getVirtualFile(); - if (virtualClassFile != null && fileIndex.isInLibraryClasses(virtualClassFile) && - classOwner.getManager().areElementsEquivalent(classOwner.getContainingDirectory(), classFile.getContainingDirectory())) { + if (virtualClassFile != null && fileIndex.isInLibraryClasses(virtualClassFile) + && !classOwner.getManager().areElementsEquivalent(classOwner, classFile) + && classOwner.getManager().areElementsEquivalent(classOwner.getContainingDirectory(), classFile.getContainingDirectory())) { continue; } } From 1ac7e4cc5454aeebf358a718b53bcd4746547d79 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 10 Sep 2014 14:13:34 +0400 Subject: [PATCH 15/23] [git] don't load refs by default, e.g. in commits for push dialog --- plugins/git4idea/src/git4idea/history/GitHistoryUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java index a0030c8158a5..ef30e79436f3 100644 --- a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java +++ b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java @@ -841,7 +841,7 @@ public class GitHistoryUtils { if (factory == null) { return Collections.emptyList(); } - return loadDetails(project, root, true, true, new NullableFunction() { + return loadDetails(project, root, false, true, new NullableFunction() { @Override @Nullable public GitCommit fun(GitLogRecord record) { From b80923d64fe2a09140821c81daa4b84d48bda212 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 8 Sep 2014 20:20:13 +0400 Subject: [PATCH 16/23] javadoc --- .../util/src/com/intellij/util/ui/UIUtil.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index aec2a356ded0..28c95b80763c 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -2085,7 +2085,7 @@ public class UIUtil { * Invoke and wait in the event dispatch thread * or in the current thread if the current thread * is event queue thread. - * + * DO NOT INVOKE THIS METHOD FROM UNDER READ ACTION. * @param runnable a runnable to invoke * @see #invokeAndWaitIfNeeded(com.intellij.util.ThrowableRunnable) */ @@ -2103,6 +2103,14 @@ public class UIUtil { } } + /** + * Invoke and wait in the event dispatch thread + * or in the current thread if the current thread + * is event queue thread. + * DO NOT INVOKE THIS METHOD FROM UNDER READ ACTION. + * @param computable a runnable to invoke + * @see #invokeAndWaitIfNeeded(com.intellij.util.ThrowableRunnable) + */ public static T invokeAndWaitIfNeeded(@NotNull final Computable computable) { final Ref result = Ref.create(); invokeAndWaitIfNeeded(new Runnable() { @@ -2114,6 +2122,14 @@ public class UIUtil { return result.get(); } + /** + * Invoke and wait in the event dispatch thread + * or in the current thread if the current thread + * is event queue thread. + * DO NOT INVOKE THIS METHOD FROM UNDER READ ACTION. + * @param runnable a runnable to invoke + * @see #invokeAndWaitIfNeeded(com.intellij.util.ThrowableRunnable) + */ public static void invokeAndWaitIfNeeded(@NotNull final ThrowableRunnable runnable) throws Throwable { if (SwingUtilities.isEventDispatchThread()) { runnable.run(); @@ -2890,6 +2906,7 @@ public class UIUtil { new Thread(new Runnable() { // The wrapper thread is unnecessary, unless it blocks on the // Clip finishing; see comments. + @Override public void run() { try { Clip clip = AudioSystem.getClip(); From e8023a2f7e39da5abe8ab934bdf998fa83c20225 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 9 Sep 2014 17:51:14 +0400 Subject: [PATCH 17/23] EA-58671 - assert: ComponentManagerImpl.getPicoContainer --- .../openapi/editor/impl/LazyRangeMarkerFactoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java index 5a9c704173aa..c4b9a38914cf 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java @@ -56,7 +56,7 @@ public class LazyRangeMarkerFactoryImpl extends LazyRangeMarkerFactory { private void transformRangeMarkers(@NotNull DocumentEvent e) { Document document = e.getDocument(); VirtualFile file = fileDocumentManager.getFile(document); - if (file == null) { + if (file == null || myProject.isDisposed()) { return; } From 8e838f3f0542722e43faf8e7c11c871f47554887 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 9 Sep 2014 19:49:44 +0400 Subject: [PATCH 18/23] cleanup --- .../psi/impl/compiled/ClsFileImpl.java | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java index 6ab8174ce28a..20c11a7ccb39 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java @@ -27,8 +27,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.extensions.PluginId; import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.progress.NonCancelableSection; -import com.intellij.openapi.progress.ProgressIndicatorProvider; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DefaultProjectFactory; import com.intellij.openapi.roots.FileIndexFacade; import com.intellij.openapi.ui.Queryable; @@ -323,7 +322,7 @@ public class ClsFileImpl extends ClsRepositoryPsiElement synchronized (myMirrorLock) { mirrorTreeElement = myMirrorFileElement; if (mirrorTreeElement == null) { - VirtualFile file = getVirtualFile(); + final VirtualFile file = getVirtualFile(); CharSequence mirrorText = ClassFileDecompiler.decompileText(file); String ext = JavaFileType.INSTANCE.getDefaultExtension(); @@ -335,16 +334,18 @@ public class ClsFileImpl extends ClsRepositoryPsiElement mirrorTreeElement = SourceTreeToPsiMap.psiToTreeNotNull(mirror); // IMPORTANT: do not take lock too early - FileDocumentManager.saveToString() can run write action - NonCancelableSection section = ProgressIndicatorProvider.startNonCancelableSectionIfSupported(); - try { - setMirror(mirrorTreeElement); - } - catch (InvalidMirrorException e) { - LOG.error(file.getPath(), wrapException(e, file)); - } - finally { - section.done(); - } + final TreeElement finalMirrorTreeElement = mirrorTreeElement; + ProgressManager.getInstance().executeNonCancelableSection(new Runnable() { + @Override + public void run() { + try { + setMirror(finalMirrorTreeElement); + } + catch (InvalidMirrorException e) { + LOG.error(file.getPath(), wrapException(e, file)); + } + } + }); myMirrorFileElement = mirrorTreeElement; } From 76c9d57ee565ed98072d4dc94e6550a5fa72a3db Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Wed, 10 Sep 2014 13:09:38 +0400 Subject: [PATCH 19/23] compiling evaluator - allow to run private this methods --- .../ui/impl/watch/CompilingEvaluator.java | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/CompilingEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/CompilingEvaluator.java index be5e5c367990..e9915bd1c65b 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/CompilingEvaluator.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/CompilingEvaluator.java @@ -28,12 +28,13 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Key; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiCodeFragment; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiJavaFile; +import com.intellij.psi.*; import com.intellij.refactoring.extractMethodObject.ExtractLightMethodObjectHandler; import com.sun.jdi.*; +import org.jetbrains.org.objectweb.asm.ClassReader; +import org.jetbrains.org.objectweb.asm.ClassVisitor; +import org.jetbrains.org.objectweb.asm.ClassWriter; +import org.jetbrains.org.objectweb.asm.Opcodes; import javax.tools.*; import java.io.ByteArrayOutputStream; @@ -41,7 +42,6 @@ import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.Locale; /** * @author egor @@ -141,7 +141,7 @@ public class CompilingEvaluator implements ExpressionEvaluator { if (cls.getName().contains(getGenClassName())) { Method defineMethod = ((ClassType)classLoader.referenceType()).concreteMethodByName("defineClass", "(Ljava/lang/String;[BII)Ljava/lang/Class;"); - byte[] bytes = cls.toByteArray(); + byte[] bytes = changeSuperToMagicAccessor(cls.toByteArray()); ArrayList args = new ArrayList(); args.add(proxy.mirrorOf(cls.myOrigName)); args.add(mirrorOf(bytes, context, process)); @@ -153,6 +153,21 @@ public class CompilingEvaluator implements ExpressionEvaluator { return (ClassType)process.findClass(context, getGenPackageName() + '.' + getGenClassName(), classLoader); } + private static byte[] changeSuperToMagicAccessor(byte[] bytes) { + ClassWriter classWriter = new ClassWriter(0); + ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM5, classWriter) { + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + if ("java/lang/Object".equals(superName)) { + superName = "sun/reflect/MagicAccessorImpl"; + } + super.visit(version, access, name, signature, superName, interfaces); + } + }; + new ClassReader(bytes).accept(classVisitor, 0); + return classWriter.toByteArray(); + } + private static ArrayReference mirrorOf(byte[] bytes, EvaluationContext context, DebugProcess process) throws EvaluateException, InvalidTypeException, ClassNotLoadedException { ArrayType arrayClass = (ArrayType)process.findClass(context, "byte[]", context.getClassLoader()); From bbb5c1151356b35e9d0f9b974e0a16ab9b8267a1 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Wed, 10 Sep 2014 14:50:35 +0400 Subject: [PATCH 20/23] compiling evaluator - move extract method phase inside the evaluator --- .../engine/JavaDebuggerEvaluator.java | 24 ++--------------- .../ui/impl/watch/CompilingEvaluator.java | 12 +++++---- .../ui/impl/watch/EvaluationDescriptor.java | 26 ++++++++++++++----- 3 files changed, 28 insertions(+), 34 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebuggerEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebuggerEvaluator.java index 949f1a33d606..2eab90666967 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebuggerEvaluator.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebuggerEvaluator.java @@ -20,20 +20,15 @@ import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; import com.intellij.debugger.engine.evaluation.TextWithImportsImpl; import com.intellij.debugger.engine.events.DebuggerContextCommandImpl; import com.intellij.debugger.impl.EditorTextProvider; -import com.intellij.debugger.ui.impl.watch.CompilingEvaluator; import com.intellij.debugger.ui.impl.watch.WatchItemDescriptor; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.registry.Registry; -import com.intellij.psi.PsiCodeFragment; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; -import com.intellij.refactoring.extractMethodObject.ExtractLightMethodObjectHandler; import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.evaluation.XDebuggerEvaluator; @@ -45,8 +40,6 @@ import org.jetbrains.annotations.Nullable; * @author egor */ public class JavaDebuggerEvaluator extends XDebuggerEvaluator { - private static final Logger LOG = Logger.getInstance(JavaDebuggerEvaluator.class); - private final DebugProcessImpl myDebugProcess; private final JavaStackFrame myStackFrame; @@ -66,21 +59,6 @@ public class JavaDebuggerEvaluator extends XDebuggerEvaluator { public void evaluate(@NotNull final XExpression expression, @NotNull final XEvaluationCallback callback, @Nullable XSourcePosition expressionPosition) { - final Project project = myDebugProcess.getProject(); - final WatchItemDescriptor descriptor = new WatchItemDescriptor(project, TextWithImportsImpl.fromXExpression(expression)); - if (Registry.is("debugger.compiling.evaluator")) { - try { - PsiElement element = myDebugProcess.getDebuggerContext().getContextElement(); - PsiFile psiFile = element.getContainingFile(); - PsiCodeFragment fragment = descriptor.createCodeFragment(element); - ExtractLightMethodObjectHandler.ExtractedData data = - ExtractLightMethodObjectHandler.extractLightMethodObject(project, psiFile, fragment, CompilingEvaluator.getGeneratedClassName()); - descriptor.putUserData(CompilingEvaluator.COMPILING_EVALUATOR_DATA, data); - } - catch (Exception e) { - LOG.info(e); - } - } myDebugProcess.getManagerThread().schedule(new DebuggerContextCommandImpl(myDebugProcess.getDebuggerContext()) { @Override public Priority getPriority() { @@ -89,6 +67,8 @@ public class JavaDebuggerEvaluator extends XDebuggerEvaluator { @Override public void threadAction() { + WatchItemDescriptor descriptor = new WatchItemDescriptor(myDebugProcess.getProject(), TextWithImportsImpl.fromXExpression( + expression)); EvaluationContextImpl evalContext = myStackFrame.getFrameDebuggerContext().createEvaluationContext(); if (evalContext == null) { callback.errorOccurred("Context is not available"); diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/CompilingEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/CompilingEvaluator.java index e9915bd1c65b..439bff108409 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/CompilingEvaluator.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/CompilingEvaluator.java @@ -28,9 +28,13 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Key; -import com.intellij.psi.*; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiCodeFragment; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiJavaFile; import com.intellij.refactoring.extractMethodObject.ExtractLightMethodObjectHandler; import com.sun.jdi.*; +import org.jetbrains.annotations.NotNull; import org.jetbrains.org.objectweb.asm.ClassReader; import org.jetbrains.org.objectweb.asm.ClassVisitor; import org.jetbrains.org.objectweb.asm.ClassWriter; @@ -50,15 +54,13 @@ public class CompilingEvaluator implements ExpressionEvaluator { private final TextWithImports myText; private final PsiCodeFragment myCodeFragment; private final PsiElement myPsiContext; - private final ExtractLightMethodObjectHandler.ExtractedData myData; + @NotNull private final ExtractLightMethodObjectHandler.ExtractedData myData; private final EvaluationDescriptor myDescriptor; - public static Key COMPILING_EVALUATOR_DATA = new Key("COMPILING_EVALUATOR_DATA"); - public CompilingEvaluator(TextWithImports text, PsiCodeFragment codeFragment, PsiElement context, - ExtractLightMethodObjectHandler.ExtractedData data, + @NotNull ExtractLightMethodObjectHandler.ExtractedData data, EvaluationDescriptor descriptor) { myText = text; myCodeFragment = codeFragment; diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/EvaluationDescriptor.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/EvaluationDescriptor.java index 334ef14118ed..05e0a1fe6aec 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/EvaluationDescriptor.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/EvaluationDescriptor.java @@ -34,11 +34,9 @@ import com.intellij.debugger.jdi.StackFrameProxyImpl; import com.intellij.debugger.jdi.VirtualMachineProxyImpl; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.registry.Registry; -import com.intellij.psi.PsiCodeFragment; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiExpression; -import com.intellij.psi.PsiExpressionCodeFragment; +import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.refactoring.extractMethod.PrepareFailedException; import com.intellij.refactoring.extractMethodObject.ExtractLightMethodObjectHandler; import com.sun.jdi.ObjectCollectedException; import com.sun.jdi.ObjectReference; @@ -89,12 +87,26 @@ public abstract class EvaluationDescriptor extends ValueDescriptorImpl{ }); } catch (UnsupportedExpressionException ex) { - final ExtractLightMethodObjectHandler.ExtractedData data = getUserData(CompilingEvaluator.COMPILING_EVALUATOR_DATA); - if (Registry.is("debugger.compiling.evaluator") && data != null) { + if (Registry.is("debugger.compiling.evaluator")) { evaluator = DebuggerInvocationUtil.commitAndRunReadAction(myProject, new EvaluatingComputable() { public ExpressionEvaluator compute() throws EvaluateException { final PsiElement psiContext = PositionUtil.getContextElement(evaluationContext); - return new CompilingEvaluator(getEvaluationText(), getEvaluationCode(thisEvaluationContext), psiContext, data, EvaluationDescriptor.this); + if (psiContext == null) { + return null; + } + PsiFile psiFile = psiContext.getContainingFile(); + PsiCodeFragment fragment = createCodeFragment(psiContext); + try { + ExtractLightMethodObjectHandler.ExtractedData data = ExtractLightMethodObjectHandler.extractLightMethodObject(myProject, + psiFile, fragment, CompilingEvaluator.getGeneratedClassName()); + if (data != null) { + return new CompilingEvaluator(getEvaluationText(), getEvaluationCode(thisEvaluationContext), psiContext, data, + EvaluationDescriptor.this); + } + } + catch (PrepareFailedException ignored) { + } + return null; } }); } From 7e583c973405b4ffbbb419e477bf26c5bc98f7a3 Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Wed, 10 Sep 2014 15:21:37 +0400 Subject: [PATCH 21/23] IDEA-85423 IntelliJ behaves erratically when exiting the GUI designer --- .../intellij/designer/LightFillLayout.java | 122 +++++++++ .../intellij/designer/LightToolWindow.java | 27 +- .../designer/LightToolWindowManager.java | 22 +- .../designer/DesignerToolWindowManager.java | 2 +- .../designer/PaletteToolWindowContent.java | 11 - .../designSurface/DesignerEditorPanel.java | 99 +------ .../designer/palette/PalettePanel.java | 6 - .../palette/PaletteToolWindowManager.java | 4 +- plugins/ui-designer/src/META-INF/plugin.xml | 4 +- .../palette/impl/PaletteComponentList.java | 12 +- .../ide/palette/impl/PaletteManager.java | 229 ---------------- .../impl/PaletteToolWindowManager.java | 118 ++++++++ .../ide/palette/impl/PaletteWindow.java | 101 ++++--- .../uiDesigner/AbstractToolWindowManager.java | 67 +++++ .../intellij/uiDesigner/FormEditingUtil.java | 10 +- .../uiDesigner/FormHighlightingPass.java | 6 +- .../actions/ExpandSelectionAction.java | 13 +- .../uiDesigner/actions/ResetValueAction.java | 7 +- .../actions/SelectAllComponentsAction.java | 14 +- .../actions/ShrinkSelectionAction.java | 6 +- .../componentTree/ComponentTreeBuilder.java | 4 +- .../DesignDropTargetListener.java | 32 ++- .../uiDesigner/designSurface/GlassLayer.java | 4 +- .../uiDesigner/designSurface/GuiEditor.java | 155 ++++++----- .../InsertComponentProcessor.java | 12 +- .../designSurface/MainProcessor.java | 12 +- .../designSurface/PassiveDecorationLayer.java | 4 +- .../designSurface/QuickFixManagerImpl.java | 10 +- .../uiDesigner/editor/UIFormEditor.java | 4 +- .../propertyInspector/DesignerToolWindow.java | 139 ++++++++++ .../DesignerToolWindowManager.java | 131 +++++++++ .../PropertyInspectorTable.java | 3 +- .../UIDesignerToolWindowManager.java | 257 ------------------ .../editors/BindingEditor.java | 5 +- .../editors/string/StringEditor.java | 6 +- .../properties/BindingProperty.java | 4 +- .../uiDesigner/quickFixes/ShowHintAction.java | 5 +- .../src/messages/UIDesignerBundle.properties | 3 +- 38 files changed, 848 insertions(+), 822 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/designer/LightFillLayout.java delete mode 100644 plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteManager.java create mode 100644 plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteToolWindowManager.java create mode 100644 plugins/ui-designer/src/com/intellij/uiDesigner/AbstractToolWindowManager.java create mode 100644 plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/DesignerToolWindow.java create mode 100644 plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/DesignerToolWindowManager.java delete mode 100644 plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/UIDesignerToolWindowManager.java diff --git a/platform/platform-impl/src/com/intellij/designer/LightFillLayout.java b/platform/platform-impl/src/com/intellij/designer/LightFillLayout.java new file mode 100644 index 000000000000..af0ca87f1e05 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/designer/LightFillLayout.java @@ -0,0 +1,122 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.designer; + +import com.intellij.util.Function; + +import javax.swing.*; +import java.awt.*; + +/** + * @author Alexander Lobas + */ +public class LightFillLayout implements LayoutManager2 { + @Override + public void addLayoutComponent(Component comp, Object constraints) { + } + + @Override + public float getLayoutAlignmentX(Container target) { + return 0.5f; + } + + @Override + public float getLayoutAlignmentY(Container target) { + return 0.5f; + } + + @Override + public void invalidateLayout(Container target) { + } + + @Override + public void addLayoutComponent(String name, Component comp) { + } + + @Override + public void removeLayoutComponent(Component comp) { + } + + @Override + public Dimension maximumLayoutSize(Container target) { + return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + @Override + public Dimension preferredLayoutSize(Container parent) { + return layoutSize(parent, new Function() { + @Override + public Dimension fun(Component component) { + return component.getPreferredSize(); + } + }); + } + + @Override + public Dimension minimumLayoutSize(Container parent) { + return layoutSize(parent, new Function() { + @Override + public Dimension fun(Component component) { + return component.getMinimumSize(); + } + }); + } + + private static Dimension layoutSize(Container parent, Function getSize) { + Component toolbar = parent.getComponent(0); + Dimension toolbarSize = toolbar.isVisible() ? getSize.fun(toolbar) : new Dimension(); + Dimension contentSize = getSize.fun(parent.getComponent(1)); + int extraWidth = 0; + JComponent jParent = (JComponent)parent; + if (jParent.getClientProperty(LightToolWindow.LEFT_MIN_KEY) != null) { + extraWidth += LightToolWindow.MINIMIZE_WIDTH; + } + if (jParent.getClientProperty(LightToolWindow.RIGHT_MIN_KEY) != null) { + extraWidth += LightToolWindow.MINIMIZE_WIDTH; + } + return new Dimension(Math.max(toolbarSize.width, contentSize.width + extraWidth), toolbarSize.height + contentSize.height); + } + + @Override + public void layoutContainer(Container parent) { + int leftWidth = 0; + int rightWidth = 0; + JComponent jParent = (JComponent)parent; + JComponent left = (JComponent)jParent.getClientProperty(LightToolWindow.LEFT_MIN_KEY); + if (left != null) { + leftWidth = LightToolWindow.MINIMIZE_WIDTH; + } + JComponent right = (JComponent)jParent.getClientProperty(LightToolWindow.RIGHT_MIN_KEY); + if (right != null) { + rightWidth = LightToolWindow.MINIMIZE_WIDTH; + } + int extraWidth = leftWidth + rightWidth; + + int width = parent.getWidth() - extraWidth; + int height = parent.getHeight(); + Component toolbar = parent.getComponent(0); + Dimension toolbarSize = toolbar.isVisible() ? toolbar.getPreferredSize() : new Dimension(); + toolbar.setBounds(leftWidth, 0, width, toolbarSize.height); + parent.getComponent(1).setBounds(leftWidth, toolbarSize.height, width, height - toolbarSize.height); + + if (left != null) { + left.setBounds(0, 0, leftWidth, height); + } + if (right != null) { + right.setBounds(width + leftWidth, 0, rightWidth, height); + } + } +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java b/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java index 0d644217ef90..ce3cb33deb90 100644 --- a/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java +++ b/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java @@ -35,6 +35,8 @@ import com.intellij.ui.components.panels.Wrapper; import com.intellij.ui.tabs.TabsUtil; import com.intellij.util.ui.EmptyIcon; import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; @@ -47,6 +49,7 @@ import java.awt.image.BufferedImage; public class LightToolWindow extends JPanel { public static final String LEFT_MIN_KEY = "left"; public static final String RIGHT_MIN_KEY = "right"; + public static final int MINIMIZE_WIDTH = 25; private static final String IGNORE_WIDTH_KEY = "ignore_width"; private final LightToolWindowContent myContent; @@ -79,19 +82,19 @@ public class LightToolWindow extends JPanel { } }; - public LightToolWindow(LightToolWindowContent content, - String title, - Icon icon, - JComponent component, - JComponent focusedComponent, - ThreeComponentsSplitter contentSplitter, - ToolWindowAnchor anchor, - LightToolWindowManager manager, - Project project, - PropertiesComponent propertiesComponent, - String key, + public LightToolWindow(@NotNull LightToolWindowContent content, + @NotNull String title, + @NotNull Icon icon, + @NotNull JComponent component, + @NotNull JComponent focusedComponent, + @NotNull ThreeComponentsSplitter contentSplitter, + @Nullable ToolWindowAnchor anchor, + @NotNull LightToolWindowManager manager, + @NotNull Project project, + @NotNull PropertiesComponent propertiesComponent, + @NotNull String key, int defaultWidth, - AnAction[] actions) { + @Nullable AnAction[] actions) { super(new BorderLayout()); myContent = content; myFocusedComponent = focusedComponent; diff --git a/platform/platform-impl/src/com/intellij/designer/LightToolWindowManager.java b/platform/platform-impl/src/com/intellij/designer/LightToolWindowManager.java index e6d887ea2c43..0bfb083dec94 100644 --- a/platform/platform-impl/src/com/intellij/designer/LightToolWindowManager.java +++ b/platform/platform-impl/src/com/intellij/designer/LightToolWindowManager.java @@ -204,33 +204,33 @@ public abstract class LightToolWindowManager implements ProjectComponent { protected abstract ToggleEditorModeAction createToggleAction(ToolWindowAnchor anchor); - public final void bind(DesignerEditorPanelFacade designer) { + public final void bind(@NotNull DesignerEditorPanelFacade designer) { if (isEditorMode()) { myCreateAction.run(designer); } } - public final void dispose(DesignerEditorPanelFacade designer) { + public final void dispose(@NotNull DesignerEditorPanelFacade designer) { if (isEditorMode()) { disposeContent(designer); } } - protected final Object getContent(DesignerEditorPanelFacade designer) { + protected final Object getContent(@NotNull DesignerEditorPanelFacade designer) { LightToolWindow toolWindow = (LightToolWindow)designer.getClientProperty(getComponentName()); return toolWindow.getContent(); } - protected abstract LightToolWindow createContent(DesignerEditorPanelFacade designer); + protected abstract LightToolWindow createContent(@NotNull DesignerEditorPanelFacade designer); - protected final LightToolWindow createContent(DesignerEditorPanelFacade designer, - LightToolWindowContent content, - String title, - Icon icon, - JComponent component, - JComponent focusedComponent, + protected final LightToolWindow createContent(@NotNull DesignerEditorPanelFacade designer, + @NotNull LightToolWindowContent content, + @NotNull String title, + @NotNull Icon icon, + @NotNull JComponent component, + @NotNull JComponent focusedComponent, int defaultWidth, - AnAction[] actions) { + @Nullable AnAction[] actions) { return new LightToolWindow(content, title, icon, diff --git a/plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindowManager.java b/plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindowManager.java index 2631e83625a5..a35be4d28697 100644 --- a/plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindowManager.java +++ b/plugins/ui-designer-core/src/com/intellij/designer/DesignerToolWindowManager.java @@ -126,7 +126,7 @@ public final class DesignerToolWindowManager extends AbstractToolWindowManager { ////////////////////////////////////////////////////////////////////////////////////////// @Override - protected LightToolWindow createContent(DesignerEditorPanelFacade designer) { + protected LightToolWindow createContent(@NotNull DesignerEditorPanelFacade designer) { DesignerToolWindow toolWindowContent = new DesignerToolWindow(myProject, false); toolWindowContent.update((DesignerEditorPanel)designer); diff --git a/plugins/ui-designer-core/src/com/intellij/designer/PaletteToolWindowContent.java b/plugins/ui-designer-core/src/com/intellij/designer/PaletteToolWindowContent.java index 5e77e7c0b02d..69949491991a 100644 --- a/plugins/ui-designer-core/src/com/intellij/designer/PaletteToolWindowContent.java +++ b/plugins/ui-designer-core/src/com/intellij/designer/PaletteToolWindowContent.java @@ -15,19 +15,8 @@ */ package com.intellij.designer; -import com.intellij.designer.designSurface.DesignerEditorPanel; -import com.intellij.designer.palette.PaletteItem; -import org.jetbrains.annotations.Nullable; - public interface PaletteToolWindowContent extends LightToolWindowContent { - @Nullable - PaletteItem getActiveItem(); - void clearActiveItem(); void refresh(); - - boolean isEmpty(); - - void loadPalette(@Nullable DesignerEditorPanel designer); } \ No newline at end of file diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/DesignerEditorPanel.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/DesignerEditorPanel.java index c3aaa6939f54..87f9e2cb3332 100644 --- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/DesignerEditorPanel.java +++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/DesignerEditorPanel.java @@ -177,7 +177,7 @@ public abstract class DesignerEditorPanel extends JPanel } private void createDesignerCard() { - JPanel panel = new JPanel(new FillLayout()); + JPanel panel = new JPanel(new LightFillLayout()); myContentSplitter.setInnerComponent(panel); myLayeredPane = new MyLayeredPane(); @@ -859,103 +859,6 @@ public abstract class DesignerEditorPanel extends JPanel // ////////////////////////////////////////////////////////////////////////////////////////// - private static final int MINIMIZE_WIDTH = 25; - - private static final class FillLayout implements LayoutManager2 { - @Override - public void addLayoutComponent(Component comp, Object constraints) { - } - - @Override - public float getLayoutAlignmentX(Container target) { - return 0.5f; - } - - @Override - public float getLayoutAlignmentY(Container target) { - return 0.5f; - } - - @Override - public void invalidateLayout(Container target) { - } - - @Override - public void addLayoutComponent(String name, Component comp) { - } - - @Override - public void removeLayoutComponent(Component comp) { - } - - @Override - public Dimension maximumLayoutSize(Container target) { - return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); - } - - @Override - public Dimension preferredLayoutSize(Container parent) { - Component toolbar = parent.getComponent(0); - Dimension toolbarSize = toolbar.isVisible() ? toolbar.getPreferredSize() : new Dimension(); - Dimension contentSize = parent.getComponent(1).getPreferredSize(); - int extraWidth = 0; - JComponent jParent = (JComponent)parent; - if (jParent.getClientProperty(LightToolWindow.LEFT_MIN_KEY) != null) { - extraWidth += MINIMIZE_WIDTH; - } - if (jParent.getClientProperty(LightToolWindow.RIGHT_MIN_KEY) != null) { - extraWidth += MINIMIZE_WIDTH; - } - return new Dimension(Math.max(toolbarSize.width, contentSize.width + extraWidth), toolbarSize.height + contentSize.height); - } - - @Override - public Dimension minimumLayoutSize(Container parent) { - Component toolbar = parent.getComponent(0); - Dimension toolbarSize = toolbar.isVisible() ? toolbar.getMinimumSize() : new Dimension(); - Dimension contentSize = parent.getComponent(1).getMinimumSize(); - int extraWidth = 0; - JComponent jParent = (JComponent)parent; - if (jParent.getClientProperty(LightToolWindow.LEFT_MIN_KEY) != null) { - extraWidth += MINIMIZE_WIDTH; - } - if (jParent.getClientProperty(LightToolWindow.RIGHT_MIN_KEY) != null) { - extraWidth += MINIMIZE_WIDTH; - } - return new Dimension(Math.max(toolbarSize.width, contentSize.width + extraWidth), toolbarSize.height + contentSize.height); - } - - @Override - public void layoutContainer(Container parent) { - int leftWidth = 0; - int rightWidth = 0; - JComponent jParent = (JComponent)parent; - JComponent left = (JComponent)jParent.getClientProperty(LightToolWindow.LEFT_MIN_KEY); - if (left != null) { - leftWidth = MINIMIZE_WIDTH; - } - JComponent right = (JComponent)jParent.getClientProperty(LightToolWindow.RIGHT_MIN_KEY); - if (right != null) { - rightWidth = MINIMIZE_WIDTH; - } - int extraWidth = leftWidth + rightWidth; - - int width = parent.getWidth() - extraWidth; - int height = parent.getHeight(); - Component toolbar = parent.getComponent(0); - Dimension toolbarSize = toolbar.isVisible() ? toolbar.getPreferredSize() : new Dimension(); - toolbar.setBounds(leftWidth, 0, width, toolbarSize.height); - parent.getComponent(1).setBounds(leftWidth, toolbarSize.height, width, height - toolbarSize.height); - - if (left != null) { - left.setBounds(0, 0, leftWidth, height); - } - if (right != null) { - right.setBounds(width + leftWidth, 0, rightWidth, height); - } - } - } - /** * Size of the scene, in scroll pane view port pixels. */ diff --git a/plugins/ui-designer-core/src/com/intellij/designer/palette/PalettePanel.java b/plugins/ui-designer-core/src/com/intellij/designer/palette/PalettePanel.java index a7dfef3758ae..f81baca17551 100644 --- a/plugins/ui-designer-core/src/com/intellij/designer/palette/PalettePanel.java +++ b/plugins/ui-designer-core/src/com/intellij/designer/palette/PalettePanel.java @@ -131,12 +131,6 @@ public class PalettePanel extends JPanel implements DataProvider, PaletteToolWin repaint(); } - @Override - public boolean isEmpty() { - return myGroups.isEmpty(); - } - - @Override public void loadPalette(@Nullable DesignerEditorPanel designer) { if (myDesigner == null && designer == null) { return; diff --git a/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteToolWindowManager.java b/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteToolWindowManager.java index 63631f772665..3fddf66eaad6 100644 --- a/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteToolWindowManager.java +++ b/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteToolWindowManager.java @@ -89,7 +89,7 @@ public class PaletteToolWindowManager extends AbstractToolWindowManager { protected void updateToolWindow(@Nullable DesignerEditorPanelFacade designer) { myToolWindowPanel.loadPalette((DesignerEditorPanel)designer); - if (myToolWindowPanel.isEmpty()) { + if (designer == null) { myToolWindow.setAvailable(false, null); } else { @@ -116,7 +116,7 @@ public class PaletteToolWindowManager extends AbstractToolWindowManager { ////////////////////////////////////////////////////////////////////////////////////////// @Override - protected LightToolWindow createContent(DesignerEditorPanelFacade designer) { + protected LightToolWindow createContent(@NotNull DesignerEditorPanelFacade designer) { PalettePanel palettePanel = new PalettePanel(); palettePanel.loadPalette((DesignerEditorPanel)designer); diff --git a/plugins/ui-designer/src/META-INF/plugin.xml b/plugins/ui-designer/src/META-INF/plugin.xml index 1871b77a7cb8..1dbd8d76a91c 100644 --- a/plugins/ui-designer/src/META-INF/plugin.xml +++ b/plugins/ui-designer/src/META-INF/plugin.xml @@ -147,12 +147,12 @@ - com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager + com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager - com.intellij.ide.palette.impl.PaletteManager + com.intellij.ide.palette.impl.PaletteToolWindowManager com.intellij.uiDesigner.clientProperties.ClientPropertiesManager diff --git a/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteComponentList.java b/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteComponentList.java index ea4f6de53401..77b58a922a87 100644 --- a/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteComponentList.java +++ b/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteComponentList.java @@ -42,14 +42,16 @@ import java.awt.event.*; */ public class PaletteComponentList extends JBList { private final Project myProject; + private final PaletteWindow myPalette; private final PaletteGroup myGroup; private int myHoverIndex = -1; private int myBeforeClickSelectedRow = -1; private int myDropTargetIndex = -1; private boolean myNeedClearSelection = false; - public PaletteComponentList(Project project, PaletteGroup group) { + public PaletteComponentList(Project project, PaletteWindow palette, PaletteGroup group) { myProject = project; + myPalette = palette; myGroup = group; setModel(new AbstractListModel() { public int getSize() { @@ -118,15 +120,15 @@ public class PaletteComponentList extends JBList { addKeyListener(new KeyListener() { public void keyPressed(KeyEvent e) { - PaletteManager.getInstance(myProject).notifyKeyEvent(e); + myPalette.notifyKeyEvent(e); } public void keyReleased(KeyEvent e) { - PaletteManager.getInstance(myProject).notifyKeyEvent(e); + myPalette.notifyKeyEvent(e); } public void keyTyped(KeyEvent e) { - PaletteManager.getInstance(myProject).notifyKeyEvent(e); + myPalette.notifyKeyEvent(e); } }); @@ -395,7 +397,7 @@ public class PaletteComponentList extends JBList { } public void dropActionChanged(final int gestureModifiers) { - PaletteManager.getInstance(myProject).notifyDropActionChanged(gestureModifiers); + myPalette.notifyDropActionChanged(gestureModifiers); } } } diff --git a/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteManager.java b/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteManager.java deleted file mode 100644 index 1ad6a1cd858d..000000000000 --- a/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteManager.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.intellij.ide.palette.impl; - -import com.intellij.icons.AllIcons; -import com.intellij.ide.IdeBundle; -import com.intellij.ide.palette.PaletteDragEventListener; -import com.intellij.ide.palette.PaletteItem; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.components.ProjectComponent; -import com.intellij.openapi.fileEditor.FileEditorManager; -import com.intellij.openapi.fileEditor.FileEditorManagerEvent; -import com.intellij.openapi.fileEditor.FileEditorManagerListener; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.startup.StartupManager; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.wm.ToolWindow; -import com.intellij.openapi.wm.ToolWindowAnchor; -import com.intellij.openapi.wm.ToolWindowManager; -import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.ui.update.MergingUpdateQueue; -import com.intellij.util.ui.update.Update; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.util.List; - -/** - * @author yole - */ -public class PaletteManager implements ProjectComponent { - private final Project myProject; - private final FileEditorManager myFileEditorManager; - private PaletteWindow myPaletteWindow; - private ToolWindow myPaletteToolWindow; - private final List myKeyListeners = ContainerUtil.createLockFreeCopyOnWriteList(); - private final List myDragEventListeners = ContainerUtil.createLockFreeCopyOnWriteList(); - private final List mySelectionListeners = ContainerUtil.createLockFreeCopyOnWriteList(); - - public PaletteManager(Project project, FileEditorManager fileEditorManager) { - myProject = project; - myFileEditorManager = fileEditorManager; - } - - @Override - public void projectOpened() { - if (!ApplicationManager.getApplication().isHeadlessEnvironment()) { - StartupManager.getInstance(myProject).registerPostStartupActivity(new Runnable() { - @Override - public void run() { - myPaletteWindow = new PaletteWindow(myProject); - myPaletteToolWindow = ToolWindowManager.getInstance(myProject). - registerToolWindow(IdeBundle.message("toolwindow.palette"), - myPaletteWindow, - ToolWindowAnchor.RIGHT, - myProject, - true); - myPaletteToolWindow.setIcon(AllIcons.Toolwindows.ToolWindowPalette); - setContent(); - final MyFileEditorManagerListener myListener = new MyFileEditorManagerListener(); - myFileEditorManager.addFileEditorManagerListener(myListener, myProject); - } - }); - } - } - - @Override - public void projectClosed() { - if (myPaletteWindow != null) { - myPaletteWindow.dispose(); - ToolWindowManager.getInstance(myProject).unregisterToolWindow(IdeBundle.message("toolwindow.palette")); - myPaletteWindow = null; - } - } - - @Override - @NotNull - public String getComponentName() { - return "PaletteManager"; - } - - @Override - public void initComponent() { - } - - @Override - public void disposeComponent() { - if (myPaletteWindow != null) { - myPaletteWindow.dispose(); - } - } - - public static PaletteManager getInstance(final Project project) { - return project.getComponent(PaletteManager.class); - } - - public void clearActiveItem() { - if (myPaletteWindow != null) { - myPaletteWindow.clearActiveItem(); - } - } - - @Nullable - public PaletteItem getActiveItem() { - if (myPaletteWindow != null) { - return myPaletteWindow.getActiveItem(); - } - return null; - } - - @Nullable - public T getActiveItem(Class cls) { - PaletteItem item = getActiveItem(); - if (item != null && item.getClass().isInstance(item)) { - //noinspection unchecked - return (T)item; - } - return null; - } - - public void addKeyListener(KeyListener l) { - myKeyListeners.add(l); - } - - public void removeKeyListener(KeyListener l) { - myKeyListeners.remove(l); - } - - public void addDragEventListener(PaletteDragEventListener l) { - myDragEventListeners.add(l); - } - - public void removeDragEventListener(PaletteDragEventListener l) { - myDragEventListeners.remove(l); - } - - public void addSelectionListener(ListSelectionListener l) { - mySelectionListeners.add(l); - } - - public void removeSelectionListener(ListSelectionListener l) { - mySelectionListeners.remove(l); - } - - private final MergingUpdateQueue myQueue = new MergingUpdateQueue("palette", 200, true, null); - - private void processFileEditorChange(@Nullable final VirtualFile selectedFile) { - myQueue.cancelAllUpdates(); - myQueue.queue(new Update("update") { - @Override - public void run() { - if (myPaletteWindow == null) return; - myPaletteWindow.refreshPaletteIfChanged(selectedFile); - setContent(); - } - }); - } - - private void setContent() { - if (myPaletteWindow.getActiveGroupCount() == 0) { - myPaletteToolWindow.setAvailable(false, null); - } - else { - myPaletteToolWindow.setAvailable(true, null); - myPaletteToolWindow.show(null); - } - } - - void notifyKeyEvent(final KeyEvent e) { - for (KeyListener l : myKeyListeners) { - if (e.getID() == KeyEvent.KEY_PRESSED) { - l.keyPressed(e); - } - else if (e.getID() == KeyEvent.KEY_RELEASED) { - l.keyReleased(e); - } - else if (e.getID() == KeyEvent.KEY_TYPED) { - l.keyTyped(e); - } - } - } - - void notifyDropActionChanged(int gestureModifiers) { - for (PaletteDragEventListener l : myDragEventListeners) { - l.dropActionChanged(gestureModifiers); - } - } - - void notifySelectionChanged(final ListSelectionEvent event) { - for (ListSelectionListener l : mySelectionListeners) { - l.valueChanged(event); - } - } - - private class MyFileEditorManagerListener implements FileEditorManagerListener { - @Override - public void fileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) { - processFileEditorChange(file); - } - - @Override - public void fileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) { - processFileEditorChange(null); - } - - @Override - public void selectionChanged(@NotNull FileEditorManagerEvent event) { - processFileEditorChange(event.getNewFile()); - } - } -} diff --git a/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteToolWindowManager.java b/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteToolWindowManager.java new file mode 100644 index 000000000000..c6fe8756d1f5 --- /dev/null +++ b/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteToolWindowManager.java @@ -0,0 +1,118 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.ide.palette.impl; + +import com.intellij.designer.DesignerEditorPanelFacade; +import com.intellij.designer.LightToolWindow; +import com.intellij.icons.AllIcons; +import com.intellij.ide.IdeBundle; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.wm.ToolWindowAnchor; +import com.intellij.openapi.wm.ToolWindowManager; +import com.intellij.ui.content.Content; +import com.intellij.ui.content.ContentManager; +import com.intellij.uiDesigner.AbstractToolWindowManager; +import com.intellij.uiDesigner.designSurface.GuiEditor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Alexander Lobas + */ +public class PaletteToolWindowManager extends AbstractToolWindowManager { + private final PaletteWindow myToolWindowPanel; + + public PaletteToolWindowManager(Project project, FileEditorManager fileEditorManager) { + super(project, fileEditorManager); + myToolWindowPanel = ApplicationManager.getApplication().isHeadlessEnvironment() ? null : new PaletteWindow(project); + } + + public static PaletteWindow getInstance(GuiEditor designer) { + PaletteToolWindowManager manager = getInstance(designer.getProject()); + if (manager.isEditorMode()) { + return (PaletteWindow)manager.getContent(designer); + } + return manager.myToolWindowPanel; + } + + public static PaletteToolWindowManager getInstance(Project project) { + return project.getComponent(PaletteToolWindowManager.class); + } + + @Override + protected void initToolWindow() { + myToolWindow = ToolWindowManager.getInstance(myProject) + .registerToolWindow(IdeBundle.message("toolwindow.palette"), false, getAnchor(), myProject, true); + myToolWindow.setIcon(AllIcons.Toolwindows.ToolWindowPalette); + initGearActions(); + + ContentManager contentManager = myToolWindow.getContentManager(); + Content content = contentManager.getFactory().createContent(myToolWindowPanel, null, false); + content.setCloseable(false); + content.setPreferredFocusableComponent(myToolWindowPanel); + contentManager.addContent(content); + contentManager.setSelectedContent(content, true); + myToolWindow.setAvailable(false, null); + } + + @Override + protected void updateToolWindow(@Nullable DesignerEditorPanelFacade designer) { + myToolWindowPanel.refreshPaletteIfChanged((GuiEditor)designer); + + if (designer == null) { + myToolWindow.setAvailable(false, null); + } + else { + myToolWindow.setAvailable(true, null); + myToolWindow.show(null); + } + } + + @Override + protected ToolWindowAnchor getAnchor() { + return ToolWindowAnchor.RIGHT; + } + + @Override + protected LightToolWindow createContent(@NotNull DesignerEditorPanelFacade designer) { + PaletteWindow palettePanel = new PaletteWindow(myProject); + palettePanel.refreshPaletteIfChanged((GuiEditor)designer); + + return createContent(designer, + palettePanel, + IdeBundle.message("toolwindow.palette"), + AllIcons.Toolwindows.ToolWindowPalette, + palettePanel, + palettePanel, + 180, + null); + } + + @Override + public void disposeComponent() { + if (myToolWindowPanel != null) { + myToolWindowPanel.dispose(); + } + } + + @NotNull + @Override + public String getComponentName() { + return "PaletteManager"; + } +} \ No newline at end of file diff --git a/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteWindow.java b/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteWindow.java index 27f280386731..0c7b57ce999c 100644 --- a/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteWindow.java +++ b/plugins/ui-designer/src/com/intellij/ide/palette/impl/PaletteWindow.java @@ -15,18 +15,19 @@ */ package com.intellij.ide.palette.impl; +import com.intellij.designer.LightToolWindowContent; import com.intellij.ide.palette.PaletteGroup; import com.intellij.ide.palette.PaletteItem; import com.intellij.ide.palette.PaletteItemProvider; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.extensions.Extensions; -import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.PopupHandler; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.components.JBTabbedPane; +import com.intellij.uiDesigner.designSurface.GuiEditor; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.NonNls; @@ -48,7 +49,7 @@ import java.util.*; /** * @author yole */ -public class PaletteWindow extends JPanel implements DataProvider { +public class PaletteWindow extends JPanel implements LightToolWindowContent, DataProvider { private final Project myProject; private final ArrayList myGroupHeaders = new ArrayList(); private final PaletteItemProvider[] myProviders; @@ -60,7 +61,6 @@ public class PaletteWindow extends JPanel implements DataProvider { private PaletteGroupHeader myLastFocusedGroup; @NonNls private static final String ourHelpID = "guiDesigner.uiTour.palette"; - private PaletteManager myPaletteManager; private final DragSourceListener myDragSourceListener = new DragSourceAdapter() { @Override @@ -74,20 +74,17 @@ public class PaletteWindow extends JPanel implements DataProvider { } }; + private GuiEditor myDesigner; + public PaletteWindow(Project project) { myProject = project; - myPaletteManager = PaletteManager.getInstance(myProject); myProviders = Extensions.getExtensions(PaletteItemProvider.EP_NAME, project); - for (PaletteItemProvider provider : myProviders) { - provider.addListener(myPropertyChangeListener); - } setLayout(new GridLayout(1, 1)); myScrollPane.addMouseListener(new MyScrollPanePopupHandler()); myScrollPane.setBorder(null); KeyStroke escStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); new ClearActiveItemAction().registerCustomShortcutSet(new CustomShortcutSet(escStroke), myScrollPane); - refreshPalette(); if (!ApplicationManager.getApplication().isHeadlessEnvironment()) { DragSource.getDefaultDragSource().addDragSourceListener(myDragSourceListener); @@ -95,16 +92,40 @@ public class PaletteWindow extends JPanel implements DataProvider { } public void dispose() { + removePaletteProviderListener(); + if (!ApplicationManager.getApplication().isHeadlessEnvironment()) { DragSource.getDefaultDragSource().removeDragSourceListener(myDragSourceListener); } } - public void refreshPalette() { - refreshPalette(null); + private void addPaletteProviderListener() { + for (PaletteItemProvider provider : myProviders) { + provider.addListener(myPropertyChangeListener); + } } - public void refreshPalette(@Nullable VirtualFile selectedFile) { + private void removePaletteProviderListener() { + for (PaletteItemProvider provider : myProviders) { + provider.removeListener(myPropertyChangeListener); + } + } + + public void refreshPaletteIfChanged(@Nullable GuiEditor designer) { + removePaletteProviderListener(); + myDesigner = designer; + if (designer != null) { + addPaletteProviderListener(); + } + + VirtualFile file = designer == null ? null : designer.getFile(); + Set currentGroups = new HashSet(collectCurrentGroups(file)); + if (!currentGroups.equals(myGroups)) { + refreshPalette(file); + } + } + + private void refreshPalette(@Nullable VirtualFile selectedFile) { for (PaletteGroupHeader groupHeader : myGroupHeaders) { groupHeader.getComponentList().removeListSelectionListener(myListSelectionListener); } @@ -161,7 +182,7 @@ public class PaletteWindow extends JPanel implements DataProvider { myGroupHeaders.add(groupHeader); myGroups.add(group); control.add(groupHeader); - PaletteComponentList componentList = new PaletteComponentList(myProject, group); + PaletteComponentList componentList = new PaletteComponentList(myProject, this, group); control.add(componentList); groupHeader.setComponentList(componentList); componentList.addListSelectionListener(myListSelectionListener); @@ -177,12 +198,6 @@ public class PaletteWindow extends JPanel implements DataProvider { private ArrayList collectCurrentGroups(@Nullable VirtualFile selectedFile) { ArrayList result = new ArrayList(); - if (selectedFile == null) { - VirtualFile[] editedFiles = FileEditorManager.getInstance(myProject).getSelectedFiles(); - if (editedFiles.length > 0) { - selectedFile = editedFiles[0]; - } - } if (selectedFile != null) { for (PaletteItemProvider provider : myProviders) { PaletteGroup[] groups = provider.getActiveGroups(selectedFile); @@ -192,24 +207,13 @@ public class PaletteWindow extends JPanel implements DataProvider { return result; } - public void refreshPaletteIfChanged(VirtualFile selectedFile) { - Set currentGroups = new HashSet(collectCurrentGroups(selectedFile)); - if (!currentGroups.equals(myGroups)) { - refreshPalette(selectedFile); - } - } - - public int getActiveGroupCount() { - return myGroups.size(); - } - public void clearActiveItem() { if (getActiveItem() == null) return; for (PaletteGroupHeader group : myGroupHeaders) { group.getComponentList().clearSelection(); } ListSelectionEvent event = new ListSelectionEvent(this, -1, -1, false); - myPaletteManager.notifySelectionChanged(event); + notifySelectionChanged(event); } @Nullable @@ -222,6 +226,16 @@ public class PaletteWindow extends JPanel implements DataProvider { return null; } + @Nullable + public T getActiveItem(Class cls) { + PaletteItem item = getActiveItem(); + if (item != null && item.getClass().isInstance(item)) { + //noinspection unchecked + return (T)item; + } + return null; + } + @Nullable public Object getData(String dataId) { if (PlatformDataKeys.HELP_ID.is(dataId)) { @@ -269,6 +283,29 @@ public class PaletteWindow extends JPanel implements DataProvider { } } + void notifyKeyEvent(final KeyEvent e) { + if (myDesigner != null) { + if (e.getID() == KeyEvent.KEY_PRESSED) { + myDesigner.paletteKeyPressed(e); + } + else if (e.getID() == KeyEvent.KEY_RELEASED) { + myDesigner.paletteKeyReleased(e); + } + } + } + + void notifyDropActionChanged(int gestureModifiers) { + if (myDesigner != null) { + myDesigner.paletteDropActionChanged(gestureModifiers); + } + } + + void notifySelectionChanged(final ListSelectionEvent event) { + if (myDesigner != null) { + myDesigner.paletteValueChanged(event); + } + } + private class MyListSelectionListener implements ListSelectionListener { public void valueChanged(ListSelectionEvent e) { PaletteComponentList sourceList = (PaletteComponentList)e.getSource(); @@ -283,13 +320,13 @@ public class PaletteWindow extends JPanel implements DataProvider { break; } } - myPaletteManager.notifySelectionChanged(e); + notifySelectionChanged(e); } } private class MyPropertyChangeListener implements PropertyChangeListener { public void propertyChange(PropertyChangeEvent evt) { - refreshPalette(); + refreshPalette(myDesigner.getFile()); } } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/AbstractToolWindowManager.java b/plugins/ui-designer/src/com/intellij/uiDesigner/AbstractToolWindowManager.java new file mode 100644 index 000000000000..1a221506c1c2 --- /dev/null +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/AbstractToolWindowManager.java @@ -0,0 +1,67 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.uiDesigner; + +import com.intellij.designer.DesignerEditorPanelFacade; +import com.intellij.designer.LightToolWindowManager; +import com.intellij.designer.ToggleEditorModeAction; +import com.intellij.ide.palette.impl.PaletteToolWindowManager; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.fileEditor.FileEditor; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.wm.ToolWindowAnchor; +import com.intellij.uiDesigner.editor.UIFormEditor; +import com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager; +import org.jetbrains.annotations.Nullable; + +/** + * @author Alexander Lobas + */ +public abstract class AbstractToolWindowManager extends LightToolWindowManager { + public AbstractToolWindowManager(Project project, FileEditorManager fileEditorManager) { + super(project, fileEditorManager); + } + + @Override + public void projectOpened() { + if (!ApplicationManager.getApplication().isHeadlessEnvironment()) { + super.projectOpened(); + } + } + + @Nullable + @Override + protected DesignerEditorPanelFacade getDesigner(FileEditor editor) { + if (editor instanceof UIFormEditor) { + UIFormEditor formEditor = (UIFormEditor)editor; + return formEditor.getEditor(); + } + return null; + } + + @Override + protected ToggleEditorModeAction createToggleAction(ToolWindowAnchor anchor) { + return new ToggleEditorModeAction(this, myProject, anchor) { + @Override + protected LightToolWindowManager getOppositeManager() { + AbstractToolWindowManager designerManager = DesignerToolWindowManager.getInstance(myProject); + AbstractToolWindowManager paletteManager = PaletteToolWindowManager.getInstance(myProject); + return myManager == designerManager ? paletteManager : designerManager; + } + }; + } +} \ No newline at end of file diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/FormEditingUtil.java b/plugins/ui-designer/src/com/intellij/uiDesigner/FormEditingUtil.java index 6f9866018f4c..f2443b264b78 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/FormEditingUtil.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/FormEditingUtil.java @@ -41,7 +41,7 @@ import com.intellij.uiDesigner.editor.UIFormEditor; import com.intellij.uiDesigner.lw.*; import com.intellij.uiDesigner.palette.ComponentItem; import com.intellij.uiDesigner.palette.Palette; -import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager; +import com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager; import com.intellij.uiDesigner.propertyInspector.properties.BindingProperty; import com.intellij.uiDesigner.propertyInspector.properties.IntroComponentProperty; import com.intellij.uiDesigner.radComponents.RadAbstractGridLayoutManager; @@ -602,7 +602,7 @@ public final class FormEditingUtil { if (project == null) { return null; } - final UIDesignerToolWindowManager toolWindowManager = UIDesignerToolWindowManager.getInstance(project); + final DesignerToolWindowManager toolWindowManager = DesignerToolWindowManager.getInstance(project); if (toolWindowManager == null) { return null; } @@ -702,7 +702,7 @@ public final class FormEditingUtil { final RadContainer root = (RadContainer)getRoot(component); if (root == null) return; - ComponentTreeBuilder builder = UIDesignerToolWindowManager.getInstance(component.getProject()).getComponentTreeBuilder(); + ComponentTreeBuilder builder = DesignerToolWindowManager.getInstance(editor).getComponentTreeBuilder(); // this can return null if the click to select the control also requested to grab the focus - // the component tree will be instantiated after the event has been processed completely if (builder != null) { @@ -724,7 +724,7 @@ public final class FormEditingUtil { public static void selectComponents(final GuiEditor editor, List components) { if (components.size() > 0) { RadComponent component = components.get(0); - ComponentTreeBuilder builder = UIDesignerToolWindowManager.getInstance(component.getProject()).getComponentTreeBuilder(); + ComponentTreeBuilder builder = DesignerToolWindowManager.getInstance(editor).getComponentTreeBuilder(); if (builder == null) { // race condition when handling event? return; @@ -780,7 +780,7 @@ public final class FormEditingUtil { } public static Object getNextSaveUndoGroupId(final Project project) { - final GuiEditor guiEditor = UIDesignerToolWindowManager.getInstance(project).getActiveFormEditor(); + final GuiEditor guiEditor = DesignerToolWindowManager.getInstance(project).getActiveFormEditor(); return guiEditor == null ? null : guiEditor.getNextSaveGroupId(); } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/FormHighlightingPass.java b/plugins/ui-designer/src/com/intellij/uiDesigner/FormHighlightingPass.java index dae49482b998..e78c1d957f74 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/FormHighlightingPass.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/FormHighlightingPass.java @@ -19,7 +19,7 @@ package com.intellij.uiDesigner; import com.intellij.codeHighlighting.HighlightingPass; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.uiDesigner.designSurface.GuiEditor; -import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager; +import com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager; import org.jetbrains.annotations.NotNull; /** @@ -37,7 +37,7 @@ public class FormHighlightingPass implements HighlightingPass { } public void applyInformationToEditor() { - UIDesignerToolWindowManager.getInstance(myEditor.getProject()).refreshErrors(); + DesignerToolWindowManager.getInstance(myEditor).refreshErrors(); myEditor.refreshIntentionHint(); } -} +} \ No newline at end of file diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/ExpandSelectionAction.java b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/ExpandSelectionAction.java index c04c39ac4f4b..d1f2e6dd3688 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/ExpandSelectionAction.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/ExpandSelectionAction.java @@ -18,13 +18,14 @@ package com.intellij.uiDesigner.actions; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.Presentation; -import com.intellij.uiDesigner.*; -import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager; -import com.intellij.uiDesigner.radComponents.RadComponent; -import com.intellij.uiDesigner.radComponents.RadContainer; -import com.intellij.uiDesigner.designSurface.GuiEditor; +import com.intellij.uiDesigner.FormEditingUtil; +import com.intellij.uiDesigner.SelectionState; import com.intellij.uiDesigner.componentTree.ComponentPtr; import com.intellij.uiDesigner.componentTree.ComponentTreeBuilder; +import com.intellij.uiDesigner.designSurface.GuiEditor; +import com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager; +import com.intellij.uiDesigner.radComponents.RadComponent; +import com.intellij.uiDesigner.radComponents.RadContainer; import java.util.Stack; @@ -43,7 +44,7 @@ public final class ExpandSelectionAction extends AnAction{ final SelectionState selectionState = editor.getSelectionState(); selectionState.setInsideChange(true); - ComponentTreeBuilder builder = UIDesignerToolWindowManager.getInstance(editor.getProject()).getComponentTreeBuilder(); + ComponentTreeBuilder builder = DesignerToolWindowManager.getInstance(editor).getComponentTreeBuilder(); if (builder != null) { builder.beginUpdateSelection(); } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/ResetValueAction.java b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/ResetValueAction.java index 108451fff59c..d9085a3d08c5 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/ResetValueAction.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/ResetValueAction.java @@ -18,10 +18,7 @@ package com.intellij.uiDesigner.actions; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.uiDesigner.designSurface.GuiEditor; -import com.intellij.uiDesigner.propertyInspector.Property; -import com.intellij.uiDesigner.propertyInspector.PropertyInspector; -import com.intellij.uiDesigner.propertyInspector.PropertyInspectorTable; -import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager; +import com.intellij.uiDesigner.propertyInspector.*; import com.intellij.uiDesigner.radComponents.RadComponent; import java.util.ArrayList; @@ -44,7 +41,7 @@ public class ResetValueAction extends AbstractGuiEditorAction { public static void doResetValue(final List selection, final Property property, final GuiEditor editor) { try { if (!editor.ensureEditable()) return; - final PropertyInspector propertyInspector = UIDesignerToolWindowManager.getInstance(editor.getProject()).getPropertyInspector(); + final PropertyInspector propertyInspector = DesignerToolWindowManager.getInstance(editor).getPropertyInspector(); if (propertyInspector.isEditing()) { propertyInspector.stopEditing(); } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/SelectAllComponentsAction.java b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/SelectAllComponentsAction.java index cdfe0686c438..2569b4fb8477 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/SelectAllComponentsAction.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/SelectAllComponentsAction.java @@ -15,13 +15,13 @@ */ package com.intellij.uiDesigner.actions; -import com.intellij.uiDesigner.designSurface.GuiEditor; -import com.intellij.uiDesigner.radComponents.RadComponent; -import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager; -import com.intellij.uiDesigner.componentTree.ComponentTreeBuilder; -import com.intellij.uiDesigner.FormEditingUtil; -import com.intellij.uiDesigner.lw.IComponent; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.uiDesigner.FormEditingUtil; +import com.intellij.uiDesigner.componentTree.ComponentTreeBuilder; +import com.intellij.uiDesigner.designSurface.GuiEditor; +import com.intellij.uiDesigner.lw.IComponent; +import com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager; +import com.intellij.uiDesigner.radComponents.RadComponent; import java.util.List; @@ -30,7 +30,7 @@ import java.util.List; */ public class SelectAllComponentsAction extends AbstractGuiEditorAction { protected void actionPerformed(final GuiEditor editor, final List selection, final AnActionEvent e) { - final ComponentTreeBuilder builder = UIDesignerToolWindowManager.getInstance(editor.getProject()).getComponentTreeBuilder(); + final ComponentTreeBuilder builder = DesignerToolWindowManager.getInstance(editor).getComponentTreeBuilder(); builder.beginUpdateSelection(); try { FormEditingUtil.iterate(editor.getRootContainer(), new FormEditingUtil.ComponentVisitor() { diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/ShrinkSelectionAction.java b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/ShrinkSelectionAction.java index ccbbe252164b..20d79845c45f 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/ShrinkSelectionAction.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/ShrinkSelectionAction.java @@ -18,12 +18,12 @@ package com.intellij.uiDesigner.actions; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.Presentation; -import com.intellij.uiDesigner.SelectionState; import com.intellij.uiDesigner.FormEditingUtil; -import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager; +import com.intellij.uiDesigner.SelectionState; import com.intellij.uiDesigner.componentTree.ComponentPtr; import com.intellij.uiDesigner.componentTree.ComponentTreeBuilder; import com.intellij.uiDesigner.designSurface.GuiEditor; +import com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager; import java.util.Stack; @@ -37,7 +37,7 @@ public final class ShrinkSelectionAction extends AnAction{ assert editor != null; final SelectionState selectionState = editor.getSelectionState(); selectionState.setInsideChange(true); - ComponentTreeBuilder builder = UIDesignerToolWindowManager.getInstance(editor.getProject()).getComponentTreeBuilder(); + ComponentTreeBuilder builder = DesignerToolWindowManager.getInstance(editor).getComponentTreeBuilder(); builder.beginUpdateSelection(); try{ diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/componentTree/ComponentTreeBuilder.java b/plugins/ui-designer/src/com/intellij/uiDesigner/componentTree/ComponentTreeBuilder.java index 25791e2815da..aa5161ea0b96 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/componentTree/ComponentTreeBuilder.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/componentTree/ComponentTreeBuilder.java @@ -25,8 +25,8 @@ import com.intellij.uiDesigner.FormEditingUtil; import com.intellij.uiDesigner.HierarchyChangeListener; import com.intellij.uiDesigner.SelectionWatcher; import com.intellij.uiDesigner.designSurface.GuiEditor; +import com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager; import com.intellij.uiDesigner.propertyInspector.PropertyInspector; -import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager; import com.intellij.uiDesigner.radComponents.RadComponent; import com.intellij.uiDesigner.radComponents.RadContainer; import org.jetbrains.annotations.NotNull; @@ -221,7 +221,7 @@ public final class ComponentTreeBuilder extends AbstractTreeBuilder { } private void updateSelection() { - final PropertyInspector propertyInspector = UIDesignerToolWindowManager.getInstance(myEditor.getProject()).getPropertyInspector(); + final PropertyInspector propertyInspector = DesignerToolWindowManager.getInstance(myEditor).getPropertyInspector(); if (propertyInspector.isEditing()) { propertyInspector.stopEditing(); } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/DesignDropTargetListener.java b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/DesignDropTargetListener.java index d96eac097f48..f3ddc85e9280 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/DesignDropTargetListener.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/DesignDropTargetListener.java @@ -15,26 +15,26 @@ */ package com.intellij.uiDesigner.designSurface; -import com.intellij.ide.palette.impl.PaletteManager; +import com.intellij.ide.palette.impl.PaletteToolWindowManager; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.uiDesigner.CutCopyPasteSupport; import com.intellij.uiDesigner.FormEditingUtil; import com.intellij.uiDesigner.SimpleTransferable; import com.intellij.uiDesigner.UIDesignerBundle; import com.intellij.uiDesigner.componentTree.ComponentTree; -import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager; import com.intellij.uiDesigner.core.GridConstraints; import com.intellij.uiDesigner.palette.ComponentItem; +import com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager; import com.intellij.uiDesigner.radComponents.RadComponent; import com.intellij.uiDesigner.radComponents.RadContainer; import javax.swing.*; import java.awt.*; import java.awt.dnd.*; -import java.util.List; import java.util.ArrayList; +import java.util.List; /** * @author yole @@ -49,12 +49,10 @@ class DesignDropTargetListener implements DropTargetListener { private final GuiEditor myEditor; private final GridInsertProcessor myGridInsertProcessor; private boolean myUseDragDelta = false; - private final ComponentTree myComponentTree; public DesignDropTargetListener(final GuiEditor editor) { myEditor = editor; myGridInsertProcessor = new GridInsertProcessor(editor); - myComponentTree = UIDesignerToolWindowManager.getInstance(editor.getProject()).getComponentTree(); } public void dragEnter(DropTargetDragEvent dtde) { @@ -150,16 +148,18 @@ class DesignDropTargetListener implements DropTargetListener { myEditor.getDragLayer().repaint(); ComponentDropLocation location = myGridInsertProcessor.processDragEvent(dtde.getLocation(), myComponentDragObject); + ComponentTree componentTree = DesignerToolWindowManager.getInstance(myEditor).getComponentTree(); + if (!location.canDrop(myComponentDragObject) || (myDraggedComponentList != null && FormEditingUtil.isDropOnChild(myDraggedComponentList, location))) { - if (myComponentTree != null) { - myComponentTree.setDropTargetComponent(null); + if (componentTree != null) { + componentTree.setDropTargetComponent(null); } dtde.rejectDrag(); } else { - if (myComponentTree != null) { - myComponentTree.setDropTargetComponent(location.getContainer()); + if (componentTree != null) { + componentTree.setDropTargetComponent(location.getContainer()); } dtde.acceptDrag(dtde.getDropAction()); } @@ -178,8 +178,9 @@ class DesignDropTargetListener implements DropTargetListener { public void dragExit(DropTargetEvent dte) { try { - if (myComponentTree != null) { - myComponentTree.setDropTargetComponent(null); + ComponentTree componentTree = DesignerToolWindowManager.getInstance(myEditor).getComponentTree(); + if (componentTree != null) { + componentTree.setDropTargetComponent(null); } myUseDragDelta = false; if (myDraggedComponentList != null) { @@ -198,8 +199,9 @@ class DesignDropTargetListener implements DropTargetListener { public void drop(final DropTargetDropEvent dtde) { try { - if (myComponentTree != null) { - myComponentTree.setDropTargetComponent(null); + ComponentTree componentTree = DesignerToolWindowManager.getInstance(myEditor).getComponentTree(); + if (componentTree != null) { + componentTree.setDropTargetComponent(null); } @@ -221,7 +223,7 @@ class DesignDropTargetListener implements DropTargetListener { new InsertComponentProcessor(myEditor).processComponentInsert(dtde.getLocation(), componentItem); ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { - PaletteManager.getInstance(myEditor.getProject()).clearActiveItem(); + PaletteToolWindowManager.getInstance(myEditor).clearActiveItem(); myEditor.getActiveDecorationLayer().removeFeedback(); myEditor.getLayeredPane().setCursor(null); myEditor.getGlassLayer().requestFocus(); diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GlassLayer.java b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GlassLayer.java index 015a9dc4653e..8122989132d8 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GlassLayer.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GlassLayer.java @@ -21,7 +21,7 @@ import com.intellij.ui.popup.PopupOwner; import com.intellij.uiDesigner.FormEditingUtil; import com.intellij.uiDesigner.actions.*; import com.intellij.uiDesigner.componentTree.ComponentTree; -import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager; +import com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager; import com.intellij.uiDesigner.radComponents.RadComponent; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -136,7 +136,7 @@ public final class GlassLayer extends JComponent implements DataProvider, PopupO */ public Object getData(final String dataId) { if(CommonDataKeys.NAVIGATABLE.is(dataId)) { - final ComponentTree componentTree = UIDesignerToolWindowManager.getInstance(myEditor.getProject()).getComponentTree(); + final ComponentTree componentTree = DesignerToolWindowManager.getInstance(myEditor).getComponentTree(); if (componentTree != null) { return componentTree.getData(dataId); } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GuiEditor.java b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GuiEditor.java index 22d4d461f2ac..7459a05a33c3 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GuiEditor.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GuiEditor.java @@ -17,10 +17,10 @@ package com.intellij.uiDesigner.designSurface; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; import com.intellij.designer.DesignerEditorPanelFacade; +import com.intellij.designer.LightFillLayout; import com.intellij.ide.DeleteProvider; import com.intellij.ide.highlighter.XmlFileHighlighter; -import com.intellij.ide.palette.PaletteDragEventListener; -import com.intellij.ide.palette.impl.PaletteManager; +import com.intellij.ide.palette.impl.PaletteToolWindowManager; import com.intellij.lang.properties.psi.PropertiesFile; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; @@ -43,7 +43,9 @@ import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogBuilder; import com.intellij.openapi.ui.ThreeComponentsSplitter; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vfs.ReadonlyStatusHandler; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; @@ -57,13 +59,15 @@ import com.intellij.uiDesigner.componentTree.ComponentSelectionListener; import com.intellij.uiDesigner.componentTree.ComponentTree; import com.intellij.uiDesigner.core.GridLayoutManager; import com.intellij.uiDesigner.core.Util; +import com.intellij.uiDesigner.editor.UIFormEditor; import com.intellij.uiDesigner.lw.CompiledClassPropertiesProvider; import com.intellij.uiDesigner.lw.IComponent; import com.intellij.uiDesigner.lw.IProperty; import com.intellij.uiDesigner.lw.LwRootContainer; import com.intellij.uiDesigner.palette.ComponentItem; +import com.intellij.uiDesigner.propertyInspector.DesignerToolWindow; +import com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager; import com.intellij.uiDesigner.propertyInspector.PropertyInspector; -import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager; import com.intellij.uiDesigner.propertyInspector.properties.IntroStringProperty; import com.intellij.uiDesigner.radComponents.RadComponent; import com.intellij.uiDesigner.radComponents.RadContainer; @@ -71,6 +75,7 @@ import com.intellij.uiDesigner.radComponents.RadRootContainer; import com.intellij.uiDesigner.radComponents.RadTabbedPane; import com.intellij.util.Alarm; import com.intellij.util.NotNullProducer; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -78,11 +83,13 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.EventListenerList; import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; import java.awt.*; import java.awt.dnd.DnDConstants; import java.awt.dnd.DropTarget; -import java.awt.event.*; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Locale; @@ -100,6 +107,7 @@ public final class GuiEditor extends JPanel implements DesignerEditorPanelFacade private static final Logger LOG = Logger.getInstance("#com.intellij.uiDesigner.GuiEditor"); private final Project myProject; + @NotNull private final UIFormEditor myEditor; private Module myModule; @NotNull private final VirtualFile myFile; @@ -184,7 +192,9 @@ public final class GuiEditor extends JPanel implements DesignerEditorPanelFacade */ private boolean myInsideChange; private final DocumentAdapter myDocumentListener; - private final CardLayout myCardLayout; + private final CardLayout myCardLayout = new CardLayout(); + private final ThreeComponentsSplitter myContentSplitter = new ThreeComponentsSplitter(); + private final JPanel myCardPanel = new JPanel(myCardLayout); @NonNls private final static String CARD_VALID = "valid"; @NonNls private final static String CARD_INVALID = "invalid"; @@ -207,9 +217,6 @@ public final class GuiEditor extends JPanel implements DesignerEditorPanelFacade private final QuickFixManagerImpl myQuickFixManager; private final GridCaptionPanel myHorzCaptionPanel; private final GridCaptionPanel myVertCaptionPanel; - private final MyPaletteKeyListener myPaletteKeyListener; - private final MyPaletteDragListener myPaletteDragListener; - private final MyPaletteSelectionListener myPaletteSelectionListener; private ComponentPtr mySelectionAnchor; private ComponentPtr mySelectionLead; /** @@ -226,7 +233,8 @@ public final class GuiEditor extends JPanel implements DesignerEditorPanelFacade * @throws java.lang.IllegalArgumentException if the file * is null or file is not valid PsiFile */ - public GuiEditor(Project project, @NotNull final Module module, @NotNull final VirtualFile file) { + public GuiEditor(@NotNull UIFormEditor editor, @NotNull Project project, @NotNull Module module, @NotNull VirtualFile file) { + myEditor = editor; LOG.assertTrue(file.isValid()); myProject = project; @@ -235,13 +243,25 @@ public final class GuiEditor extends JPanel implements DesignerEditorPanelFacade myCutCopyPasteSupport = new CutCopyPasteSupport(this); - myCardLayout = new CardLayout(); - setLayout(myCardLayout); + setLayout(new BorderLayout()); + + myContentSplitter.setDividerWidth(0); + myContentSplitter.setDividerMouseZoneSize(Registry.intValue("ide.splitter.mouseZone")); + add(myContentSplitter, BorderLayout.CENTER); myValidCard = new JPanel(new BorderLayout()); myInvalidCard = createInvalidCard(); - add(myValidCard, CARD_VALID); - add(myInvalidCard, CARD_INVALID); + + myCardPanel.add(myValidCard, CARD_VALID); + myCardPanel.add(myInvalidCard, CARD_INVALID); + + JPanel contentPanel = new JPanel(new LightFillLayout()); + JLabel toolbar = new JLabel(); + toolbar.setVisible(false); + contentPanel.add(toolbar); + contentPanel.add(myCardPanel); + + myContentSplitter.setInnerComponent(contentPanel); myListenerList = new EventListenerList(); @@ -350,23 +370,28 @@ public final class GuiEditor extends JPanel implements DesignerEditorPanelFacade myActiveDecorationLayer.installSelectionWatcher(); - final PaletteManager paletteManager = PaletteManager.getInstance(getProject()); - myPaletteKeyListener = new MyPaletteKeyListener(); - paletteManager.addKeyListener(myPaletteKeyListener); - myPaletteDragListener = new MyPaletteDragListener(); - paletteManager.addDragEventListener(myPaletteDragListener); - myPaletteSelectionListener = new MyPaletteSelectionListener(); - paletteManager.addSelectionListener(myPaletteSelectionListener); - ActionManager.getInstance().getAction("GuiDesigner.IncreaseIndent").registerCustomShortcutSet( new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0)), myGlassLayer); ActionManager.getInstance().getAction("GuiDesigner.DecreaseIndent").registerCustomShortcutSet( new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, KeyEvent.SHIFT_MASK)), myGlassLayer); + + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + DesignerToolWindowManager.getInstance(myProject).bind(GuiEditor.this); + PaletteToolWindowManager.getInstance(myProject).bind(GuiEditor.this); + } + }); } @Override public ThreeComponentsSplitter getContentSplitter() { - return null; // TODO: Auto-generated method stub + return myContentSplitter; + } + + @NotNull + public UIFormEditor getEditor() { + return myEditor; } @NotNull @@ -385,13 +410,14 @@ public final class GuiEditor extends JPanel implements DesignerEditorPanelFacade myWhere = new Exception(); } - final PaletteManager paletteManager = PaletteManager.getInstance(getProject()); - paletteManager.removeKeyListener(myPaletteKeyListener); - paletteManager.removeDragEventListener(myPaletteDragListener); - paletteManager.removeSelectionListener(myPaletteSelectionListener); myDocument.removeDocumentListener(myDocumentListener); PsiManager.getInstance(getProject()).removePsiTreeChangeListener(myPsiTreeChangeListener); + + DesignerToolWindowManager.getInstance(myProject).dispose(this); + PaletteToolWindowManager.getInstance(myProject).dispose(this); myPsiTreeChangeListener.dispose(); + + Disposer.dispose(myContentSplitter); } @NotNull @@ -459,8 +485,7 @@ public final class GuiEditor extends JPanel implements DesignerEditorPanelFacade public void refreshAndSave(final boolean forceSync) { // Update property inspector - final UIDesignerToolWindowManager manager = UIDesignerToolWindowManager.getInstance(getProject()); - final PropertyInspector propertyInspector = manager.getPropertyInspector(); + final PropertyInspector propertyInspector = DesignerToolWindowManager.getInstance(this).getPropertyInspector(); if (propertyInspector != null) { propertyInspector.synchWithTree(forceSync); } @@ -509,8 +534,7 @@ public final class GuiEditor extends JPanel implements DesignerEditorPanelFacade // Standard Swing cut/copy/paste actions should work if user is editing something inside property inspector Project project = getProject(); if (project.isDisposed()) return null; - final UIDesignerToolWindowManager manager = UIDesignerToolWindowManager.getInstance(project); - final PropertyInspector inspector = manager.getPropertyInspector(); + final PropertyInspector inspector = DesignerToolWindowManager.getInstance(this).getPropertyInspector(); if (inspector != null && inspector.isEditing()) { return null; } @@ -667,7 +691,7 @@ public final class GuiEditor extends JPanel implements DesignerEditorPanelFacade public void setStringDescriptorLocale(final Locale locale) { myRootContainer.setStringDescriptorLocale(locale); refreshProperties(); - UIDesignerToolWindowManager.getInstance(getProject()).updateComponentTree(); + DesignerToolWindowManager.getInstance(this).updateComponentTree(); DaemonCodeAnalyzer.getInstance(getProject()).restart(); } @@ -705,10 +729,10 @@ public final class GuiEditor extends JPanel implements DesignerEditorPanelFacade }); if (!anythingModified.isNull()) { refresh(); - final UIDesignerToolWindowManager twm = UIDesignerToolWindowManager.getInstance(getProject()); - ComponentTree tree = twm.getComponentTree(); + DesignerToolWindow designerToolWindow = DesignerToolWindowManager.getInstance(this); + ComponentTree tree = designerToolWindow.getComponentTree(); if (tree != null) tree.repaint(); - PropertyInspector inspector = twm.getPropertyInspector(); + PropertyInspector inspector = designerToolWindow.getPropertyInspector(); if (inspector != null) inspector.synchWithTree(true); } } @@ -871,7 +895,7 @@ public final class GuiEditor extends JPanel implements DesignerEditorPanelFacade restoreTabbedPaneSelectedTabs(tabbedPaneSelectedTabs); } myInvalid = false; - myCardLayout.show(this, CARD_VALID); + myCardLayout.show(myCardPanel, CARD_VALID); refresh(); } catch (Exception exc) { @@ -892,7 +916,7 @@ public final class GuiEditor extends JPanel implements DesignerEditorPanelFacade setRootContainer(new RadRootContainer(this, "0")); myFormInvalidLabel.setText(UIDesignerBundle.message("error.form.file.is.invalid.message", FormEditingUtil.getExceptionMessage(exc))); myInvalid = true; - myCardLayout.show(this, CARD_INVALID); + myCardLayout.show(myCardPanel, CARD_INVALID); repaint(); } @@ -995,10 +1019,6 @@ public final class GuiEditor extends JPanel implements DesignerEditorPanelFacade return undoManager.isUndoInProgress() || undoManager.isRedoInProgress(); } - private boolean isActiveEditor() { - return UIDesignerToolWindowManager.getInstance(getProject()).getActiveFormEditor() == this; - } - void hideIntentionHint() { myQuickFixManager.hideIntentionHint(); } @@ -1095,8 +1115,7 @@ public final class GuiEditor extends JPanel implements DesignerEditorPanelFacade } public void update(final AnActionEvent e) { - final UIDesignerToolWindowManager manager = UIDesignerToolWindowManager.getInstance(getProject()); - PropertyInspector inspector = manager.getPropertyInspector(); + PropertyInspector inspector = DesignerToolWindowManager.getInstance(GuiEditor.this).getPropertyInspector(); e.getPresentation().setEnabled(inspector != null && !inspector.isEditing()); } } @@ -1117,9 +1136,8 @@ public final class GuiEditor extends JPanel implements DesignerEditorPanelFacade } public boolean canDeleteElement(@NotNull final DataContext dataContext) { - final UIDesignerToolWindowManager manager = UIDesignerToolWindowManager.getInstance(getProject()); return - !manager.getPropertyInspector().isEditing() && + !DesignerToolWindowManager.getInstance(GuiEditor.this).getPropertyInspector().isEditing() && !myInplaceEditingLayer.isEditing() && FormEditingUtil.canDeleteSelection(GuiEditor.this); } @@ -1223,39 +1241,30 @@ public final class GuiEditor extends JPanel implements DesignerEditorPanelFacade } } - private class MyPaletteKeyListener extends KeyAdapter { - @Override - public void keyPressed(KeyEvent e) { - PaletteManager paletteManager = PaletteManager.getInstance(getProject()); - if (e.getKeyCode() == KeyEvent.VK_SHIFT && paletteManager.getActiveItem(ComponentItem.class) != null && isActiveEditor()) { - setDesignTimeInsets(12); - } - } - - @Override - public void keyReleased(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_SHIFT) { - setDesignTimeInsets(2); - } + public void paletteKeyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_SHIFT && PaletteToolWindowManager.getInstance(this).getActiveItem(ComponentItem.class) != null) { + setDesignTimeInsets(12); } } - private class MyPaletteDragListener implements PaletteDragEventListener { - public void dropActionChanged(int gestureModifiers) { - if ((gestureModifiers & InputEvent.SHIFT_MASK) != 0 && isActiveEditor()) { - setDesignTimeInsets(12); - } - else { - setDesignTimeInsets(2); - } + public void paletteKeyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_SHIFT) { + setDesignTimeInsets(2); } } - private class MyPaletteSelectionListener implements ListSelectionListener { - public void valueChanged(ListSelectionEvent e) { - if (PaletteManager.getInstance(getProject()).getActiveItem() == null) { - myProcessor.cancelPaletteInsert(); - } + public void paletteDropActionChanged(int gestureModifiers) { + if ((gestureModifiers & InputEvent.SHIFT_MASK) != 0) { + setDesignTimeInsets(12); + } + else { + setDesignTimeInsets(2); } } -} + + public void paletteValueChanged(ListSelectionEvent e) { + if (PaletteToolWindowManager.getInstance(this).getActiveItem() == null) { + myProcessor.cancelPaletteInsert(); + } + } +} \ No newline at end of file diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/InsertComponentProcessor.java b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/InsertComponentProcessor.java index b088447afa0b..4eb3f32a0ed3 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/InsertComponentProcessor.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/InsertComponentProcessor.java @@ -17,7 +17,7 @@ package com.intellij.uiDesigner.designSurface; import com.intellij.CommonBundle; import com.intellij.codeInsight.FileModificationService; -import com.intellij.ide.palette.impl.PaletteManager; +import com.intellij.ide.palette.impl.PaletteToolWindowManager; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; @@ -63,7 +63,6 @@ import java.util.Map; public final class InsertComponentProcessor extends EventProcessor { private static final Logger LOG = Logger.getInstance("#com.intellij.uiDesigner.designSurface.InsertComponentProcessor"); - private final PaletteManager myPaletteManager; private final GuiEditor myEditor; private boolean mySticky; private RadComponent myInsertedComponent; @@ -87,7 +86,6 @@ public final class InsertComponentProcessor extends EventProcessor { public InsertComponentProcessor(@NotNull final GuiEditor editor) { myEditor = editor; myGridInsertProcessor = new GridInsertProcessor(editor); - myPaletteManager = PaletteManager.getInstance(editor.getProject()); } public void setSticky(final boolean sticky) { @@ -261,7 +259,7 @@ public final class InsertComponentProcessor extends EventProcessor { private ComponentItem getComponentToInsert() { return (myComponentToInsert != null) ? myComponentToInsert - : myPaletteManager.getActiveItem(ComponentItem.class); + : PaletteToolWindowManager.getInstance(myEditor).getActiveItem(ComponentItem.class); } public void processComponentInsert(@NotNull final Point point, final ComponentItem item) { @@ -295,7 +293,7 @@ public final class InsertComponentProcessor extends EventProcessor { setCursor(Cursor.getDefaultCursor()); if (myInsertedComponent == null) { if (!mySticky) { - PaletteManager.getInstance(myEditor.getProject()).clearActiveItem(); + PaletteToolWindowManager.getInstance(myEditor).clearActiveItem(); } return; } @@ -328,7 +326,7 @@ public final class InsertComponentProcessor extends EventProcessor { checkBindTopLevelPanel(); if (!mySticky) { - PaletteManager.getInstance(myEditor.getProject()).clearActiveItem(); + PaletteToolWindowManager.getInstance(myEditor).clearActiveItem(); } myEditor.refreshAndSave(false); @@ -578,7 +576,7 @@ public final class InsertComponentProcessor extends EventProcessor { } public Cursor processMouseMoveEvent(final MouseEvent e) { - final ComponentItem componentItem = myPaletteManager.getActiveItem(ComponentItem.class); + final ComponentItem componentItem = PaletteToolWindowManager.getInstance(myEditor).getActiveItem(ComponentItem.class); if (componentItem != null) { return myGridInsertProcessor.processMouseMoveEvent(e.getPoint(), false, new ComponentItemDragObject(componentItem)); } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/MainProcessor.java b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/MainProcessor.java index 3816a3aa66f8..951ae951f56e 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/MainProcessor.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/MainProcessor.java @@ -15,7 +15,7 @@ */ package com.intellij.uiDesigner.designSurface; -import com.intellij.ide.palette.impl.PaletteManager; +import com.intellij.ide.palette.impl.PaletteToolWindowManager; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.uiDesigner.FormEditingUtil; @@ -58,7 +58,7 @@ public final class MainProcessor extends EventProcessor{ if (e.getKeyCode() == KeyEvent.VK_SHIFT) { if (e.getID() == KeyEvent.KEY_PRESSED) { if ((myCurrentProcessor != null && myCurrentProcessor.isDragActive()) || - (PaletteManager.getInstance(myEditor.getProject()).getActiveItem(ComponentItem.class) != null && + (PaletteToolWindowManager.getInstance(myEditor).getActiveItem(ComponentItem.class) != null && myCurrentProcessor != myInsertComponentProcessor)) { myEditor.setDesignTimeInsets(12); } @@ -151,7 +151,7 @@ public final class MainProcessor extends EventProcessor{ Cursor cursor = Cursor.getDefaultCursor(); if(id==MouseEvent.MOUSE_MOVED){ - if (PaletteManager.getInstance(myEditor.getProject()).getActiveItem(ComponentItem.class) != null) { + if (PaletteToolWindowManager.getInstance(myEditor).getActiveItem(ComponentItem.class) != null) { if (myInsertFeedbackEnabled) { cursor = myInsertComponentProcessor.processMouseMoveEvent(e); } @@ -292,7 +292,7 @@ public final class MainProcessor extends EventProcessor{ return; } - final ComponentItem selectedItem = PaletteManager.getInstance(myEditor.getProject()).getActiveItem(ComponentItem.class); + final ComponentItem selectedItem = PaletteToolWindowManager.getInstance(myEditor).getActiveItem(ComponentItem.class); if (selectedItem != null) { myInsertComponentProcessor.setSticky(UIUtil.isControlKeyDown(e)); myCurrentProcessor = myInsertComponentProcessor; @@ -341,7 +341,7 @@ public final class MainProcessor extends EventProcessor{ return true; } } - else if (PaletteManager.getInstance(myEditor.getProject()).getActiveItem(ComponentItem.class) != null) { + else if (PaletteToolWindowManager.getInstance(myEditor).getActiveItem(ComponentItem.class) != null) { cancelPaletteInsert(); return true; } @@ -349,7 +349,7 @@ public final class MainProcessor extends EventProcessor{ } void cancelPaletteInsert() { - PaletteManager.getInstance(myEditor.getProject()).clearActiveItem(); + PaletteToolWindowManager.getInstance(myEditor).clearActiveItem(); myEditor.getLayeredPane().setCursor(Cursor.getDefaultCursor()); myEditor.getActiveDecorationLayer().removeFeedback(); } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/PassiveDecorationLayer.java b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/PassiveDecorationLayer.java index 070612857a53..1153adadfdf0 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/PassiveDecorationLayer.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/PassiveDecorationLayer.java @@ -17,7 +17,7 @@ package com.intellij.uiDesigner.designSurface; import com.intellij.uiDesigner.FormEditingUtil; import com.intellij.uiDesigner.componentTree.ComponentTree; -import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager; +import com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager; import com.intellij.uiDesigner.radComponents.RadButtonGroup; import com.intellij.uiDesigner.radComponents.RadComponent; import com.intellij.uiDesigner.radComponents.RadRootContainer; @@ -56,7 +56,7 @@ class PassiveDecorationLayer extends JComponent{ final Set paintedGroups = new HashSet(); final RadRootContainer rootContainer = myEditor.getRootContainer(); - final ComponentTree componentTree = UIDesignerToolWindowManager.getInstance(component.getProject()).getComponentTree(); + final ComponentTree componentTree = DesignerToolWindowManager.getInstance(myEditor).getComponentTree(); final Collection selectedGroups = componentTree != null ? componentTree.getSelectedElements(RadButtonGroup.class) : Collections.emptyList(); diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/QuickFixManagerImpl.java b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/QuickFixManagerImpl.java index 15e1c34daf78..241ae963a3cd 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/QuickFixManagerImpl.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/QuickFixManagerImpl.java @@ -18,14 +18,12 @@ package com.intellij.uiDesigner.designSurface; import com.intellij.uiDesigner.ErrorAnalyzer; import com.intellij.uiDesigner.ErrorInfo; import com.intellij.uiDesigner.FormEditingUtil; -import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager; +import com.intellij.uiDesigner.componentTree.ComponentSelectionListener; import com.intellij.uiDesigner.quickFixes.QuickFixManager; import com.intellij.uiDesigner.radComponents.RadComponent; import org.jetbrains.annotations.NotNull; import javax.swing.*; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; import java.awt.*; import java.util.ArrayList; @@ -35,9 +33,9 @@ import java.util.ArrayList; public class QuickFixManagerImpl extends QuickFixManager { public QuickFixManagerImpl(final GuiEditor editor, final GlassLayer component, final JViewport viewPort) { super(editor, component, viewPort); - final UIDesignerToolWindowManager toolWindowManager = UIDesignerToolWindowManager.getInstance(editor.getProject()); - toolWindowManager.addComponentSelectionListener(new TreeSelectionListener() { - public void valueChanged(TreeSelectionEvent e) { + editor.addComponentSelectionListener(new ComponentSelectionListener() { + @Override + public void selectedComponentChanged(GuiEditor source) { hideIntentionHint(); updateIntentionHintVisibility(); } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/editor/UIFormEditor.java b/plugins/ui-designer/src/com/intellij/uiDesigner/editor/UIFormEditor.java index 796b880b6244..c457500c703c 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/editor/UIFormEditor.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/editor/UIFormEditor.java @@ -48,14 +48,14 @@ public final class UIFormEditor extends UserDataHolderBase implements /*Navigata private final GuiEditor myEditor; private UIFormEditor.MyBackgroundEditorHighlighter myBackgroundEditorHighlighter; - public UIFormEditor(final Project project, final VirtualFile file){ + public UIFormEditor(@NotNull final Project project, @NotNull final VirtualFile file){ final VirtualFile vf = file instanceof LightVirtualFile ? ((LightVirtualFile)file).getOriginalFile() : file; final Module module = ModuleUtil.findModuleForFile(vf, project); if (module == null) { throw new IllegalArgumentException("No module for file " + file + " in project " + project); } myFile = file; - myEditor = new GuiEditor(project, module, file); + myEditor = new GuiEditor(this, project, module, file); } @NotNull diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/DesignerToolWindow.java b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/DesignerToolWindow.java new file mode 100644 index 000000000000..e8164e19e21e --- /dev/null +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/DesignerToolWindow.java @@ -0,0 +1,139 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.uiDesigner.propertyInspector; + +import com.intellij.designer.LightToolWindowContent; +import com.intellij.openapi.actionSystem.DataProvider; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.Splitter; +import com.intellij.openapi.util.Disposer; +import com.intellij.ui.IdeBorderFactory; +import com.intellij.ui.ScrollPaneFactory; +import com.intellij.ui.SideBorder; +import com.intellij.uiDesigner.componentTree.ComponentTree; +import com.intellij.uiDesigner.componentTree.ComponentTreeBuilder; +import com.intellij.uiDesigner.designSurface.GuiEditor; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import java.awt.*; + +/** + * @author Alexander Lobas + */ +public class DesignerToolWindow implements LightToolWindowContent { + private final MyToolWindowPanel myToolWindowPanel = new MyToolWindowPanel(); + private ComponentTree myComponentTree; + private ComponentTreeBuilder myComponentTreeBuilder; + private PropertyInspector myPropertyInspector; + + public DesignerToolWindow(Project project) { + myComponentTree = new ComponentTree(project); + + JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myComponentTree); + scrollPane.setBorder(IdeBorderFactory.createBorder(SideBorder.BOTTOM)); + scrollPane.setPreferredSize(new Dimension(250, -1)); + myComponentTree.initQuickFixManager(scrollPane.getViewport()); + + myPropertyInspector = new PropertyInspector(project, myComponentTree); + + myToolWindowPanel.setFirstComponent(scrollPane); + myToolWindowPanel.setSecondComponent(myPropertyInspector); + } + + @Override + public void dispose() { + clearTreeBuilder(); + myToolWindowPanel.dispose(); + myComponentTree = null; + myPropertyInspector = null; + } + + private void clearTreeBuilder() { + if (myComponentTreeBuilder != null) { + Disposer.dispose(myComponentTreeBuilder); + myComponentTreeBuilder = null; + } + } + + public void update(GuiEditor designer) { + clearTreeBuilder(); + + myComponentTree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode())); + myComponentTree.setEditor(designer); + myPropertyInspector.setEditor(designer); + + if (designer == null) { + myComponentTree.setFormEditor(null); + } + else { + myComponentTree.setFormEditor(designer.getEditor()); + myComponentTreeBuilder = new ComponentTreeBuilder(myComponentTree, designer); + } + } + + public JComponent getToolWindowPanel() { + return myToolWindowPanel; + } + + public ComponentTree getComponentTree() { + return myComponentTree; + } + + public ComponentTreeBuilder getComponentTreeBuilder() { + return myComponentTreeBuilder; + } + + public void updateComponentTree() { + if (myComponentTreeBuilder != null) { + myComponentTreeBuilder.queueUpdate(); + } + } + + public PropertyInspector getPropertyInspector() { + return myPropertyInspector; + } + + public void refreshErrors() { + if (myComponentTree != null) { + myComponentTree.refreshIntentionHint(); + myComponentTree.repaint(myComponentTree.getVisibleRect()); + } + + // PropertyInspector + if (myPropertyInspector != null) { + myPropertyInspector.refreshIntentionHint(); + myPropertyInspector.repaint(myPropertyInspector.getVisibleRect()); + } + } + + private class MyToolWindowPanel extends Splitter implements DataProvider { + MyToolWindowPanel() { + super(true, 0.33f); + } + + @Nullable + public Object getData(@NonNls String dataId) { + if (GuiEditor.DATA_KEY.is(dataId) && myComponentTree != null) { + return myComponentTree.getData(dataId); + } + return null; + } + } +} \ No newline at end of file diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/DesignerToolWindowManager.java b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/DesignerToolWindowManager.java new file mode 100644 index 000000000000..36e6935dae99 --- /dev/null +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/DesignerToolWindowManager.java @@ -0,0 +1,131 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.uiDesigner.propertyInspector; + +import com.intellij.designer.DesignerEditorPanelFacade; +import com.intellij.designer.LightToolWindow; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.wm.ToolWindowAnchor; +import com.intellij.openapi.wm.ToolWindowManager; +import com.intellij.openapi.wm.impl.content.ToolWindowContentUi; +import com.intellij.ui.content.Content; +import com.intellij.ui.content.ContentManager; +import com.intellij.uiDesigner.AbstractToolWindowManager; +import com.intellij.uiDesigner.UIDesignerBundle; +import com.intellij.uiDesigner.designSurface.GuiEditor; +import icons.UIDesignerIcons; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Alexander Lobas + */ +public class DesignerToolWindowManager extends AbstractToolWindowManager { + private final DesignerToolWindow myToolWindowPanel; + + public DesignerToolWindowManager(Project project, FileEditorManager fileEditorManager) { + super(project, fileEditorManager); + myToolWindowPanel = ApplicationManager.getApplication().isHeadlessEnvironment() ? null : new DesignerToolWindow(project); + } + + public static DesignerToolWindow getInstance(GuiEditor designer) { + DesignerToolWindowManager manager = getInstance(designer.getProject()); + if (manager.isEditorMode()) { + return (DesignerToolWindow)manager.getContent(designer); + } + return manager.myToolWindowPanel; + } + + public static DesignerToolWindowManager getInstance(Project project) { + return project.getComponent(DesignerToolWindowManager.class); + } + + @Nullable + public GuiEditor getActiveFormEditor() { + return (GuiEditor)getActiveDesigner(); + } + + @Override + protected void initToolWindow() { + myToolWindow = ToolWindowManager.getInstance(myProject).registerToolWindow(UIDesignerBundle.message("toolwindow.ui.designer.name"), + false, getAnchor(), myProject, true); + myToolWindow.setIcon(UIDesignerIcons.ToolWindowUIDesigner); + + if (!ApplicationManager.getApplication().isHeadlessEnvironment()) { + myToolWindow.getComponent().putClientProperty(ToolWindowContentUi.HIDE_ID_LABEL, "true"); + } + + initGearActions(); + + ContentManager contentManager = myToolWindow.getContentManager(); + Content content = + contentManager.getFactory() + .createContent(myToolWindowPanel.getToolWindowPanel(), UIDesignerBundle.message("toolwindow.ui.designer.title"), false); + content.setCloseable(false); + content.setPreferredFocusableComponent(myToolWindowPanel.getComponentTree()); + contentManager.addContent(content); + contentManager.setSelectedContent(content, true); + myToolWindow.setAvailable(false, null); + } + + @Override + protected void updateToolWindow(@Nullable DesignerEditorPanelFacade designer) { + myToolWindowPanel.update((GuiEditor)designer); + + if (designer == null) { + myToolWindow.setAvailable(false, null); + } + else { + myToolWindow.setAvailable(true, null); + myToolWindow.show(null); + } + } + + @Override + protected ToolWindowAnchor getAnchor() { + return ToolWindowAnchor.LEFT; + } + + @Override + protected LightToolWindow createContent(@NotNull DesignerEditorPanelFacade designer) { + DesignerToolWindow toolWindowContent = new DesignerToolWindow(myProject); + toolWindowContent.update((GuiEditor)designer); + + return createContent(designer, + toolWindowContent, + UIDesignerBundle.message("toolwindow.ui.designer.title"), + UIDesignerIcons.ToolWindowUIDesigner, + toolWindowContent.getToolWindowPanel(), + toolWindowContent.getComponentTree(), + 320, + null); + } + + @Override + public void disposeComponent() { + if (myToolWindowPanel != null) { + myToolWindowPanel.dispose(); + } + } + + @NotNull + @Override + public String getComponentName() { + return "UIDesignerToolWindowManager"; + } +} \ No newline at end of file diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/PropertyInspectorTable.java b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/PropertyInspectorTable.java index 059ba0407107..e4b7fccedbff 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/PropertyInspectorTable.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/PropertyInspectorTable.java @@ -281,7 +281,8 @@ public final class PropertyInspectorTable extends Table implements DataProvider{ return myEditor; } else if (PlatformDataKeys.FILE_EDITOR.is(dataId)) { - return UIDesignerToolWindowManager.getInstance(myProject).getActiveFormFileEditor(); + GuiEditor designer = DesignerToolWindowManager.getInstance(myProject).getActiveFormEditor(); + return designer == null ? null : designer.getEditor(); } else if (PlatformDataKeys.HELP_ID.is(dataId)) { return ourHelpID; diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/UIDesignerToolWindowManager.java b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/UIDesignerToolWindowManager.java deleted file mode 100644 index 5d6092c8032a..000000000000 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/UIDesignerToolWindowManager.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.intellij.uiDesigner.propertyInspector; - -import com.intellij.openapi.actionSystem.DataProvider; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.components.ProjectComponent; -import com.intellij.openapi.fileEditor.FileEditor; -import com.intellij.openapi.fileEditor.FileEditorManager; -import com.intellij.openapi.fileEditor.FileEditorManagerEvent; -import com.intellij.openapi.fileEditor.FileEditorManagerListener; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.Splitter; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.wm.ToolWindow; -import com.intellij.openapi.wm.ToolWindowAnchor; -import com.intellij.openapi.wm.ToolWindowManager; -import com.intellij.ui.IdeBorderFactory; -import com.intellij.ui.ScrollPaneFactory; -import com.intellij.ui.SideBorder; -import com.intellij.uiDesigner.UIDesignerBundle; -import com.intellij.uiDesigner.componentTree.ComponentTree; -import com.intellij.uiDesigner.componentTree.ComponentTreeBuilder; -import com.intellij.uiDesigner.designSurface.GuiEditor; -import com.intellij.uiDesigner.editor.UIFormEditor; -import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.ui.update.MergingUpdateQueue; -import com.intellij.util.ui.update.Update; -import icons.UIDesignerIcons; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; -import javax.swing.event.TreeSelectionListener; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeModel; -import java.awt.*; -import java.util.List; - -/** - * @author yole - */ -public class UIDesignerToolWindowManager implements ProjectComponent { - private final Project myProject; - private MyToolWindowPanel myToolWindowPanel; - private ComponentTree myComponentTree; - private ComponentTreeBuilder myComponentTreeBuilder; - private PropertyInspector myPropertyInspector; - private final FileEditorManager myFileEditorManager; - private ToolWindow myToolWindow; - private boolean myToolWindowDisposed = false; - private final List myPendingListeners = ContainerUtil.createLockFreeCopyOnWriteList(); - - public UIDesignerToolWindowManager(final Project project, final FileEditorManager fileEditorManager) { - myProject = project; - myFileEditorManager = fileEditorManager; - MyFileEditorManagerListener listener = new MyFileEditorManagerListener(); - myFileEditorManager.addFileEditorManagerListener(listener,project); - } - - public void projectOpened() { - } - - private void checkInitToolWindow() { - if (!myToolWindowDisposed && myToolWindow == null) { - initToolWindow(); - } - } - - private void initToolWindow() { - myToolWindowPanel = new MyToolWindowPanel(); - myComponentTree = new ComponentTree(myProject); - for (TreeSelectionListener listener : myPendingListeners) { - myComponentTree.addTreeSelectionListener(listener); - } - myPendingListeners.clear(); - final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myComponentTree); - scrollPane.setBorder(IdeBorderFactory.createBorder(SideBorder.BOTTOM)); - scrollPane.setPreferredSize(new Dimension(250, -1)); - myComponentTree.initQuickFixManager(scrollPane.getViewport()); - myPropertyInspector= new PropertyInspector(myProject, myComponentTree); - myToolWindowPanel.setFirstComponent(scrollPane); - myToolWindowPanel.setSecondComponent(myPropertyInspector); - myToolWindow = ToolWindowManager.getInstance(myProject).registerToolWindow(UIDesignerBundle.message("toolwindow.ui.designer"), - myToolWindowPanel, - ToolWindowAnchor.LEFT, myProject, true); - myToolWindow.setIcon(UIDesignerIcons.ToolWindowUIDesigner); - myToolWindow.setAvailable(false, null); - } - - public void projectClosed() { - if (myToolWindowPanel != null) { - if (myComponentTreeBuilder != null) { - Disposer.dispose(myComponentTreeBuilder); - } - myToolWindowPanel = null; - myToolWindow = null; - myToolWindowDisposed = true; - } - } - - @NotNull @NonNls - public String getComponentName() { - return "UIDesignerToolWindowManager"; - } - - public void initComponent() { - } - - public void disposeComponent() { - } - - private final MergingUpdateQueue myQueue = new MergingUpdateQueue("property.inspector", 200, true, null); - - private void processFileEditorChange(final UIFormEditor newEditor) { - myQueue.cancelAllUpdates(); - myQueue.queue(new Update("update") { - public void run() { - if (myToolWindowDisposed) return; - GuiEditor activeFormEditor = newEditor != null ? newEditor.getEditor() : null; - if (myToolWindow == null) { - if (activeFormEditor == null) return; - initToolWindow(); - } - if (myComponentTreeBuilder != null) { - Disposer.dispose(myComponentTreeBuilder); - myComponentTreeBuilder = null; - } - myComponentTree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode())); - myComponentTree.setEditor(activeFormEditor); - myComponentTree.setFormEditor(newEditor); - myPropertyInspector.setEditor(activeFormEditor); - if (activeFormEditor == null) { - myToolWindow.setAvailable(false, null); - } - else { - myComponentTreeBuilder = new ComponentTreeBuilder(myComponentTree, activeFormEditor); - myToolWindow.setAvailable(true, null); - myToolWindow.show(null); - } - } - }); - } - - @Nullable - public UIFormEditor getActiveFormFileEditor() { - FileEditor[] fileEditors = myFileEditorManager.getSelectedEditors(); - for (FileEditor fileEditor : fileEditors) { - if (fileEditor instanceof UIFormEditor) { - return (UIFormEditor)fileEditor; - } - } - return null; - } - - @Nullable - public GuiEditor getActiveFormEditor() { - UIFormEditor formEditor = getActiveFormFileEditor(); - return formEditor == null ? null : formEditor.getEditor(); - } - - public static UIDesignerToolWindowManager getInstance(Project project) { - return project.getComponent(UIDesignerToolWindowManager.class); - } - - public ComponentTree getComponentTree() { - checkInitToolWindow(); - return myComponentTree; - } - - public ComponentTreeBuilder getComponentTreeBuilder() { - return myComponentTreeBuilder; - } - - public PropertyInspector getPropertyInspector() { - return myPropertyInspector; - } - - public void refreshErrors() { - if (myComponentTree != null) { - myComponentTree.refreshIntentionHint(); - myComponentTree.repaint(myComponentTree.getVisibleRect()); - } - - // PropertyInspector - if (myPropertyInspector != null) { - myPropertyInspector.refreshIntentionHint(); - myPropertyInspector.repaint(myPropertyInspector.getVisibleRect()); - } - } - - public void updateComponentTree() { - final ComponentTreeBuilder builder = myComponentTreeBuilder; - if (builder != null) { - builder.queueUpdate(); - } - } - - public void addComponentSelectionListener(TreeSelectionListener treeSelectionListener) { - if (myComponentTree != null) { - myComponentTree.addTreeSelectionListener(treeSelectionListener); - } - else { - myPendingListeners.add(treeSelectionListener); - } - } - - private class MyFileEditorManagerListener implements FileEditorManagerListener { - public void fileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) { - processFileEditorChange(getActiveFormFileEditor()); - } - - public void fileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) { - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - processFileEditorChange(getActiveFormFileEditor()); - } - }); - } - - public void selectionChanged(@NotNull FileEditorManagerEvent event) { - UIFormEditor newEditor = event.getNewEditor() instanceof UIFormEditor ? (UIFormEditor)event.getNewEditor() : null; - processFileEditorChange(newEditor); - } - } - - private class MyToolWindowPanel extends Splitter implements DataProvider { - MyToolWindowPanel() { - super(true, 0.33f); - } - - @Nullable - public Object getData(@NonNls String dataId) { - if (GuiEditor.DATA_KEY.is(dataId)) { - return getActiveFormEditor(); - } - return null; - } - } -} diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/BindingEditor.java b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/BindingEditor.java index 03c65b6640b1..c7547c7ff710 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/BindingEditor.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/BindingEditor.java @@ -25,8 +25,8 @@ import com.intellij.uiDesigner.FormEditingUtil; import com.intellij.uiDesigner.core.Spacer; import com.intellij.uiDesigner.inspections.FormInspectionUtil; import com.intellij.uiDesigner.lw.IRootContainer; +import com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager; import com.intellij.uiDesigner.propertyInspector.InplaceContext; -import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager; import com.intellij.uiDesigner.propertyInspector.properties.BindingProperty; import com.intellij.uiDesigner.radComponents.RadComponent; import com.intellij.uiDesigner.radComponents.RadErrorComponent; @@ -67,7 +67,8 @@ public final class BindingEditor extends ComboBoxPropertyEditor { SwingUtilities.invokeLater( new Runnable(){ public void run(){ - UIDesignerToolWindowManager.getInstance(project).getPropertyInspector().requestFocus(); + DesignerToolWindowManager.getInstance(DesignerToolWindowManager.getInstance(project).getActiveFormEditor()) + .getPropertyInspector().requestFocus(); } } ); diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/string/StringEditor.java b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/string/StringEditor.java index 99a6bbc82fcf..2f22910f08af 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/string/StringEditor.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/string/StringEditor.java @@ -26,9 +26,9 @@ import com.intellij.ui.DocumentAdapter; import com.intellij.uiDesigner.UIDesignerBundle; import com.intellij.uiDesigner.designSurface.GuiEditor; import com.intellij.uiDesigner.lw.StringDescriptor; -import com.intellij.uiDesigner.propertyInspector.PropertyEditor; -import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager; +import com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager; import com.intellij.uiDesigner.propertyInspector.InplaceContext; +import com.intellij.uiDesigner.propertyInspector.PropertyEditor; import com.intellij.uiDesigner.propertyInspector.properties.IntroStringProperty; import com.intellij.uiDesigner.radComponents.RadComponent; import com.intellij.util.ui.UIUtil; @@ -170,7 +170,7 @@ public final class StringEditor extends PropertyEditor { public void actionPerformed(final ActionEvent e) { // 1. Show editor dialog - final GuiEditor guiEditor = UIDesignerToolWindowManager.getInstance(myProject).getActiveFormEditor(); + final GuiEditor guiEditor = DesignerToolWindowManager.getInstance(myProject).getActiveFormEditor(); LOG.assertTrue(guiEditor != null); final StringEditorDialog dialog = new StringEditorDialog( diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/properties/BindingProperty.java b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/properties/BindingProperty.java index 58306f72167a..70d7d3017a95 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/properties/BindingProperty.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/properties/BindingProperty.java @@ -39,10 +39,10 @@ import com.intellij.uiDesigner.compiler.AsmCodeGenerator; import com.intellij.uiDesigner.designSurface.GuiEditor; import com.intellij.uiDesigner.designSurface.InsertComponentProcessor; import com.intellij.uiDesigner.inspections.FormInspectionUtil; +import com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager; import com.intellij.uiDesigner.propertyInspector.Property; import com.intellij.uiDesigner.propertyInspector.PropertyEditor; import com.intellij.uiDesigner.propertyInspector.PropertyRenderer; -import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager; import com.intellij.uiDesigner.propertyInspector.editors.BindingEditor; import com.intellij.uiDesigner.propertyInspector.renderers.LabelPropertyRenderer; import com.intellij.uiDesigner.quickFixes.CreateFieldFix; @@ -177,7 +177,7 @@ public final class BindingProperty extends Property { } // Commit document before refactoring starts - GuiEditor editor = UIDesignerToolWindowManager.getInstance(project).getActiveFormEditor(); + GuiEditor editor = DesignerToolWindowManager.getInstance(project).getActiveFormEditor(); if (editor != null) { editor.refreshAndSave(false); } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/quickFixes/ShowHintAction.java b/plugins/ui-designer/src/com/intellij/uiDesigner/quickFixes/ShowHintAction.java index f08294c5cbff..beb87f197151 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/quickFixes/ShowHintAction.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/quickFixes/ShowHintAction.java @@ -17,8 +17,8 @@ package com.intellij.uiDesigner.quickFixes; import com.intellij.openapi.actionSystem.*; import com.intellij.uiDesigner.designSurface.GuiEditor; +import com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager; import com.intellij.uiDesigner.propertyInspector.PropertyInspector; -import com.intellij.uiDesigner.propertyInspector.UIDesignerToolWindowManager; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -46,8 +46,7 @@ final class ShowHintAction extends AnAction { myManager.showIntentionHint(); // 2. Commit possible non committed value and show popup - final UIDesignerToolWindowManager manager = UIDesignerToolWindowManager.getInstance(editor.getProject()); - final PropertyInspector propertyInspector = manager.getPropertyInspector(); + final PropertyInspector propertyInspector = DesignerToolWindowManager.getInstance(myManager.getEditor()).getPropertyInspector(); if(propertyInspector != null && propertyInspector.isEditing()) { propertyInspector.stopEditing(); } diff --git a/plugins/ui-designer/src/messages/UIDesignerBundle.properties b/plugins/ui-designer/src/messages/UIDesignerBundle.properties index d8231bc59b39..d544e3993776 100644 --- a/plugins/ui-designer/src/messages/UIDesignerBundle.properties +++ b/plugins/ui-designer/src/messages/UIDesignerBundle.properties @@ -271,7 +271,8 @@ add.component.choose.icon=Choose Icon File inspection.no.scroll.pane=Scrollable component not in JScrollPane inspection.no.scroll.pane.quickfix=Surround with JScrollPane surround.with.popup.title=Surround With -toolwindow.ui.designer=UI Designer +toolwindow.ui.designer.name=UI Designer +toolwindow.ui.designer.title=Component Tree error.cannot.delete.unused.field=Cannot delete unused field: {0} command.delete.unused.field=Delete Unused Field error.for.component=Component {0}: {1} From 6addfe099471f905f2602308ad8b3325c799ec19 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Wed, 10 Sep 2014 13:41:10 +0200 Subject: [PATCH 22/23] notnull --- .../src/com/intellij/mock/MockVirtualFileSystem.java | 2 ++ .../intellij/testFramework/fixtures/IdeaTestFixtureFactory.java | 2 ++ .../com/intellij/testFramework/fixtures/TestFixtureBuilder.java | 2 ++ .../fixtures/impl/HeavyTestFixtureBuilderImpl.java | 2 ++ .../testFramework/fixtures/impl/IdeaTestFixtureFactoryImpl.java | 1 + .../fixtures/impl/LightTestFixtureBuilderImpl.java | 2 ++ 6 files changed, 11 insertions(+) diff --git a/platform/testFramework/src/com/intellij/mock/MockVirtualFileSystem.java b/platform/testFramework/src/com/intellij/mock/MockVirtualFileSystem.java index 73b8cfeaf267..c5a806a1125c 100644 --- a/platform/testFramework/src/com/intellij/mock/MockVirtualFileSystem.java +++ b/platform/testFramework/src/com/intellij/mock/MockVirtualFileSystem.java @@ -32,6 +32,7 @@ public class MockVirtualFileSystem extends DeprecatedVirtualFileSystem { public static final String PROTOCOL = "mock"; @Override + @NotNull public VirtualFile findFileByPath(@NotNull String path) { path = path.replace(File.separatorChar, '/'); path = path.replace('/', ':'); @@ -106,6 +107,7 @@ public class MockVirtualFileSystem extends DeprecatedVirtualFileSystem { return MockVirtualFileSystem.this; } + @NotNull public MyVirtualFile getOrCreate(String name) { MyVirtualFile file = myChildren.get(name); if (file == null) { diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/IdeaTestFixtureFactory.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/IdeaTestFixtureFactory.java index 010caad8fcd2..ecc5bff4dc50 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/IdeaTestFixtureFactory.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/IdeaTestFixtureFactory.java @@ -37,6 +37,7 @@ public abstract class IdeaTestFixtureFactory { } } + @NotNull public static IdeaTestFixtureFactory getFixtureFactory() { return ourInstance; } @@ -59,6 +60,7 @@ public abstract class IdeaTestFixtureFactory { public abstract TestFixtureBuilder createFixtureBuilder(@NotNull String name); + @NotNull public abstract TestFixtureBuilder createLightFixtureBuilder(); public abstract TestFixtureBuilder createLightFixtureBuilder(@Nullable LightProjectDescriptor projectDescriptor); diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/TestFixtureBuilder.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/TestFixtureBuilder.java index b275ec521c8c..1d0e648611ef 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/TestFixtureBuilder.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/TestFixtureBuilder.java @@ -17,11 +17,13 @@ package com.intellij.testFramework.fixtures; import com.intellij.testFramework.builders.ModuleFixtureBuilder; +import org.jetbrains.annotations.NotNull; /** * @author mike */ public interface TestFixtureBuilder { + @NotNull T getFixture(); M addModule(Class builderClass); diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyTestFixtureBuilderImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyTestFixtureBuilderImpl.java index c7b7779fe92a..412c87ee5bce 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyTestFixtureBuilderImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyTestFixtureBuilderImpl.java @@ -22,6 +22,7 @@ import com.intellij.testFramework.fixtures.IdeaProjectTestFixture; import com.intellij.testFramework.fixtures.TestFixtureBuilder; import com.intellij.util.pico.ConstructorInjectionComponentAdapter; import com.intellij.util.pico.IdeaPicoContainer; +import org.jetbrains.annotations.NotNull; import org.picocontainer.MutablePicoContainer; import java.lang.reflect.Field; @@ -50,6 +51,7 @@ class HeavyTestFixtureBuilderImpl implements TestFixtureBuilder createLightFixtureBuilder() { return new LightTestFixtureBuilderImpl(new LightIdeaTestFixtureImpl( diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/LightTestFixtureBuilderImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/LightTestFixtureBuilderImpl.java index 43a2ee7c031c..a196e4211649 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/LightTestFixtureBuilderImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/LightTestFixtureBuilderImpl.java @@ -19,6 +19,7 @@ package com.intellij.testFramework.fixtures.impl; import com.intellij.testFramework.builders.ModuleFixtureBuilder; import com.intellij.testFramework.fixtures.IdeaProjectTestFixture; import com.intellij.testFramework.fixtures.TestFixtureBuilder; +import org.jetbrains.annotations.NotNull; /** * @author mike @@ -31,6 +32,7 @@ class LightTestFixtureBuilderImpl implements T myFixture = fixture; } + @NotNull @Override public F getFixture() { return myFixture; From c34bd7071523daa61e535c811edf968b54b176df Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Wed, 10 Sep 2014 15:34:00 +0400 Subject: [PATCH 23/23] IDEA-125738 Goto custom region action usability --- .../CustomFoldingRegionsPopup.java | 133 ++++++++++++++ .../customFolding/GotoCustomRegionAction.java | 96 +++++++--- .../customFolding/GotoCustomRegionDialog.form | 25 --- .../customFolding/GotoCustomRegionDialog.java | 169 ------------------ .../src/messages/IdeBundle.properties | 5 +- 5 files changed, 206 insertions(+), 222 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/lang/customFolding/CustomFoldingRegionsPopup.java delete mode 100644 platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionDialog.form delete mode 100644 platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionDialog.java diff --git a/platform/lang-impl/src/com/intellij/lang/customFolding/CustomFoldingRegionsPopup.java b/platform/lang-impl/src/com/intellij/lang/customFolding/CustomFoldingRegionsPopup.java new file mode 100644 index 000000000000..203179709dae --- /dev/null +++ b/platform/lang-impl/src/com/intellij/lang/customFolding/CustomFoldingRegionsPopup.java @@ -0,0 +1,133 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.lang.customFolding; + +import com.intellij.ide.IdeBundle; +import com.intellij.lang.folding.FoldingDescriptor; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.ScrollType; +import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.ui.popup.PopupChooserBuilder; +import com.intellij.psi.PsiElement; +import com.intellij.ui.components.JBList; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.util.*; + +/** + * @author Rustam Vishnyakov + */ +public class CustomFoldingRegionsPopup { + private final @NotNull JBList myRegionsList; + private final @NotNull JBPopup myPopup; + private final @NotNull Editor myEditor; + + CustomFoldingRegionsPopup(@NotNull Collection descriptors, + @NotNull final Editor editor, + @NotNull final Project project) { + myEditor = editor; + myRegionsList = new JBList(); + //noinspection unchecked + myRegionsList.setModel(new MyListModel(orderByPosition(descriptors))); + myRegionsList.setSelectedIndex(0); + + final PopupChooserBuilder popupBuilder = JBPopupFactory.getInstance().createListPopupBuilder(myRegionsList); + myPopup = popupBuilder + .setTitle(IdeBundle.message("goto.custom.region.command")) + .setResizable(false) + .setMovable(false) + .setItemChoosenCallback(new Runnable() { + @Override + public void run() { + PsiElement navigationElement = getNavigationElement(); + if (navigationElement != null) { + navigateTo(editor, navigationElement); + IdeDocumentHistory.getInstance(project).includeCurrentCommandAsNavigation(); + } + } + }).createPopup(); + } + + void show() { + myPopup.showInBestPositionFor(myEditor); + } + + private static class MyListModel extends DefaultListModel { + private MyListModel(Collection descriptors) { + for (FoldingDescriptor descriptor : descriptors) { + //noinspection unchecked + super.addElement(new MyFoldingDescriptorWrapper(descriptor)); + } + } + } + + private static class MyFoldingDescriptorWrapper { + private final @NotNull FoldingDescriptor myDescriptor; + + private MyFoldingDescriptorWrapper(@NotNull FoldingDescriptor descriptor) { + myDescriptor = descriptor; + } + + @NotNull + public FoldingDescriptor getDescriptor() { + return myDescriptor; + } + + @Nullable + @Override + public String toString() { + return myDescriptor.getPlaceholderText(); + } + } + + @Nullable + public PsiElement getNavigationElement() { + Object selection = myRegionsList.getSelectedValue(); + if (selection instanceof MyFoldingDescriptorWrapper) { + return ((MyFoldingDescriptorWrapper)selection).getDescriptor().getElement().getPsi(); + } + return null; + } + + private static Collection orderByPosition(Collection descriptors) { + List sorted = new ArrayList(descriptors.size()); + sorted.addAll(descriptors); + Collections.sort(sorted, new Comparator() { + @Override + public int compare(FoldingDescriptor descriptor1, FoldingDescriptor descriptor2) { + int pos1 = descriptor1.getElement().getTextRange().getStartOffset(); + int pos2 = descriptor2.getElement().getTextRange().getStartOffset(); + return pos1 - pos2; + } + }); + return sorted; + } + + private static void navigateTo(@NotNull Editor editor, @NotNull PsiElement element) { + int offset = element.getTextRange().getStartOffset(); + if (offset >= 0 && offset < editor.getDocument().getTextLength()) { + editor.getCaretModel().removeSecondaryCarets(); + editor.getCaretModel().moveToOffset(offset); + editor.getScrollingModel().scrollToCaret(ScrollType.CENTER); + editor.getSelectionModel().removeSelection(); + } + } +} diff --git a/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionAction.java b/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionAction.java index 016f7f14cc4d..e0117affbcad 100644 --- a/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionAction.java +++ b/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionAction.java @@ -16,26 +16,35 @@ package com.intellij.lang.customFolding; import com.intellij.ide.IdeBundle; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.actionSystem.Presentation; +import com.intellij.lang.Language; +import com.intellij.lang.folding.*; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.ScrollType; -import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; +import com.intellij.openapi.ui.MessageType; +import com.intellij.openapi.ui.popup.Balloon; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.util.Disposer; +import com.intellij.psi.FileViewProvider; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.util.containers.HashSet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.Set; /** * @author Rustam Vishnyakov */ -public class GotoCustomRegionAction extends AnAction implements DumbAware { +public class GotoCustomRegionAction extends AnAction implements DumbAware, PopupAction { @Override - public void actionPerformed(AnActionEvent e) { + public void actionPerformed(final AnActionEvent e) { final Project project = e.getProject(); final Editor editor = e.getData(CommonDataKeys.EDITOR); if (Boolean.TRUE.equals(e.getData(PlatformDataKeys.IS_MODAL_CONTEXT))) { @@ -52,14 +61,13 @@ public class GotoCustomRegionAction extends AnAction implements DumbAware { new Runnable() { @Override public void run() { - GotoCustomRegionDialog dialog = new GotoCustomRegionDialog(project, editor); - dialog.show(); - if (dialog.isOK()) { - PsiElement navigationElement = dialog.getNavigationElement(); - if (navigationElement != null) { - navigateTo(editor, navigationElement); - IdeDocumentHistory.getInstance(project).includeCurrentCommandAsNavigation(); - } + Collection foldingDescriptors = getCustomFoldingDescriptors(editor, project); + if (foldingDescriptors.size() > 0) { + CustomFoldingRegionsPopup regionsPopup = new CustomFoldingRegionsPopup(foldingDescriptors, editor, project); + regionsPopup.show(); + } + else { + notifyCustomRegionsUnavailable(editor, project); } } }, @@ -71,7 +79,7 @@ public class GotoCustomRegionAction extends AnAction implements DumbAware { @Override public void update(AnActionEvent e) { Presentation presentation = e.getPresentation(); - presentation.setText("Custom Region..."); + presentation.setText(IdeBundle.message("goto.custom.region.menu.item")); final Editor editor = e.getData(CommonDataKeys.EDITOR); final Project project = e.getProject(); boolean isAvailable = editor != null && project != null; @@ -79,13 +87,49 @@ public class GotoCustomRegionAction extends AnAction implements DumbAware { presentation.setVisible(isAvailable); } - private static void navigateTo(Editor editor, PsiElement element) { - int offset = element.getTextRange().getStartOffset(); - if (offset >= 0 && offset < editor.getDocument().getTextLength()) { - editor.getCaretModel().removeSecondaryCarets(); - editor.getCaretModel().moveToOffset(offset); - editor.getScrollingModel().scrollToCaret(ScrollType.CENTER); - editor.getSelectionModel().removeSelection(); + @NotNull + private static Collection getCustomFoldingDescriptors(@NotNull Editor editor, @NotNull Project project) { + Set foldingDescriptors = new HashSet(); + final Document document = editor.getDocument(); + PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project); + PsiFile file = documentManager != null ? documentManager.getPsiFile(document) : null; + if (file != null) { + final FileViewProvider viewProvider = file.getViewProvider(); + for (final Language language : viewProvider.getLanguages()) { + final PsiFile psi = viewProvider.getPsi(language); + final FoldingBuilder foldingBuilder = LanguageFolding.INSTANCE.forLanguage(language); + if (psi != null) { + for (FoldingDescriptor descriptor : LanguageFolding.buildFoldingDescriptors(foldingBuilder, psi, document, false)) { + CustomFoldingBuilder customFoldingBuilder = getCustomFoldingBuilder(foldingBuilder, descriptor); + if (customFoldingBuilder != null) { + if (customFoldingBuilder.isCustomRegionStart(descriptor.getElement())) { + foldingDescriptors.add(descriptor); + } + } + } + } + } } + return foldingDescriptors; + } + + @Nullable + private static CustomFoldingBuilder getCustomFoldingBuilder(FoldingBuilder builder, FoldingDescriptor descriptor) { + if (builder instanceof CustomFoldingBuilder) return (CustomFoldingBuilder)builder; + FoldingBuilder originalBuilder = descriptor.getElement().getUserData(CompositeFoldingBuilder.FOLDING_BUILDER); + if (originalBuilder instanceof CustomFoldingBuilder) return (CustomFoldingBuilder)originalBuilder; + return null; + } + + private static void notifyCustomRegionsUnavailable(@NotNull Editor editor, @NotNull Project project) { + final JBPopupFactory popupFactory = JBPopupFactory.getInstance(); + Balloon balloon = popupFactory + .createHtmlTextBalloonBuilder(IdeBundle.message("goto.custom.region.message.unavailable"), MessageType.INFO, null) + .setFadeoutTime(2000) + .setHideOnClickOutside(true) + .setHideOnKeyOutside(true) + .createBalloon(); + Disposer.register(project, balloon); + balloon.show(popupFactory.guessBestPopupLocation(editor), Balloon.Position.above); } } diff --git a/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionDialog.form b/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionDialog.form deleted file mode 100644 index c155616c8186..000000000000 --- a/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionDialog.form +++ /dev/null @@ -1,25 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - -
diff --git a/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionDialog.java b/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionDialog.java deleted file mode 100644 index 49d63dfe24b9..000000000000 --- a/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionDialog.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2000-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.lang.customFolding; - -import com.intellij.ide.IdeBundle; -import com.intellij.lang.Language; -import com.intellij.lang.folding.*; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.psi.FileViewProvider; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.ui.components.JBList; -import com.intellij.ui.components.JBScrollPane; -import com.intellij.util.containers.HashSet; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; -import java.awt.*; -import java.util.*; -import java.util.List; - -/** - * @author Rustam Vishnyakov - */ -public class GotoCustomRegionDialog extends DialogWrapper { - private JBList myRegionsList; - private JPanel myContentPane; - private JBScrollPane myScrollPane; - private final Editor myEditor; - private final Project myProject; - - protected GotoCustomRegionDialog(@Nullable Project project, @NotNull Editor editor) { - super(project); - myEditor = editor; - myProject = project; - Collection descriptors = getCustomFoldingDescriptors(); - init(); - if (descriptors.size() == 0) { - myScrollPane.setVisible(false); - myContentPane.add(new JLabel(IdeBundle.message("goto.custom.region.message.unavailable")), BorderLayout.NORTH); - setOKActionEnabled(false); - } - else { - myRegionsList.setModel(new MyListModel(orderByPosition(descriptors))); - myRegionsList.setSelectedIndex(0); - } - setTitle(IdeBundle.message("goto.custom.region.command")); - } - - @Override - public JComponent getPreferredFocusedComponent() { - if (!myRegionsList.isEmpty()) { - return myRegionsList; - } - return super.getPreferredFocusedComponent(); - } - - @Override - protected JComponent createCenterPanel() { - return myContentPane; - } - - private Collection getCustomFoldingDescriptors() { - Set foldingDescriptors = new HashSet(); - final Document document = myEditor.getDocument(); - PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject); - PsiFile file = documentManager != null ? documentManager.getPsiFile(document) : null; - if (file != null) { - final FileViewProvider viewProvider = file.getViewProvider(); - for (final Language language : viewProvider.getLanguages()) { - final PsiFile psi = viewProvider.getPsi(language); - final FoldingBuilder foldingBuilder = LanguageFolding.INSTANCE.forLanguage(language); - if (psi != null) { - for (FoldingDescriptor descriptor : LanguageFolding.buildFoldingDescriptors(foldingBuilder, psi, document, false)) { - CustomFoldingBuilder customFoldingBuilder = getCustomFoldingBuilder(foldingBuilder, descriptor); - if (customFoldingBuilder != null) { - if (customFoldingBuilder.isCustomRegionStart(descriptor.getElement())) { - foldingDescriptors.add(descriptor); - } - } - } - } - } - } - return foldingDescriptors; - } - - private static Collection orderByPosition(Collection descriptors) { - List sorted = new ArrayList(descriptors.size()); - sorted.addAll(descriptors); - Collections.sort(sorted, new Comparator() { - @Override - public int compare(FoldingDescriptor descriptor1, FoldingDescriptor descriptor2) { - int pos1 = descriptor1.getElement().getTextRange().getStartOffset(); - int pos2 = descriptor2.getElement().getTextRange().getStartOffset(); - return pos1 - pos2; - } - }); - return sorted; - } - - private void createUIComponents() { - myRegionsList = new JBList(); - myScrollPane = new JBScrollPane(myRegionsList); - } - - @Nullable - private static CustomFoldingBuilder getCustomFoldingBuilder(FoldingBuilder builder, FoldingDescriptor descriptor) { - if (builder instanceof CustomFoldingBuilder) return (CustomFoldingBuilder)builder; - FoldingBuilder originalBuilder = descriptor.getElement().getUserData(CompositeFoldingBuilder.FOLDING_BUILDER); - if (originalBuilder instanceof CustomFoldingBuilder) return (CustomFoldingBuilder)originalBuilder; - return null; - } - - - private static class MyListModel extends DefaultListModel { - private MyListModel(Collection descriptors) { - for (FoldingDescriptor descriptor : descriptors) { - super.addElement(new MyFoldingDescriptorWrapper(descriptor)); - } - } - } - - private static class MyFoldingDescriptorWrapper { - private final @NotNull FoldingDescriptor myDescriptor; - - private MyFoldingDescriptorWrapper(@NotNull FoldingDescriptor descriptor) { - myDescriptor = descriptor; - } - - @NotNull - public FoldingDescriptor getDescriptor() { - return myDescriptor; - } - - @Nullable - @Override - public String toString() { - return myDescriptor.getPlaceholderText(); - } - } - - @Nullable - public PsiElement getNavigationElement() { - Object selection = myRegionsList.getSelectedValue(); - if (selection instanceof MyFoldingDescriptorWrapper) { - return ((MyFoldingDescriptorWrapper)selection).getDescriptor().getElement().getPsi(); - } - return null; - } -} diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index 720ac40cc1eb..e5a1ecc0f649 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -1142,8 +1142,9 @@ whatsnew.action.custom.text=What''s _New in {0} whatsnew.action.custom.description=Find out about the new features in this version of {0} diff.dialog.title=Diff Between ''{0}'' and ''{1}'' -goto.custom.region.command=Go to Custom Region -goto.custom.region.message.dumb.mode=Go to Custom Region action is not available until indices are built. +goto.custom.region.menu.item=Custom Folding Region... +goto.custom.region.command=Go to Custom Folding Region +goto.custom.region.message.dumb.mode=Go to Custom Folding Region action is not available until indices are built. goto.custom.region.message.unavailable=There are no custom folding regions in the current file. alphabetical.mode.is.on.warning=Alphabetical order for tabs is ON. Switch it OFF?