From 239a86900326dba149a6724f56357ab8f295e34d Mon Sep 17 00:00:00 2001 From: nik Date: Tue, 15 May 2012 12:31:36 +0400 Subject: [PATCH 01/61] supported per-module encoding detection in jps --- .../jps/incremental/BuilderRegistry.java | 5 + .../CompilerEncodingConfiguration.java | 107 ++++++++++++++++++ .../jps/incremental/ModuleLevelBuilder.java | 4 + .../jps/incremental/java/JavaBuilder.java | 5 + .../jps/server/ProjectDescriptor.java | 7 ++ .../src/org/jetbrains/jps/Project.groovy | 1 + .../jps/idea/IdeaProjectLoader.groovy | 4 + .../jps/incremental/groovy/GroovyBuilder.java | 5 + 8 files changed, 138 insertions(+) create mode 100644 jps/jps-builders/src/org/jetbrains/jps/incremental/CompilerEncodingConfiguration.java diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java index dbe6eecef318..8070a4a9f556 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java @@ -1,5 +1,6 @@ package org.jetbrains.jps.incremental; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.jps.idea.OwnServiceLoader; import java.util.*; @@ -65,6 +66,10 @@ public class BuilderRegistry { return Collections.unmodifiableList(myModuleLevelBuilders.get(category)); // todo } + public List getAllModuleLevelBuilders() { + return ContainerUtil.concat(myModuleLevelBuilders.values()); + } + public List getProjectLevelBuilders() { return myProjectLevelBuilders; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompilerEncodingConfiguration.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompilerEncodingConfiguration.java new file mode 100644 index 000000000000..62bedef2151b --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompilerEncodingConfiguration.java @@ -0,0 +1,107 @@ +package org.jetbrains.jps.incremental; + +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.util.containers.ContainerUtil; +import gnu.trove.THashMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.Module; +import org.jetbrains.jps.ModuleChunk; +import org.jetbrains.jps.incremental.fs.RootDescriptor; + +import java.io.File; +import java.util.*; + +/** + * @author nik + */ +public class CompilerEncodingConfiguration { + private final Map myFilePathToCharset; + private final ModuleRootsIndex myRootsIndex; + private Map> myModuleCharsetMap; + + public CompilerEncodingConfiguration(Map filePathToCharset, ModuleRootsIndex rootsIndex) { + myFilePathToCharset = filePathToCharset; + myRootsIndex = rootsIndex; + } + + public Map> getModuleCharsetMap() { + if (myModuleCharsetMap == null) { + myModuleCharsetMap = computeModuleCharsetMap(); + } + return myModuleCharsetMap; + } + + private Map> computeModuleCharsetMap() { + final Map> map = new THashMap>(); + final List builders = BuilderRegistry.getInstance().getAllModuleLevelBuilders(); + for (Map.Entry entry : myFilePathToCharset.entrySet()) { + final String filePath = entry.getKey(); + final String charset = entry.getValue(); + File file = new File(FileUtil.toSystemDependentName(filePath)); + if (charset == null || (!file.isDirectory() && !shouldHonorEncodingForCompilation(builders, file))) continue; + + final RootDescriptor rootDescriptor = myRootsIndex.getModuleAndRoot(file); + if (rootDescriptor == null) continue; + + final String module = rootDescriptor.module; + Set set = map.get(module); + if (set == null) { + set = new LinkedHashSet(); + map.put(module, set); + + final File sourceRoot = rootDescriptor.root; + File current = FileUtil.getParentFile(file); + String parentCharset = null; + while (current != null) { + final String currentCharset = myFilePathToCharset.get(FileUtil.toSystemIndependentName(current.getAbsolutePath())); + if (currentCharset != null) { + parentCharset = currentCharset; + } + if (FileUtil.filesEqual(current, sourceRoot)) { + break; + } + current = FileUtil.getParentFile(current); + } + if (parentCharset != null) { + set.add(parentCharset); + } + } + set.add(charset); + } + + return map; + } + + private static boolean shouldHonorEncodingForCompilation(List builders, File file) { + for (ModuleLevelBuilder builder : builders) { + if (builder.shouldHonorFileEncodingForCompilation(file)) { + return true; + } + } + return false; + } + + @Nullable + public String getPreferredModuleChunkEncoding(@NotNull ModuleChunk moduleChunk) { + for (Module module : moduleChunk.getModules()) { + final Set encodings = getModuleCharsetMap().get(module.getName()); + final String encoding = ContainerUtil.getFirstItem(encodings, null); + if (encoding != null) return encoding; + } + return null; + } + + @NotNull + public Set getAllModuleChunkEncodings(@NotNull ModuleChunk moduleChunk) { + final Map> map = getModuleCharsetMap(); + Set encodings = new HashSet(); + for (Module module : moduleChunk.getModules()) { + final Set moduleEncodings = map.get(module.getName()); + if (moduleEncodings != null) { + encodings.addAll(moduleEncodings); + } + } + return encodings; + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java index 014c9ff487f3..f480fde5b38f 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java @@ -41,6 +41,10 @@ public abstract class ModuleLevelBuilder extends Builder { public abstract ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException; + public boolean shouldHonorFileEncodingForCompilation(File file) { + return false; + } + public final BuilderCategory getCategory() { return myCategory; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index 38f7516f288c..d7a5483a6608 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -223,6 +223,11 @@ public class JavaBuilder extends ModuleLevelBuilder { } } + @Override + public boolean shouldHonorFileEncodingForCompilation(File file) { + return JAVA_SOURCES_FILTER.accept(file) || FORM_SOURCES_FILTER.accept(file); + } + @Nullable private static File getBoundSource(File srcRoot, File formFile) throws IOException { final String boundClassName = FormsParsing.readBoundClassName(formFile); diff --git a/jps/jps-builders/src/org/jetbrains/jps/server/ProjectDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/server/ProjectDescriptor.java index e62b7c878921..c0fa5acbc087 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/server/ProjectDescriptor.java +++ b/jps/jps-builders/src/org/jetbrains/jps/server/ProjectDescriptor.java @@ -5,6 +5,7 @@ import org.jetbrains.jps.Module; import org.jetbrains.jps.Project; import org.jetbrains.jps.Sdk; import org.jetbrains.jps.incremental.BuildLoggingManager; +import org.jetbrains.jps.incremental.CompilerEncodingConfiguration; import org.jetbrains.jps.incremental.ModuleRootsIndex; import org.jetbrains.jps.incremental.fs.BuildFSState; import org.jetbrains.jps.incremental.storage.BuildDataManager; @@ -27,6 +28,7 @@ public final class ProjectDescriptor { public ModuleRootsIndex rootsIndex; private int myUseCounter = 1; private Set myProjectJavaSdks; + private CompilerEncodingConfiguration myEncodingConfiguration; public ProjectDescriptor(Project project, BuildFSState fsState, @@ -40,6 +42,7 @@ public final class ProjectDescriptor { myLoggingManager = loggingManager; this.rootsIndex = new ModuleRootsIndex(project); myProjectJavaSdks = new HashSet(); + myEncodingConfiguration = new CompilerEncodingConfiguration(project.getFilePathToCharset(), rootsIndex); for (Module module : project.getModules().values()) { final Sdk sdk = module.getSdk(); if (sdk instanceof JavaSdk && !myProjectJavaSdks.contains(sdk)) { @@ -51,6 +54,10 @@ public final class ProjectDescriptor { } } + public CompilerEncodingConfiguration getEncodingConfiguration() { + return myEncodingConfiguration; + } + public Set getProjectJavaSdks() { return myProjectJavaSdks; } diff --git a/jps/model/src/org/jetbrains/jps/Project.groovy b/jps/model/src/org/jetbrains/jps/Project.groovy index d08da5c5ed64..bc330008cf39 100644 --- a/jps/model/src/org/jetbrains/jps/Project.groovy +++ b/jps/model/src/org/jetbrains/jps/Project.groovy @@ -22,6 +22,7 @@ class Project { final IgnoredFilePatterns ignoredFilePatterns = new IgnoredFilePatterns() String projectCharset; // contains project charset, if not specified default charset will be used (used by compilers) + Map filePathToCharset = [:]; def Project() { } diff --git a/jps/model/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy b/jps/model/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy index a500b889211d..d40e9cc91e9b 100644 --- a/jps/model/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy +++ b/jps/model/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy @@ -340,6 +340,10 @@ public class IdeaProjectLoader { if ("PROJECT".equals(url)) { project.projectCharset = charset; } + else { + def path = projectMacroExpander.expandMacros(IdeaProjectLoadingUtil.pathFromUrl(url)); + project.filePathToCharset[path] = charset; + } } } diff --git a/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java b/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java index d854a99bf2c6..f23b54077dd6 100644 --- a/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java +++ b/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java @@ -132,6 +132,11 @@ public class GroovyBuilder extends ModuleLevelBuilder { return moduleOutputPath.endsWith("/") ? moduleOutputPath : moduleOutputPath + "/"; } + @Override + public boolean shouldHonorFileEncodingForCompilation(File file) { + return isGroovyFile(file.getAbsolutePath()); + } + private String getCompilerOutput(String moduleOutputDir) throws IOException { return FileUtil.toCanonicalPath((myForStubs ? FileUtil.createTempDirectory("groovyStubs", null) : new File(moduleOutputDir)).getPath()); } From e185fd37c390030a8cda541cda7f17b2b6f97f2e Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 15 May 2012 12:26:00 +0400 Subject: [PATCH 02/61] more startup logging --- .../intellij/openapi/components/impl/ComponentManagerImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java index bdedb7ec2194..951e861606a5 100644 --- a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java @@ -98,7 +98,9 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements private void createComponents() { try { + long start = System.currentTimeMillis(); myComponentsRegistry.loadClasses(); + LOG.info("Component classes loaded in " + (System.currentTimeMillis() - start) + " ms"); final Class[] componentInterfaces = myComponentsRegistry.getComponentInterfaces(); for (Class componentInterface : componentInterfaces) { From 50111be994b99ab8875cadf57f3f6b3644c749e0 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 15 May 2012 12:49:40 +0400 Subject: [PATCH 03/61] literals are keywords again [romka] --- .../src/com/intellij/psi/impl/source/tree/ElementType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/ElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/ElementType.java index b506fd85e094..06607b51eeb4 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/ElementType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/ElementType.java @@ -38,7 +38,7 @@ public interface ElementType extends JavaTokenType, JavaDocTokenType, INT_KEYWORD, INTERFACE_KEYWORD, LONG_KEYWORD, NATIVE_KEYWORD, NEW_KEYWORD, PACKAGE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, SHORT_KEYWORD, SUPER_KEYWORD, SWITCH_KEYWORD, STRICTFP_KEYWORD, SYNCHRONIZED_KEYWORD, THIS_KEYWORD, THROW_KEYWORD, PROTECTED_KEYWORD, TRANSIENT_KEYWORD, RETURN_KEYWORD, VOID_KEYWORD, STATIC_KEYWORD, WHILE_KEYWORD, TRY_KEYWORD, VOLATILE_KEYWORD, THROWS_KEYWORD, - ENUM_KEYWORD); + ENUM_KEYWORD, TRUE_KEYWORD, FALSE_KEYWORD, NULL_KEYWORD); TokenSet OPERATION_BIT_SET = TokenSet.create( EQ, GT, LT, EXCL, TILDE, QUEST, COLON, PLUS, MINUS, ASTERISK, DIV, AND, OR, XOR, From c8838c615c353796ce22158766c52ebb43794339 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 15 May 2012 13:00:44 +0400 Subject: [PATCH 04/61] logging removed --- .../components/impl/ComponentManagerImpl.java | 144 +++++++----------- 1 file changed, 52 insertions(+), 92 deletions(-) diff --git a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java index 951e861606a5..8e14a3bb733d 100644 --- a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java @@ -24,6 +24,7 @@ import com.intellij.openapi.extensions.PluginDescriptor; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressIndicatorProvider; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.UserDataHolderBase; @@ -40,8 +41,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; import org.picocontainer.*; +import org.picocontainer.defaults.*; import org.picocontainer.defaults.CachingComponentAdapter; -import org.picocontainer.defaults.ConstructorInjectionComponentAdapter; import java.lang.reflect.Array; import java.util.ArrayList; @@ -98,9 +99,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements private void createComponents() { try { - long start = System.currentTimeMillis(); myComponentsRegistry.loadClasses(); - LOG.info("Component classes loaded in " + (System.currentTimeMillis() - start) + " ms"); final Class[] componentInterfaces = myComponentsRegistry.getComponentInterfaces(); for (Class componentInterface : componentInterfaces) { @@ -445,13 +444,14 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements try { final Class interfaceClass = Class.forName(config.getInterfaceClass(), true, loader); - final Class implementationClass = Class.forName(config.getImplementationClass(), true, loader); + final Class implementationClass = Comparing.equal(config.getInterfaceClass(), config.getImplementationClass()) ? + interfaceClass : Class.forName(config.getImplementationClass(), true, loader); if (myInterfaceToClassMap.get(interfaceClass) != null) { throw new Error("ComponentSetup for component " + interfaceClass.getName() + " already registered"); } - getPicoContainer().registerComponent(new ComponentConfigComponentAdapter(config)); + getPicoContainer().registerComponent(new ComponentConfigComponentAdapter(config, implementationClass)); myInterfaceToClassMap.put(interfaceClass, implementationClass); myComponentClassToConfig.put(implementationClass, config); myComponentInterfaces.add(interfaceClass); @@ -561,12 +561,57 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements private class ComponentConfigComponentAdapter implements ComponentAdapter { private final ComponentConfig myConfig; - private ComponentAdapter myDelegate; + private final ComponentAdapter myDelegate; private boolean myInitialized = false; private boolean myInitializing = false; - public ComponentConfigComponentAdapter(final ComponentConfig config) { + public ComponentConfigComponentAdapter(final ComponentConfig config, Class implementationClass) { myConfig = config; + final String componentKey = config.getInterfaceClass(); + myDelegate = new CachingComponentAdapter(new ConstructorInjectionComponentAdapter(componentKey, implementationClass, null, true)) { + @Override + public Object getComponentInstance(PicoContainer picoContainer) throws PicoInitializationException, PicoIntrospectionException { + Object componentInstance = null; + try { + long startTime = myInitialized ? 0 : System.nanoTime(); + componentInstance = super.getComponentInstance(picoContainer); + + if (!myInitialized) { + if (myInitializing) { + if (myConfig.pluginDescriptor != null) { + LOG.error(new PluginException("Cyclic component initialization: " + componentKey, myConfig.pluginDescriptor.getPluginId())); + } + else { + LOG.error(new Throwable("Cyclic component initialization: " + componentKey)); + } + } + myInitializing = true; + myComponentsRegistry.registerComponentInstance(componentInstance); + initComponent(componentInstance); + long endTime = System.nanoTime(); + long ms = (endTime - startTime) / 1000000; + if (ms > 10) { + if (logSlowComponents()) { + LOG.info(componentInstance.getClass().getName() + " initialized in " + ms + " ms"); + } + } + myInitializing = false; + myInitialized = true; + } + } + catch (ProcessCanceledException e) { + throw e; + } + catch (StateStorageException e) { + throw e; + } + catch (Throwable t) { + handleInitComponentError(t, componentInstance == null, componentKey); + } + return componentInstance; + } + }; + } @Override @@ -596,92 +641,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements } private ComponentAdapter getDelegate() { - if (myDelegate == null) { - final Object componentKey = getComponentKey(); - - ClassLoader loader = myConfig.getClassLoader(); - - Class implementationClass = null; - - try { - implementationClass = Class.forName(myConfig.getImplementationClass(), true, loader); - } - catch (Exception e) { - @NonNls final String message = "Error while registering component: " + myConfig; - - if (myConfig.pluginDescriptor != null) { - LOG.error(message, new PluginException(e, myConfig.pluginDescriptor.getPluginId())); - } - else { - LOG.error(message, e); - } - } - catch (Error e) { - if (myConfig.pluginDescriptor != null) { - LOG.error(new PluginException(e, myConfig.pluginDescriptor.getPluginId())); - } - else { - throw e; - } - } - - assert implementationClass != null; - - myDelegate = new CachingComponentAdapter(new ConstructorInjectionComponentAdapter(componentKey, implementationClass, null, true)) { - @Override - public Object getComponentInstance(PicoContainer picoContainer) throws PicoInitializationException, PicoIntrospectionException { - Object componentInstance = null; - try { - long startTime = myInitialized ? 0 : System.nanoTime(); - componentInstance = super.getComponentInstance(picoContainer); - - if (!myInitialized) { - if (myInitializing) { - if (myConfig.pluginDescriptor != null) { - LOG.error(new PluginException("Cyclic component initialization: " + componentKey, myConfig.pluginDescriptor.getPluginId())); - } - else { - LOG.error(new Throwable("Cyclic component initialization: " + componentKey)); - } - } - myInitializing = true; - myComponentsRegistry.registerComponentInstance(componentInstance); - initComponent(componentInstance); - long endTime = System.nanoTime(); - long ms = (endTime - startTime) / 1000000; - if (ms > 10) { - if (logSlowComponents()) { - LOG.info(componentInstance.getClass().getName() + " initialized in " + ms + " ms"); - } - } - myInitializing = false; - myInitialized = true; - } - } - catch (ProcessCanceledException e) { - throw e; - } - catch (StateStorageException e) { - throw e; - } - catch (Throwable t) { - handleInitComponentError(t, componentInstance == null, componentKey.toString()); - } - return componentInstance; - } - }; - } - return myDelegate; } } - - public final int hashCode() { - return super.hashCode(); - } - - @SuppressWarnings({"EqualsWhichDoesntCheckParameterClass"}) - public final boolean equals(Object obj) { - return super.equals(obj); - } } From 3b9144bc7b264aeafb642c838abc1c2f240fa9bf Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 15 May 2012 13:15:23 +0400 Subject: [PATCH 05/61] inplace rename: naming, restore warnings for non-substituted renames (IDEA-85729) --- .../refactoring/rename/inplace/InplaceRefactoring.java | 8 +++----- .../rename/inplace/MemberInplaceRenameHandler.java | 2 +- .../refactoring/rename/inplace/MemberInplaceRenamer.java | 6 +++++- .../rename/inplace/VariableInplaceRenamer.java | 4 +--- .../src/messages/RefactoringBundle.properties | 1 + 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java index d6015a1ed694..b3f0a517a0d9 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java @@ -252,11 +252,9 @@ public abstract class InplaceRefactoring { if (oldDocument != myEditor.getDocument()) { final int exitCode = Messages.showYesNoCancelDialog(myProject, e.getMessage(), getCommandName(), "Navigate to Started", "Cancel Started", "Cancel", Messages.getErrorIcon()); - if (exitCode == -1 || exitCode == Messages.CANCEL) return true; - //todo ann: //if (exitCode == Messages.YES ) { - navigateToAlreadyStarted(oldDocument, exitCode); - return true; - //} + if (exitCode == -1) return true; + navigateToAlreadyStarted(oldDocument, exitCode); + return true; } else { revertState(); diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenameHandler.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenameHandler.java index 216165ab7fcc..45d74ff03420 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenameHandler.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenameHandler.java @@ -57,7 +57,7 @@ public class MemberInplaceRenameHandler extends VariableInplaceRenameHandler { final RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(elementToRename); if (processor.isInplaceRenameSupported()) { final StartMarkAction startMarkAction = StartMarkAction.canStart(elementToRename.getProject()); - if (startMarkAction == null) { + if (startMarkAction == null || processor.substituteElementToRename(elementToRename, editor) == elementToRename) { processor.substituteElementToRename(elementToRename, editor, new Pass() { @Override public void pass(PsiElement element) { diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java index baa446d0025f..52894500489f 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java @@ -24,6 +24,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.editor.impl.EditorImpl; import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; @@ -237,7 +238,10 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer { @Override protected void revertStateOnFinish() { - ((EditorImpl)InjectedLanguageUtil.getTopLevelEditor(myEditor)).startDumb(); + final Editor editor = InjectedLanguageUtil.getTopLevelEditor(myEditor); + if (editor == FileEditorManager.getInstance(myProject).getSelectedTextEditor()) { + ((EditorImpl)editor).startDumb(); + } revertState(); } diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java index a1c1c2a7fd32..8894c2cc7c71 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java @@ -44,7 +44,6 @@ import com.intellij.refactoring.rename.naming.AutomaticRenamerFactory; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.refactoring.util.TextOccurrencesUtil; import com.intellij.usageView.UsageInfo; -import com.intellij.usageView.UsageViewUtil; import com.intellij.util.PairProcessor; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; @@ -260,8 +259,7 @@ public class VariableInplaceRenamer extends InplaceRefactoring { LOG.error(myElementToRename); return "Rename"; } - return RefactoringBundle.message("renaming.0.1.to.2", UsageViewUtil.getType(variable), UsageViewUtil.getDescriptiveName(variable), - variable.getName()); + return RefactoringBundle.message("renaming.command.name", myInitialName); } @Override diff --git a/platform/platform-resources-en/src/messages/RefactoringBundle.properties b/platform/platform-resources-en/src/messages/RefactoringBundle.properties index f9871e1aad9c..8efe3f1f88f3 100644 --- a/platform/platform-resources-en/src/messages/RefactoringBundle.properties +++ b/platform/platform-resources-en/src/messages/RefactoringBundle.properties @@ -577,6 +577,7 @@ inner.class.0.is.already.defined.in.class.1=Inner class {0} is already defined i class.0.already.exists=Class {0} already exists renaming.something=Renaming something renaming.0.1.to.2=Renaming {0} {1} to {2} +renaming.command.name=Renaming {0} 0.to.be.renamed.to.1.2={0} to be renamed to {1}{2} references.in.code.to.0=References in code to {0} rename.variables.title=Rename Variables From 7ca6a15de801695ca7dc990a73eb2dc792d7be42 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 15 May 2012 13:31:27 +0400 Subject: [PATCH 06/61] romca's fix reverted --- .../src/com/intellij/psi/impl/source/tree/ElementType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/ElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/ElementType.java index 06607b51eeb4..b506fd85e094 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/ElementType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/ElementType.java @@ -38,7 +38,7 @@ public interface ElementType extends JavaTokenType, JavaDocTokenType, INT_KEYWORD, INTERFACE_KEYWORD, LONG_KEYWORD, NATIVE_KEYWORD, NEW_KEYWORD, PACKAGE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, SHORT_KEYWORD, SUPER_KEYWORD, SWITCH_KEYWORD, STRICTFP_KEYWORD, SYNCHRONIZED_KEYWORD, THIS_KEYWORD, THROW_KEYWORD, PROTECTED_KEYWORD, TRANSIENT_KEYWORD, RETURN_KEYWORD, VOID_KEYWORD, STATIC_KEYWORD, WHILE_KEYWORD, TRY_KEYWORD, VOLATILE_KEYWORD, THROWS_KEYWORD, - ENUM_KEYWORD, TRUE_KEYWORD, FALSE_KEYWORD, NULL_KEYWORD); + ENUM_KEYWORD); TokenSet OPERATION_BIT_SET = TokenSet.create( EQ, GT, LT, EXCL, TILDE, QUEST, COLON, PLUS, MINUS, ASTERISK, DIV, AND, OR, XOR, From dde04a403d5fa8aafeda7e58dc2b9718a7545567 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 15 May 2012 15:05:01 +0400 Subject: [PATCH 07/61] preserve javadoc refs during inplace rename (IDEA-85817) --- .../completion/JavaDocCompletionContributor.java | 1 + .../impl/source/javadoc/PsiDocMethodOrFieldRef.java | 12 ------------ .../javaDoc/LinkFromInnerClassToSelfMethod.java | 2 +- .../codeInsight/daemonCodeAnalyzer/javaDoc/See3.java | 2 +- .../daemonCodeAnalyzer/javaDoc/Vararg.java | 2 +- .../daemonCodeAnalyzer/javaDoc/resolve/pkg/See1.java | 8 ++++---- .../renameInplace/MethodWithJavadocRef.java | 11 +++++++++++ .../renameInplace/MethodWithJavadocRef_after.java | 11 +++++++++++ .../refactoring/RenameMembersInplaceTest.java | 4 ++++ 9 files changed, 34 insertions(+), 19 deletions(-) create mode 100644 java/java-tests/testData/refactoring/renameInplace/MethodWithJavadocRef.java create mode 100644 java/java-tests/testData/refactoring/renameInplace/MethodWithJavadocRef_after.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java index 3a7469a87256..cffb3f0f1762 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java @@ -220,6 +220,7 @@ public class JavaDocCompletionContributor extends CompletionContributor { if (context.getCompletionChar() == Lookup.REPLACE_SELECT_CHAR) { final PsiDocTagValue valueElement = tag.getValueElement(); endOffset = valueElement.getTextRange().getEndOffset(); + context.setTailOffset(endOffset); } editor.getDocument().deleteString(afterSharp, endOffset); editor.getCaretModel().moveToOffset(signatureOffset); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocMethodOrFieldRef.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocMethodOrFieldRef.java index 91cdd946eb29..c42d906d94cd 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocMethodOrFieldRef.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocMethodOrFieldRef.java @@ -381,18 +381,6 @@ public class PsiDocMethodOrFieldRef extends CompositePsiElement implements PsiDo if (nextSibling != null) { final int startOffset = nextSibling.getTextRange().getStartOffset() - getTextRange().getStartOffset(); int endOffset = nextSibling.getTextRange().getEndOffset() - getTextRange().getStartOffset(); - final PsiElement nextParSibling = nextSibling.getNextSibling(); - if (nextParSibling != null && "(".equals(nextParSibling.getText())) { - endOffset++; - PsiElement nextElement = nextParSibling.getNextSibling(); - if (nextElement != null && SourceTreeToPsiMap.psiToTreeNotNull(nextElement).getElementType() == DOC_TAG_VALUE_TOKEN) { - endOffset += nextElement.getTextLength(); - nextElement = nextElement.getNextSibling(); - } - if (nextElement != null && ")".equals(nextElement.getText())) { - endOffset++; - } - } return new TextRange(startOffset, endOffset); } return new TextRange(getTextLength(), getTextLength()); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/LinkFromInnerClassToSelfMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/LinkFromInnerClassToSelfMethod.java index c8a24ca4ee9d..5071c0125218 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/LinkFromInnerClassToSelfMethod.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/LinkFromInnerClassToSelfMethod.java @@ -2,7 +2,7 @@ class Test { public void i(int ppp) {} /** - * {@link #foo(int)} + * {@link #foo(int)} * {@link #foo()} * {@link #i(int)} */ diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/See3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/See3.java index f5e465172ba3..121b6bf585e5 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/See3.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/See3.java @@ -1,6 +1,6 @@ class Test { /** - * @see #perform(int) + * @see #perform(int) */ public void i() {} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Vararg.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Vararg.java index 604c85627cc2..5192745c27da 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Vararg.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Vararg.java @@ -1,7 +1,7 @@ public class Test { /** * @see Test#test(String, int...) - * @see Test#test(String, long...) + * @see Test#test(String, long...) **/ void foo() {} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/resolve/pkg/See1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/resolve/pkg/See1.java index 24d1dae563da..fcd58fccc0fc 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/resolve/pkg/See1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/resolve/pkg/See1.java @@ -1,10 +1,10 @@ package pkg; /** - * @see #method(B1.C) - * @see #method(B1.C[][]) - * @see #method(B1.C..) - * @see #method(B1.C[) + * @see #method(B1.C) + * @see #method(B1.C[][]) + * @see #method(B1.C..) + * @see #method(B1.C[) */ class A1 { public void method(B1.C[] c) { } diff --git a/java/java-tests/testData/refactoring/renameInplace/MethodWithJavadocRef.java b/java/java-tests/testData/refactoring/renameInplace/MethodWithJavadocRef.java new file mode 100644 index 000000000000..f807afcfe63c --- /dev/null +++ b/java/java-tests/testData/refactoring/renameInplace/MethodWithJavadocRef.java @@ -0,0 +1,11 @@ +public class RefactorBug { + public static void something(int a, float b) { + } + + /** + * @see #something(int, float) + */ + public static void somethingElse() { + + } +} diff --git a/java/java-tests/testData/refactoring/renameInplace/MethodWithJavadocRef_after.java b/java/java-tests/testData/refactoring/renameInplace/MethodWithJavadocRef_after.java new file mode 100644 index 000000000000..3fb1fc23599d --- /dev/null +++ b/java/java-tests/testData/refactoring/renameInplace/MethodWithJavadocRef_after.java @@ -0,0 +1,11 @@ +public class RefactorBug { + public static void bar(int a, float b) { + } + + /** + * @see #bar(int, float) + */ + public static void somethingElse() { + + } +} diff --git a/java/java-tests/testSrc/com/intellij/refactoring/RenameMembersInplaceTest.java b/java/java-tests/testSrc/com/intellij/refactoring/RenameMembersInplaceTest.java index 585216da1f8e..d551d0ea8580 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/RenameMembersInplaceTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/RenameMembersInplaceTest.java @@ -53,6 +53,10 @@ public class RenameMembersInplaceTest extends LightCodeInsightTestCase { public void testClassWithMultipleConstructors() throws Exception { doTestInplaceRename("Bar"); } + + public void testMethodWithJavadocRef() throws Exception { + doTestInplaceRename("bar"); + } public void testConflictingMethodName() throws Exception { try { From 252cc5354228ad8d9051f50a073246813f79b3bb Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 15 May 2012 13:26:30 +0200 Subject: [PATCH 08/61] use default project --- .../src/com/intellij/openapi/diff/MergeApplication.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/openapi/diff/MergeApplication.java b/platform/platform-api/src/com/intellij/openapi/diff/MergeApplication.java index 2ce8927cb5c3..b2e29f1bc88d 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/MergeApplication.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/MergeApplication.java @@ -16,6 +16,7 @@ package com.intellij.openapi.diff; import com.intellij.openapi.application.ApplicationNamesInfo; +import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.vfs.VirtualFile; /** @@ -41,7 +42,7 @@ public class MergeApplication extends ApplicationStarterBase { MergeRequest request = DiffRequestFactory.getInstance() .createMergeRequest(getText(left), getText(right), getText(middle), result, - null, + ProjectManager.getInstance().getDefaultProject(), ActionButtonPresentation.APPLY, ActionButtonPresentation.CANCEL_WITH_PROMPT); request.addHint(DiffTool.HINT_SHOW_MODAL_DIALOG); From e2917706cf15292ee8b07fcb8d76374b22248293 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Tue, 15 May 2012 10:49:28 +0200 Subject: [PATCH 09/61] TestFramework: 'assertInstanceOf' logging improved --- .../src/com/intellij/testFramework/UsefulTestCase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java index 576b80af610b..01fcccbf1368 100644 --- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java @@ -468,7 +468,7 @@ public abstract class UsefulTestCase extends TestCase { } public static T assertInstanceOf(Object o, Class aClass) { - Assert.assertNotNull(o); + Assert.assertNotNull("Expected instance of: " + aClass.getName() + " actual: " + null, o); Assert.assertTrue("Expected instance of: " + aClass.getName() + " actual: " + o.getClass().getName(), aClass.isInstance(o)); return (T)o; } From a10da2400a36f8178a4f4d8a4e2596f372aec9be Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Tue, 15 May 2012 15:56:24 +0400 Subject: [PATCH 10/61] IDEA-19061 Integrate the Rearranger-plugin into core-IDEA *) 'groovy' dependency is added to the 'rearranger' module; *) RearrangerTest is re-written to groovy; *) refactorings; --- plugins/rearranger/rearranger.iml | 1 + .../rearranger/RearrangerActionHandler.java | 4 +- .../rearranger/entry/ClassContentsEntry.java | 15 +- .../com/wrq/rearranger/entry/ClassEntry.java | 106 ++++---- .../entry/ClassInitializerEntry.java | 2 +- .../com/wrq/rearranger/entry/FieldEntry.java | 12 +- .../com/wrq/rearranger/entry/MethodEntry.java | 243 +++++++++--------- .../entry/MiscellaneousTextEntry.java | 10 +- ...ngeEntry.java => PopupTreeRangeEntry.java} | 4 +- .../wrq/rearranger/entry/PsiFileEntry.java | 22 +- .../com/wrq/rearranger/entry/RangeEntry.java | 185 +++++++------ ...elatableEntry.java => RelatableEntry.java} | 2 +- .../wrq/rearranger/popup/FilePopupEntry.java | 2 + .../wrq/rearranger/rearrangement/Emitter.java | 41 +-- .../rearrangement/GenericRearranger.java | 74 +++--- .../wrq/rearranger/rearrangement/Mover.java | 23 +- .../wrq/rearranger/rearrangement/Parser.java | 30 ++- .../wrq/rearranger/rearrangement/Spacer.java | 145 +++++------ .../ruleinstance/CommentRuleInstance.java | 42 ++- .../ruleinstance/CommonRuleInstance.java | 6 +- .../HeaderTrailerRuleInstance.java | 18 +- .../ruleinstance/InterfaceInstance.java | 11 +- .../PrecedingCommentRuleInstance.java | 4 +- .../rearranger/ruleinstance/RuleInstance.java | 3 +- .../SubsequentCommentRuleInstance.java | 4 +- .../SurroundingCommentRuleInstance.java | 8 +- .../wrq/rearranger/settings/CommentRule.java | 11 +- .../attributeGroups/AttributeGroup.java | 10 +- .../attributeGroups/ClassAttributes.java | 33 ++- .../attributeGroups/CommonAttributes.java | 119 ++++----- .../settings/attributeGroups/DefaultRule.java | 4 +- .../attributeGroups/FieldAttributes.java | 33 +-- .../settings/attributeGroups/HeaderRule.java | 16 +- .../attributeGroups/InnerClassAttributes.java | 31 ++- .../attributeGroups/InterfaceAttributes.java | 7 +- .../attributeGroups/ItemAttributes.java | 8 +- .../attributeGroups/MethodAttributes.java | 53 ++-- .../settings/attributeGroups/Rule.java | 7 +- .../settings/attributeGroups/TrailerRule.java | 4 +- .../com/wrq/rearranger/util/CommentUtil.java | 57 ++-- .../com/wrq/rearranger/RearrangerTest.groovy | 29 +-- .../attributeGroups/MethodAttributesTest.java | 6 +- .../wrq/rearranger/RearrangementResult2.java | 4 +- 43 files changed, 728 insertions(+), 721 deletions(-) rename plugins/rearranger/src/com/wrq/rearranger/entry/{IPopupTreeRangeEntry.java => PopupTreeRangeEntry.java} (93%) rename plugins/rearranger/src/com/wrq/rearranger/entry/{IRelatableEntry.java => RelatableEntry.java} (98%) diff --git a/plugins/rearranger/rearranger.iml b/plugins/rearranger/rearranger.iml index 7adfe3aca0d2..cb24fd03e1f1 100644 --- a/plugins/rearranger/rearranger.iml +++ b/plugins/rearranger/rearranger.iml @@ -17,6 +17,7 @@ + diff --git a/plugins/rearranger/src/com/wrq/rearranger/RearrangerActionHandler.java b/plugins/rearranger/src/com/wrq/rearranger/RearrangerActionHandler.java index 10bd83c6ce03..64a58b1ca43d 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/RearrangerActionHandler.java +++ b/plugins/rearranger/src/com/wrq/rearranger/RearrangerActionHandler.java @@ -152,7 +152,7 @@ public final class RearrangerActionHandler extends EditorActionHandler { wb.whenTrue(); } catch (InterruptedException e) { - e.printStackTrace(); //To change body of catch statement use Options | File Templates. + e.printStackTrace(); } LOG.debug("end execute"); } @@ -186,7 +186,7 @@ public final class RearrangerActionHandler extends EditorActionHandler { } LOG.debug("respacing document"); PsiDocumentManager.getInstance(project).commitDocument(document); - Spacer spacer = new Spacer(project, psiFile, document, settings); + Spacer spacer = new Spacer(psiFile, document, settings); if (spacer.respace()) { PsiDocumentManager.getInstance(project).commitDocument(document); } diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/ClassContentsEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassContentsEntry.java index 743e31a51e15..f5130853b1e5 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/ClassContentsEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassContentsEntry.java @@ -26,6 +26,7 @@ import com.intellij.psi.PsiField; import com.wrq.rearranger.popup.FilePopupEntry; import com.wrq.rearranger.popup.RearrangerTreeNode; import com.wrq.rearranger.settings.RearrangerSettings; +import org.jetbrains.annotations.Nullable; import javax.swing.tree.DefaultMutableTreeNode; @@ -37,18 +38,18 @@ public abstract class ClassContentsEntry extends RangeEntry implements FilePopupEntry { - public ClassContentsEntry(final PsiElement start, - final PsiElement end, + public ClassContentsEntry(@Nullable final PsiElement start, + @Nullable final PsiElement end, final int modifiers, final String modifierString, - final String name, + final @Nullable String name, final String type) { super(start, end, modifiers, modifierString, name, type); } - public ClassContentsEntry(final PsiElement start, - final PsiElement end, + public ClassContentsEntry(@Nullable final PsiElement start, + @Nullable final PsiElement end, final boolean fixedHeader, final boolean fixedTrailer) { @@ -57,10 +58,10 @@ public abstract class ClassContentsEntry public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) { DefaultMutableTreeNode node = null; - if ((end instanceof PsiField && settings.isShowFields()) || + if ((myEnd instanceof PsiField && settings.isShowFields()) || (this instanceof ClassEntry)) { - node = new RearrangerTreeNode(this, name); + node = new RearrangerTreeNode(this, myName); parent.add(node); } return node; diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/ClassEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassEntry.java index f73d7c96543b..e6254a69ee88 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/ClassEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassEntry.java @@ -35,6 +35,8 @@ import com.wrq.rearranger.rearrangement.GenericRearranger; import com.wrq.rearranger.ruleinstance.RuleInstance; import com.wrq.rearranger.settings.RearrangerSettings; import com.wrq.rearranger.util.ModifierUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; @@ -48,36 +50,33 @@ import java.util.List; * Describes an entire class's range and type. * This information is used when reordering outer classes. */ -public class ClassEntry - extends ClassContentsEntry - implements FilePopupEntry -{ +public class ClassEntry extends ClassContentsEntry implements FilePopupEntry { + private static final Logger LOG = Logger.getInstance("#" + ClassEntry.class.getName()); - protected final List contents; - private List myResultRuleInstances; - private final RearrangerSettings settings; - private final int nestingLevel; + protected final List myContents; + private List myResultRuleInstances; + private final RearrangerSettings mySettings; + private final int myNestingLevel; - public ClassEntry(PsiElement start, - PsiElement end, + public ClassEntry(@Nullable PsiElement start, + @Nullable PsiElement end, int modifiers, String modifierString, - String name, + @Nullable String name, int nestingLevel, - RearrangerSettings settings) - { + RearrangerSettings settings) { super(start, end, modifiers, modifierString, name, ""); - contents = new ArrayList(); + myContents = new ArrayList(); myResultRuleInstances = null; - this.settings = settings; - this.nestingLevel = nestingLevel; + mySettings = settings; + myNestingLevel = nestingLevel; } public String getTypeIconName() { String result = "nodes/class"; - if (end.getParent() instanceof PsiClass) { - PsiClass psiClass = (PsiClass)end.getParent(); + if (myEnd.getParent() instanceof PsiClass) { + PsiClass psiClass = (PsiClass)myEnd.getParent(); if (psiClass.isEnum()) { result = "nodes/enum"; } @@ -89,15 +88,20 @@ public class ClassEntry } public String[] getAdditionalIconNames() { - if (end instanceof PsiJavaToken && end.getText().equals("{")) { - PsiClass psiClass = (PsiClass)end.getParent(); - if (psiClass.getModifierList().hasModifierProperty(PsiModifier.PUBLIC)) { + if (myEnd instanceof PsiJavaToken && myEnd.getText().equals("{")) { + PsiClass psiClass = (PsiClass)myEnd.getParent(); + final PsiModifierList modifierList = psiClass.getModifierList(); + if (modifierList == null) { + return null; + } + + if (modifierList.hasModifierProperty(PsiModifier.PUBLIC)) { return new String[]{"nodes/c_public"}; } - if (psiClass.getModifierList().hasModifierProperty(PsiModifier.PROTECTED)) { + if (modifierList.hasModifierProperty(PsiModifier.PROTECTED)) { return new String[]{"nodes/c_protected"}; } - if (psiClass.getModifierList().hasModifierProperty(PsiModifier.PRIVATE)) { + if (modifierList.hasModifierProperty(PsiModifier.PRIVATE)) { return new String[]{"nodes/c_private"}; } return new String[]{"nodes/c_plocal"}; @@ -106,20 +110,19 @@ public class ClassEntry } public JLabel getPopupEntryText(RearrangerSettings settings) { - return new JLabel(name); + return new JLabel(myName); } protected void parseRemainingClassContents(final Project project, int startingIndex, final PsiElement psiClass - ) - { + ) { final PsiSearchHelper psh = PsiSearchHelper.SERVICE.getInstance(project); int lastIndex = startingIndex; /** * if option indicates, don't parse inner class contents; leave them unchanged. */ - if (settings.isRearrangeInnerClasses() || nestingLevel <= 1) { + if (mySettings.isRearrangeInnerClasses() || myNestingLevel <= 1) { for (int i = startingIndex; i < psiClass.getChildren().length; i++) { PsiElement child = psiClass.getChildren()[i]; if (child instanceof PsiJavaToken && child.getText().equals("{")) { @@ -163,7 +166,7 @@ public class ClassEntry ); } if (child instanceof PsiClass) { - parseClassAttributes(child, attributes); + parseClassAttributes((PsiClass)child, attributes); // // if child is an enum, set the last entry past the LBrace to the final enumeration or the // semicolon thereafter, if any. @@ -189,8 +192,8 @@ public class ClassEntry attributes.modifiers, attributes.modifierString, attributes.name, - nestingLevel + 1, - settings + myNestingLevel + 1, + mySettings ); classContentsEntry = entry; entry.parseRemainingClassContents( @@ -206,7 +209,7 @@ public class ClassEntry attributes.modifierString, attributes.name); } - contents.add(classContentsEntry); + myContents.add(classContentsEntry); classContentsEntry.checkForComment(); lastIndex = i + 1; // next class includes everything since the end of the prior class. } @@ -222,7 +225,7 @@ public class ClassEntry psiClass.getChildren()[psiClass.getChildren().length - 1], false, true ); - contents.add(miscellaneousTextEntry); + myContents.add(miscellaneousTextEntry); miscellaneousTextEntry.checkForComment(); } } @@ -467,13 +470,16 @@ public class ClassEntry } } - private void parseClassAttributes(PsiElement child, MemberAttributes attributes) { - attributes.childClass = (PsiClass)child; + private static void parseClassAttributes(@NotNull PsiClass child, @NotNull MemberAttributes attributes) { + attributes.childClass = child; attributes.name = attributes.childClass.getName(); if (attributes.name == null) { attributes.name = ""; } - attributes.modifierString = attributes.childClass.getModifierList().getText(); + final PsiModifierList modifierList = child.getModifierList(); + if (modifierList != null) { + attributes.modifierString = modifierList.getText(); + } attributes.modifiers = ModifierUtils.getModifierMask(attributes.modifierString); attributes.type = attributes.childClass.isEnum() ? "enum" : "class"; if (attributes.childClass.isEnum()) { @@ -514,14 +520,14 @@ public class ClassEntry LOG.debug("identifying setters and extracted (related) methods"); for (ClassContentsEntry contentsEntry : getContents()) { - if (contentsEntry instanceof IRelatableEntry) { - ((IRelatableEntry)contentsEntry).determineSettersAndMethodCalls(settings, getContents()); + if (contentsEntry instanceof RelatableEntry) { + ((RelatableEntry)contentsEntry).determineSettersAndMethodCalls(mySettings, getContents()); } } LOG.debug("relating extracted methods"); for (ClassContentsEntry contentsEntry : getContents()) { - if (contentsEntry instanceof IRelatableEntry) { - ((IRelatableEntry)contentsEntry).determineExtractedMethod(settings.getExtractedMethodsSettings()); + if (contentsEntry instanceof RelatableEntry) { + ((RelatableEntry)contentsEntry).determineExtractedMethod(mySettings.getExtractedMethodsSettings()); } } /** @@ -532,18 +538,18 @@ public class ClassEntry * check for overloaded extracted methods; if configured to be kept together, attach subsequent * methods to the first and remove them from consideration for other alignment. */ - MethodEntry.handleOverloadedMethods(getContents(), settings); + MethodEntry.handleOverloadedMethods(getContents(), mySettings); final GenericRearranger classContentsRearranger = - new GenericRearranger(settings.getItemOrderAttributeList(), - contents, - nestingLevel, - settings) + new GenericRearranger(mySettings.getItemOrderAttributeList(), + myContents, + myNestingLevel, + mySettings) { public void rearrangeRelatedItems(List entries, List ruleInstanceList) { for (RuleInstance ruleInstance : ruleInstanceList) { - ruleInstance.rearrangeRuleItems(entries, settings); + ruleInstance.rearrangeRuleItems(entries, mySettings); } } }; @@ -551,13 +557,13 @@ public class ClassEntry } private void buildMethodCallGraph() { - if (settings.getExtractedMethodsSettings().isMoveExtractedMethods() || - settings.isKeepGettersSettersTogether()) + if (mySettings.getExtractedMethodsSettings().isMoveExtractedMethods() || + mySettings.isKeepGettersSettersTogether()) { LOG.debug("building method call & getter-setter graph"); for (ClassContentsEntry contentsEntry : getContents()) { - if (contentsEntry instanceof IRelatableEntry) { - ((IRelatableEntry)contentsEntry).determineGetterSetterAndExtractedMethodStatus(settings); + if (contentsEntry instanceof RelatableEntry) { + ((RelatableEntry)contentsEntry).determineGetterSetterAndExtractedMethodStatus(mySettings); } } } @@ -566,7 +572,7 @@ public class ClassEntry // End Methods of Interface IFilePopupEntry public final List getContents() { - return contents; + return myContents; } public List getResultRuleInstances() { diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/ClassInitializerEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassInitializerEntry.java index f15a3b75c5e4..33d71745ba6a 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/ClassInitializerEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassInitializerEntry.java @@ -61,7 +61,7 @@ public class ClassInitializerEntry public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) { LOG.debug("add class initializer to popup tree"); - DefaultMutableTreeNode node = new RearrangerTreeNode(this, name); + DefaultMutableTreeNode node = new RearrangerTreeNode(this, myName); parent.add(node); return node; } diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/FieldEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/FieldEntry.java index 92b96ab24473..cf764203ccd5 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/FieldEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/FieldEntry.java @@ -54,16 +54,16 @@ public class FieldEntry } public String getTypeIconName() { - if (end instanceof PsiField) { - PsiField f = (PsiField)end; + if (myEnd instanceof PsiField) { + PsiField f = (PsiField)myEnd; return ((PsiModifierList)f.getModifierList()).hasModifierProperty(PsiModifier.STATIC) ? "nodes/staticField" : "nodes/field"; } return null; } public String[] getAdditionalIconNames() { - if (end instanceof PsiField) { - PsiField f = (PsiField)end; + if (myEnd instanceof PsiField) { + PsiField f = (PsiField)myEnd; if (f.getModifierList().hasModifierProperty(PsiModifier.PUBLIC)) return new String[]{"nodes/c_public"}; if (f.getModifierList().hasModifierProperty(PsiModifier.PROTECTED)) return new String[]{"nodes/c_protected"}; if (f.getModifierList().hasModifierProperty(PsiModifier.PRIVATE)) return new String[]{"nodes/c_private"}; @@ -74,7 +74,7 @@ public class FieldEntry public JLabel getPopupEntryText(RearrangerSettings settings) { StringBuffer name = new StringBuffer(80); - PsiField f = (PsiField)end; + PsiField f = (PsiField)myEnd; name.append(f.getName()); name.append(": "); name.append(f.getTypeElement().getText()); @@ -89,7 +89,7 @@ public class FieldEntry DefaultMutableTreeNode node = super.addToPopupTree(parent, settings); if (node != null && getterMethod != null) { getterMethod.addToPopupTree(node, settings); - for (MethodEntry me : getterMethod.correspondingGetterSetters) { + for (MethodEntry me : getterMethod.myCorrespondingGetterSetters) { me.addToPopupTree(node, settings); } } diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/MethodEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/MethodEntry.java index 450d3e7ddb97..209c0e894f4c 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/MethodEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/MethodEntry.java @@ -47,7 +47,7 @@ import java.util.*; */ public class MethodEntry extends ClassContentsEntry - implements IRelatableEntry + implements RelatableEntry { // ------------------------------ FIELDS ------------------------------ @@ -58,22 +58,23 @@ public class MethodEntry * the corresponding setter will be placed in calledMethods. This allows the same code to rearrange both * types of related methods. */ - List calledMethods = new ArrayList(); - List calledByMethods = new ArrayList(); - List overloadedMethods = new ArrayList(); + private final List myCalledMethods = new ArrayList(); + private final List myCalledByMethods = new ArrayList(); + private final List myOverloadedMethods = new ArrayList(); // MethodEntry correspondingSetter = null; // TODO - avoid wrong level for setters - List correspondingGetterSetters = new ArrayList(); - private boolean keptWithProperty; - private boolean relatedMethod; + final List myCorrespondingGetterSetters = new ArrayList(); + + private boolean myKeptWithProperty; + private boolean myRelatedMethod; /** @return true if the method is related to another. In this case, the method is exempt from rule matching. */ public boolean isRelatedMethod() { - return relatedMethod; + return myRelatedMethod; } /** @return true if the method is a setter and will be emitted below a corresponding getter. */ public boolean isEmittableSetter() { - return setter && correspondingGetterSetters.size() > 0; + return setter && myCorrespondingGetterSetters.size() > 0; } private boolean isOverloadedMethod; @@ -151,16 +152,16 @@ public class MethodEntry { List parentEntries = new ArrayList(ruleInstance.getMatches()); for (RangeEntry o : parentEntries) { - if (o instanceof IRelatableEntry) { + if (o instanceof RelatableEntry) { MethodEntry me = (MethodEntry)o; if (me.isGetter()) { - if (me.keptWithProperty) { + if (me.myKeptWithProperty) { if (me.getMatchedRule() != null && me.getMatchedRule().getMatches() != null) { // prevent the getter from appearing under a rule it matches; it will be placed under the property me.getMatchedRule().getMatches().remove(me); } } - for (MethodEntry theSetter : me.correspondingGetterSetters) { + for (MethodEntry theSetter : me.myCorrespondingGetterSetters) { final RuleInstance theRule = theSetter.getMatchedRule(); LOG.debug( "rearrangeRelatedItems: for getter method " + @@ -173,7 +174,7 @@ public class MethodEntry { LOG.debug( "remove entry " + - theSetter.end + + theSetter.myEnd + " from matched rule" + theRule + "; matches = " + @@ -183,15 +184,15 @@ public class MethodEntry } } } - if (me.calledMethods.size() > 0) { + if (me.myCalledMethods.size() > 0) { List parents = new LinkedList(); parents.add(me); moveRelatedItems( entries, parents, rms, - ((PsiMethod)me.end).getName(), - ((PsiMethod)me.end).getName() + "()", + ((PsiMethod)me.myEnd).getName(), + ((PsiMethod)me.myEnd).getName() + "()", 1 ); if (LOG.isDebugEnabled()) { @@ -234,10 +235,10 @@ public class MethodEntry ListIterator li = entries.listIterator(); while (li.hasNext()) { Object o = li.next(); - if (o instanceof IRelatableEntry) { + if (o instanceof RelatableEntry) { MethodEntry me = (MethodEntry)o; for (MethodEntry entry : parents) { - if (me.calledByMethods.contains(entry)) { + if (me.myCalledByMethods.contains(entry)) { children.add(me); li.remove(); break; @@ -255,10 +256,10 @@ public class MethodEntry ListIterator li = entries.listIterator(); while (li.hasNext()) { Object o = li.next(); - if (o instanceof IRelatableEntry) { + if (o instanceof RelatableEntry) { MethodEntry me = (MethodEntry)o; for (MethodEntry entry : parents) { - if (me.calledByMethods.contains(entry)) { + if (me.myCalledByMethods.contains(entry)) { me.insertAlphabetically(children); li.remove(); break; @@ -274,7 +275,7 @@ public class MethodEntry * Add these to the list of children in order of invocation. */ for (MethodEntry me : parents) { - for (MethodEntry child : me.calledMethods) { + for (MethodEntry child : me.myCalledMethods) { if (entries.contains(child)) { children.add(child); entries.remove(child); @@ -292,7 +293,7 @@ public class MethodEntry if (children.size() > 0) { if (rms.isDepthFirstOrdering()) { for (MethodEntry entry : children) { - if (entry.calledMethods.size() == 0) { + if (entry.myCalledMethods.size() == 0) { continue; } List parent = new LinkedList(); @@ -302,7 +303,7 @@ public class MethodEntry parent, rms, topLevelMethodName, - allMethodNames + "." + ((PsiMethod)entry.end).getName() + "()", + allMethodNames + "." + ((PsiMethod)entry.myEnd).getName() + "()", level + 1 ); } @@ -336,7 +337,7 @@ public class MethodEntry allMN.append(","); } first = false; - allMN.append(((PsiMethod)entry.end).getName()); + allMN.append(((PsiMethod)entry.myEnd).getName()); } } if (parents.size() > 1) { @@ -348,11 +349,11 @@ public class MethodEntry public void insertAlphabetically(final List list) { Comparator comparator = new Comparator() { public int compare(MethodEntry me, MethodEntry me2) { - String s = ((PsiMethod)me.end).getName(); + String s = ((PsiMethod)me.myEnd).getName(); if (me.isGetter()) { - s = MethodUtil.getPropertyName((PsiMethod)me.end); + s = MethodUtil.getPropertyName((PsiMethod)me.myEnd); } - return s.compareTo(((PsiMethod)me2.end).getName()); + return s.compareTo(((PsiMethod)me2.myEnd).getName()); } }; insertInList(list, comparator); @@ -365,7 +366,7 @@ public class MethodEntry MethodEntry entry = ((MethodEntry)li.next()); if (comparator.compare(this, entry) < 0) { LOG.debug( - "insertInList dependent method: add " + end.toString() + " at index " + (li.nextIndex() - 1) + "insertInList dependent method: add " + myEnd.toString() + " at index " + (li.nextIndex() - 1) ); list.add(li.nextIndex() - 1, this); inserted = true; @@ -377,7 +378,7 @@ public class MethodEntry } void dumpChild(int level) { - LOG.debug(level + ": " + ((PsiMethod)end).getName()); + LOG.debug(level + ": " + ((PsiMethod)myEnd).getName()); for (MethodEntry methodEntry : sortedMethods) { methodEntry.dumpChild(level + 1); } @@ -397,7 +398,7 @@ public class MethodEntry */ public static void eliminateCycles(List contents) { for (ClassContentsEntry entry : contents) { - if (entry instanceof IRelatableEntry) { + if (entry instanceof RelatableEntry) { MethodEntry current = (MethodEntry)entry; List set = new LinkedList(); set.add(current); @@ -407,13 +408,13 @@ public class MethodEntry } private static void test(MethodEntry current, List set) { - Iterator it = current.calledMethods.iterator(); + Iterator it = current.myCalledMethods.iterator(); while (it.hasNext()) { MethodEntry callee = it.next(); if (set.contains(callee)) { - callee.calledByMethods.remove(current); - if (callee.calledByMethods.size() == 0) { - callee.relatedMethod = false; + callee.myCalledByMethods.remove(current); + if (callee.myCalledByMethods.size() == 0) { + callee.myRelatedMethod = false; } it.remove(); } @@ -443,10 +444,10 @@ public class MethodEntry cullOverloadedMethods(contents, false); List copy = new ArrayList(contents); for (ClassContentsEntry rangeEntry : copy) { - if (rangeEntry instanceof IRelatableEntry) { + if (rangeEntry instanceof RelatableEntry) { MethodEntry current = (MethodEntry)rangeEntry; - if (current.overloadedMethods.size() > 0) { - List newList = new ArrayList(current.overloadedMethods.size() + 1); + if (current.myOverloadedMethods.size() > 0) { + List newList = new ArrayList(current.myOverloadedMethods.size() + 1); newList.add(current); /** * we are looking at the head of a list of overloaded methods. We need to sort the list @@ -456,11 +457,11 @@ public class MethodEntry case RearrangerSettings.OVERLOADED_ORDER_RETAIN_ORIGINAL: // list is already in original order, except perhaps that the top-most extracted method // comes first (if there is one). - newList.addAll(current.overloadedMethods); + newList.addAll(current.myOverloadedMethods); break; case RearrangerSettings.OVERLOADED_ORDER_ASCENDING_PARAMETERS: case RearrangerSettings.OVERLOADED_ORDER_DESCENDING_PARAMETERS: - for (MethodEntry entry : current.overloadedMethods) { + for (MethodEntry entry : current.myOverloadedMethods) { boolean inserted = false; for (int index = 0; index < newList.size(); index++) { MethodEntry me = newList.get(index); @@ -479,7 +480,7 @@ public class MethodEntry } break; } - current.overloadedMethods.clear(); + current.myOverloadedMethods.clear(); /** * if the head of the arraylist is not the same as "current", then the sort operation moved * another method to the head of the list. Replace that in the contents array. Then assign @@ -513,23 +514,23 @@ public class MethodEntry { List copy = new ArrayList(contents); for (ClassContentsEntry o : copy) { - if (o instanceof IRelatableEntry) { + if (o instanceof RelatableEntry) { MethodEntry me = (MethodEntry)o; if ((me.isRelatedMethod() == doExtractedMethods) && !me.isOverloadedMethod) { - String meName = me.end.toString(); + String meName = me.myEnd.toString(); // search contents list for methods with identical name, and attach them as overloaded methods. ListIterator contentIterator = contents.listIterator(); while (contentIterator.hasNext()) { Object o1 = contentIterator.next(); - if (o1 instanceof IRelatableEntry) { + if (o1 instanceof RelatableEntry) { MethodEntry me2 = (MethodEntry)o1; if (me2 == me) { continue; } - String me2Name = me2.end.toString(); + String me2Name = me2.myEnd.toString(); if (meName.equals(me2Name)) { contentIterator.remove(); - me.overloadedMethods.add(me2); + me.myOverloadedMethods.add(me2); me2.isOverloadedMethod = true; // set flag so array copy will skip this entry. } } @@ -564,8 +565,8 @@ public class MethodEntry public String[] getAdditionalIconNames() { ArrayList result = new ArrayList(); String[] sa = new String[0]; - if (end instanceof PsiMethod) { - PsiMethod m = (PsiMethod)end; + if (myEnd instanceof PsiMethod) { + PsiMethod m = (PsiMethod)myEnd; if (m.getModifierList().hasModifierProperty(PsiModifier.PUBLIC)) { result.add("nodes/c_public"); } @@ -595,8 +596,8 @@ public class MethodEntry } public String getTypeIconName() { - if (end instanceof PsiMethod) { - PsiMethod m = (PsiMethod)end; + if (myEnd instanceof PsiMethod) { + PsiMethod m = (PsiMethod)myEnd; return (((PsiModifierList)m.getModifierList()).hasModifierProperty(PsiModifier.STATIC)) ? "nodes/staticMethod" : "nodes/method"; } return null; @@ -610,7 +611,7 @@ public class MethodEntry public JLabel getPopupEntryText(RearrangerSettings settings) { StringBuffer name = new StringBuffer(80); - PsiMethod m = (PsiMethod)end; + PsiMethod m = (PsiMethod)myEnd; if (m.getReturnTypeElement() != null && !settings.isShowTypeAfterMethod()) { name.append(m.getReturnTypeElement().getText()); name.append(' '); @@ -670,13 +671,13 @@ public class MethodEntry */ setGetter( MethodUtil.isGetter( - (PsiMethod)end, + (PsiMethod)myEnd, settings.getDefaultGSDefinition() ) ); setSetter( MethodUtil.isSetter( - (PsiMethod)end, + (PsiMethod)myEnd, settings.getDefaultGSDefinition() ) ); @@ -686,7 +687,7 @@ public class MethodEntry if (((IRestrictMethodExtraction)rule).isNoExtractedMethods()) { LOG.debug( "excluding " + - end.toString() + + myEnd.toString() + " from extracted method consideration" ); setNoExtractedMethods(true); @@ -739,47 +740,47 @@ public class MethodEntry * option to keep getters and setters together is set. This is a special case.) */ public void determineExtractedMethod(RelatedMethodsSettings settings) { - relatedMethod = false; + myRelatedMethod = false; if (!isGetter() && !isSetter()) { - if (calledByMethods.size() > 0) { - PsiMethod m = (PsiMethod)end; + if (myCalledByMethods.size() > 0) { + PsiMethod m = (PsiMethod)myEnd; if (!m.getModifierList().hasModifierProperty(PsiModifier.PRIVATE)) { switch (settings.getNonPrivateTreatment()) { case RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_NEVER: break; case RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_ONE_CALLER: - if (calledByMethods.size() == 1) { - relatedMethod = true; + if (myCalledByMethods.size() == 1) { + myRelatedMethod = true; } break; case RelatedMethodsSettings.NON_PRIVATE_EXTRACTED_ANY_CALLERS: - relatedMethod = true; + myRelatedMethod = true; break; } } else { - relatedMethod = true; + myRelatedMethod = true; } } } else { - if (isSetter() && calledByMethods.size() > 0 && correspondingGetterSetters.size() == 0) { - relatedMethod = true; - LOG.debug(end.toString() + " is setter but has no getter, treated as extracted method"); + if (isSetter() && myCalledByMethods.size() > 0 && myCorrespondingGetterSetters.size() == 0) { + myRelatedMethod = true; + LOG.debug(myEnd.toString() + " is setter but has no getter, treated as extracted method"); } else { - LOG.debug(end.toString() + " is getter/setter, not treated as extracted method"); + LOG.debug(myEnd.toString() + " is getter/setter, not treated as extracted method"); } } - LOG.debug("determined " + end.toString() + " is extracted method? " + relatedMethod); + LOG.debug("determined " + myEnd.toString() + " is extracted method? " + myRelatedMethod); /** * If this is not an extracted method, remove it from any callers so that it won't be moved. */ - if (!relatedMethod) { - ListIterator li = calledByMethods.listIterator(); + if (!myRelatedMethod) { + ListIterator li = myCalledByMethods.listIterator(); while (li.hasNext()) { MethodEntry entry = (li.next()); - entry.calledMethods.remove(this); + entry.myCalledMethods.remove(this); li.remove(); } } @@ -787,31 +788,31 @@ public class MethodEntry * Remaining entries are only extracted methods at this point. Using first/last rule, keep only the call by * the calling method that this child method will be grouped with, and discard the rest. */ - if (calledByMethods.size() > 1) { + if (myCalledByMethods.size() > 1) { ListIterator li; if (settings.isBelowFirstCaller()) { - li = calledByMethods.listIterator(1); + li = myCalledByMethods.listIterator(1); while (li.hasNext()) { MethodEntry entry = (li.next()); - entry.calledMethods.remove(this); + entry.myCalledMethods.remove(this); li.remove(); } } else { - li = calledByMethods.listIterator(calledByMethods.size() - 1); + li = myCalledByMethods.listIterator(myCalledByMethods.size() - 1); while (li.hasPrevious()) { MethodEntry entry = (li.previous()); - entry.calledMethods.remove(this); + entry.myCalledMethods.remove(this); li.remove(); } } } - if (relatedMethod) { + if (myRelatedMethod) { LOG.debug( "extracted method " + toString() + " will be arranged under " + - calledByMethods.get(0).toString() + myCalledByMethods.get(0).toString() ); } } @@ -819,11 +820,11 @@ public class MethodEntry // -------------------------- OTHER METHODS -------------------------- public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) { - DefaultMutableTreeNode node = new RearrangerTreeNode(this, name); + DefaultMutableTreeNode node = new RearrangerTreeNode(this, myName); parent.add(node); ListIterator li; for (MethodEntry methodEntry : sortedMethods) { - if (methodEntry.isSetter() && methodEntry.calledByMethods.size() > 0) { + if (methodEntry.isSetter() && methodEntry.myCalledByMethods.size() > 0) { // setters are arranged with getters when "keep getters/setters together" option is checked. // but setters are not really called by getters. So attach them to the upper level. methodEntry.addToPopupTree(parent, settings); @@ -832,7 +833,7 @@ public class MethodEntry methodEntry.addToPopupTree(node, settings); } } - for (MethodEntry methodEntry : overloadedMethods) { + for (MethodEntry methodEntry : myOverloadedMethods) { methodEntry.addToPopupTree(node, settings); } return node; @@ -850,15 +851,15 @@ public class MethodEntry String allMethodNames, int level) { - final String currentMethodName = ((PsiMethod)end).getName(); + final String currentMethodName = ((PsiMethod)myEnd).getName(); String[] callingNames = new String[allCallingMethods.size()]; for (int i = 0; i < allCallingMethods.size(); i++) { MethodEntry me = allCallingMethods.get(i); - callingNames[i] = ((PsiMethod)me.end).getName(); + callingNames[i] = ((PsiMethod)me.myEnd).getName(); } MethodEntry topLevel = this; - while (topLevel.calledByMethods.size() > 0) { - topLevel = (topLevel.calledByMethods.get(0)); + while (topLevel.myCalledByMethods.size() > 0) { + topLevel = (topLevel.myCalledByMethods.get(0)); } switch (rms.getCommentType()) { case RelatedMethodsSettings.COMMENT_TYPE_TOP_LEVEL: @@ -886,14 +887,14 @@ public class MethodEntry rms.getPrecedingComment(), currentMethodName, allMethodNames, - ((PsiMethod)topLevel.end).getName(), + ((PsiMethod)topLevel.myEnd).getName(), level ); customizedTrailingComment = expandComment( rms.getTrailingComment(), currentMethodName, allMethodNames, - ((PsiMethod)topLevel.end).getName(), + ((PsiMethod)topLevel.myEnd).getName(), level ); // recursively assign comments. @@ -929,7 +930,7 @@ public class MethodEntry rms.getPrecedingComment(), currentMethodName, allMethodNames, - ((PsiMethod)topLevel.end).getName(), + ((PsiMethod)topLevel.myEnd).getName(), level ); } @@ -954,7 +955,7 @@ public class MethodEntry rms.getPrecedingComment(), currentMethodName, allMethodNames, - ((PsiMethod)topLevel.end).getName(), + ((PsiMethod)topLevel.myEnd).getName(), level ); // recursively assign comments for each level. @@ -980,7 +981,7 @@ public class MethodEntry rms.getTrailingComment(), currentMethodName, allMethodNames, - ((PsiMethod)topLevel.end).getName(), + ((PsiMethod)topLevel.myEnd).getName(), level ); } @@ -1059,15 +1060,15 @@ public class MethodEntry * to only that text up to and including the open brace. Temporarily remove the rest of the text; append * it again after checking for comments. */ - int brace = alternateValue.indexOf('{'); + int brace = myAlternateValue.indexOf('{'); String temp = ""; if (brace >= 0) { // every method should have an open brace -- unless it is abstract. - temp = alternateValue.substring(brace + 1, alternateValue.length()); - alternateValue = alternateValue.substring(0, brace + 1); + temp = myAlternateValue.substring(brace + 1, myAlternateValue.length()); + myAlternateValue = myAlternateValue.substring(0, brace + 1); } super.checkForComment(); - alternateValue += temp; + myAlternateValue += temp; } /** @@ -1085,7 +1086,7 @@ public class MethodEntry /** * recursively walk the method's code block looking for method calls. */ - final PsiMethod thisMethod = (PsiMethod)end; + final PsiMethod thisMethod = (PsiMethod)myEnd; final MethodEntry thisMethodEntry = this; JavaRecursiveElementVisitor rev = new JavaRecursiveElementVisitor() { @@ -1095,11 +1096,11 @@ public class MethodEntry /** * if the called method is already in our list, don't add it again. */ - if (c != null && !calledMethods.contains(c)) { + if (c != null && !myCalledMethods.contains(c)) { for (ClassContentsEntry o : possibleMethods) { - if (o instanceof IRelatableEntry) { + if (o instanceof RelatableEntry) { MethodEntry me = (MethodEntry)o; - PsiMethod m = (PsiMethod)me.end; + PsiMethod m = (PsiMethod)me.myEnd; if (c == m) { if (settings.isKeepOverloadedMethodsTogether() && m.getName().equals(thisMethod.getName())) @@ -1108,8 +1109,8 @@ public class MethodEntry } else { LOG.debug("method " + thisMethod.toString() + " calls " + m.toString()); - calledMethods.add(me); - me.calledByMethods.add(thisMethodEntry); + myCalledMethods.add(me); + me.myCalledByMethods.add(thisMethodEntry); } break; } @@ -1138,40 +1139,40 @@ public class MethodEntry { return; } - final PsiMethod thisMethod = (PsiMethod)end; + final PsiMethod thisMethod = (PsiMethod)myEnd; String thisProperty = MethodUtil.getPropertyName(thisMethod); - if (isGetter() && !keptWithProperty) { + if (isGetter() && !myKeptWithProperty) { if (settings.isKeepGettersSettersWithProperty()) { hookGetterToProperty(possibleMethods); } } for (ClassContentsEntry o : possibleMethods) { - if (o instanceof IRelatableEntry) { + if (o instanceof RelatableEntry) { MethodEntry me = (MethodEntry)o; // don't use a setter twice (could be two methods which both look like getters; assign the setter // to only one of them.) Also, associate all getter/setter methods for the same property with the // first one encountered. if ((me.isSetter() || me.isGetter()) && - me.correspondingGetterSetters.size() == 0 && + me.myCorrespondingGetterSetters.size() == 0 && me != this) { - PsiMethod m = (PsiMethod)me.end; + PsiMethod m = (PsiMethod)me.myEnd; String otherProperty = MethodUtil.getPropertyName(m); if (thisProperty.equals(otherProperty)) { LOG.debug("method " + thisMethod.toString() + " is getter; its setter is " + m.toString()); // place getters ahead of setters if (me.isGetter()) { - correspondingGetterSetters.add(0, me); + myCorrespondingGetterSetters.add(0, me); // clear the getter flag and set the setter flag; this causes the method to be emitted // under the first getter encountered. me.setGetter(false); me.setSetter(true); } else { - correspondingGetterSetters.add(me); + myCorrespondingGetterSetters.add(me); } - me.correspondingGetterSetters.add(this); + me.myCorrespondingGetterSetters.add(this); } } } @@ -1186,7 +1187,7 @@ public class MethodEntry */ private void hookGetterToProperty(List entries) { ListIterator li = entries.listIterator(); - String property = MethodUtil.getPropertyName((PsiMethod)end); + String property = MethodUtil.getPropertyName((PsiMethod)myEnd); while (li.hasNext()) { Object o = li.next(); if (o instanceof FieldEntry) { @@ -1195,7 +1196,7 @@ public class MethodEntry sb.setCharAt(0, Character.toUpperCase(sb.charAt(0))); if (fe.getGetterMethod() == null && property.equals(sb.toString())) { fe.setGetterMethod(this); - keptWithProperty = true; + myKeptWithProperty = true; break; } } @@ -1203,7 +1204,7 @@ public class MethodEntry } public void emit(Emitter emitter) { - StringBuffer sb = emitter.getStringBuffer(); + StringBuilder sb = emitter.getTextBuffer(); if (getCustomizedPrecedingComment().length() > 0) { sb.append("\n"); sb.append(getCustomizedPrecedingComment()); @@ -1218,11 +1219,11 @@ public class MethodEntry */ ListIterator li; if (isGetter()) { - for (MethodEntry entry : correspondingGetterSetters) { + for (MethodEntry entry : myCorrespondingGetterSetters) { entry.emit(emitter); } } - for (MethodEntry me : overloadedMethods) { + for (MethodEntry me : myOverloadedMethods) { me.emit(emitter); } for (MethodEntry me : sortedMethods) { @@ -1230,17 +1231,17 @@ public class MethodEntry } } - protected void emitAllElements(StringBuffer sb, Document document) { - if (alternateValue != null) { + protected void emitAllElements(StringBuilder sb, Document document) { + if (myAlternateValue != null) { /** * protect body of method from removing newlines. */ - int brace = alternateValue.indexOf('{'); + int brace = myAlternateValue.indexOf('{'); String temp = ""; if (brace >= 0) { // every method should have an open brace -- unless it is abstract. - temp = alternateValue.substring(brace + 1, alternateValue.length()); - alternateValue = alternateValue.substring(0, brace + 1); + temp = myAlternateValue.substring(brace + 1, myAlternateValue.length()); + myAlternateValue = myAlternateValue.substring(0, brace + 1); } super.emitAllElements(sb, document); sb.append(temp); @@ -1253,8 +1254,8 @@ public class MethodEntry public void insertInterfaceOrder(List list) { Comparator comparator = new Comparator() { public int compare(MethodEntry o1, MethodEntry o2) { - final int offset1 = getMethodOffsetInInterface((PsiMethod)o1.end); - final int offset2 = getMethodOffsetInInterface((PsiMethod)o2.end); + final int offset1 = getMethodOffsetInInterface((PsiMethod)o1.myEnd); + final int offset2 = getMethodOffsetInInterface((PsiMethod)o2.myEnd); if (offset1 < offset2) return -1; if (offset1 == offset2) return 0; return 1; @@ -1263,7 +1264,7 @@ public class MethodEntry insertInList(list, comparator); } - private int getMethodOffsetInInterface(PsiMethod method) { + private static int getMethodOffsetInInterface(PsiMethod method) { final PsiMethod[] superMethods = method.findSuperMethods(); // final PsiMethod[] superMethods = PsiSuperMethodUtil.findSuperMethods(method); // todo - for IDEA 5.0 if (superMethods.length == 0) return 0; @@ -1277,11 +1278,11 @@ public class MethodEntry public String toString() { return "MethodEntry " + - end.toString() + + myEnd.toString() + "; calls " + - calledMethods.size() + + myCalledMethods.size() + ", called by " + - calledByMethods.size() + + myCalledByMethods.size() + ", nParameters=" + nParameters; } } diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/MiscellaneousTextEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/MiscellaneousTextEntry.java index 4d3da310a052..be17b09ebe30 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/MiscellaneousTextEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/MiscellaneousTextEntry.java @@ -23,13 +23,13 @@ package com.wrq.rearranger.entry; import com.intellij.psi.PsiElement; import com.wrq.rearranger.settings.RearrangerSettings; +import org.jetbrains.annotations.Nullable; import javax.swing.*; /** Corresponds to comments and whitespace that surround Java syntactic items like classes and methods. */ -public class MiscellaneousTextEntry - extends ClassContentsEntry -{ +public class MiscellaneousTextEntry extends ClassContentsEntry { + public MiscellaneousTextEntry(final PsiElement start, final PsiElement end, final boolean fixedHeader, @@ -38,6 +38,7 @@ public class MiscellaneousTextEntry super(start, end, fixedHeader, fixedTrailer); } + @Nullable public String getTypeIconName() { // do not show headers and trailers in the file structure popup. return null; @@ -47,6 +48,7 @@ public class MiscellaneousTextEntry return null; } + @Nullable public JLabel getPopupEntryText(RearrangerSettings settings) { return null; } @@ -59,7 +61,7 @@ public class MiscellaneousTextEntry else { result = "Trailer"; } - if (alternateValue != null) { + if (myAlternateValue != null) { result += "; comments removed"; } return result; diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/IPopupTreeRangeEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/PopupTreeRangeEntry.java similarity index 93% rename from plugins/rearranger/src/com/wrq/rearranger/entry/IPopupTreeRangeEntry.java rename to plugins/rearranger/src/com/wrq/rearranger/entry/PopupTreeRangeEntry.java index eb4e7636443f..ac6af64d28c3 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/IPopupTreeRangeEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/PopupTreeRangeEntry.java @@ -26,13 +26,11 @@ import com.wrq.rearranger.settings.RearrangerSettings; import javax.swing.tree.DefaultMutableTreeNode; /** - * Created by IntelliJ IDEA. * User: davek * Date: Feb 18, 2004 * Time: 9:17:56 AM - * To change this template use File | Settings | File Templates. */ -public interface IPopupTreeRangeEntry { +public interface PopupTreeRangeEntry { /** * Gives individual entries control over their appearance, depending on settings. diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/PsiFileEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/PsiFileEntry.java index 11ac5ba48afe..b6264f1cf68e 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/PsiFileEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/PsiFileEntry.java @@ -27,6 +27,7 @@ import com.intellij.psi.PsiComment; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiWhiteSpace; import com.wrq.rearranger.settings.RearrangerSettings; +import org.jetbrains.annotations.NotNull; import java.util.List; @@ -36,27 +37,24 @@ import java.util.List; * members, and trailing text, we can create a dummy "class" which will parse the file. Header text * will include the package and import statements, and outer classes will be its members. */ -public class PsiFileEntry - extends ClassEntry -{ - public PsiFileEntry(RearrangerSettings settings) { +public class PsiFileEntry extends ClassEntry { + + public PsiFileEntry(@NotNull RearrangerSettings settings) { super(null, null, 0, "", null, 0, settings); } /** - * Strip off leading elements which do not belong to the first class, and place them in + * Strips off leading elements which do not belong to the first class, and place them in * a MiscellaneousText entry. * + * * @param project * @param psiFile - * @param commentList * @return */ - public List parseFile(Project project, - PsiElement psiFile, - List commentList) - { + public List parseFile(Project project, PsiElement psiFile) { int startingIndex = 0; + // TODO den re-write to the 'firstChild & nextSibling' for (int i = 0; i < psiFile.getChildren().length; i++) { PsiElement child = psiFile.getChildren()[i]; if (child instanceof PsiClass) { @@ -86,8 +84,8 @@ public class PsiFileEntry } parseRemainingClassContents(project, startingIndex, psiFile); if (miscellaneousTextEntry != null) { - contents.add(0, miscellaneousTextEntry); + myContents.add(0, miscellaneousTextEntry); } - return contents; + return myContents; } } diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/RangeEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/RangeEntry.java index 96fd5a97102c..55dd4fa91665 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/RangeEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/RangeEntry.java @@ -23,12 +23,15 @@ package com.wrq.rearranger.entry; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.wrq.rearranger.popup.RearrangerTreeNode; import com.wrq.rearranger.rearrangement.Emitter; import com.wrq.rearranger.ruleinstance.RuleInstance; import com.wrq.rearranger.settings.RearrangerSettings; import com.wrq.rearranger.util.CommentUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.tree.DefaultMutableTreeNode; import java.util.regex.Matcher; @@ -38,66 +41,67 @@ import java.util.regex.Matcher; * contains start and end Psi elements for each item (which could be identical), as well as modifier * flags and special flags to mark any miscellaneous text or comments that precede or follow the item. */ -abstract public class RangeEntry implements IPopupTreeRangeEntry { +abstract public class RangeEntry implements PopupTreeRangeEntry { // ------------------------------ FIELDS ------------------------------ private static final Logger LOG = Logger.getInstance("#" + RangeEntry.class.getName()); - String alternateValue; - final String name; - protected final PsiElement start; - protected final PsiElement end; - private final int modifiers; - private final String modifierString; - private final boolean fixedHeader; - private final boolean fixedTrailer; - private final String type; - private RuleInstance myMatchedRule; - private boolean separatorCommentPrecedes; + + String myAlternateValue; + final String myName; + protected final PsiElement myStart; + protected final PsiElement myEnd; + private final int myModifiers; + private final String myModifierString; + private final boolean myFixedHeader; + private final boolean myFixedTrailer; + private final String myType; + private RuleInstance myMatchedRule; + private boolean mySeparatorCommentPrecedes; // --------------------------- CONSTRUCTORS --------------------------- - public RangeEntry(final PsiElement start, - final PsiElement end, + public RangeEntry(@Nullable final PsiElement start, + @Nullable final PsiElement end, final boolean fixedHeader, final boolean fixedTrailer) { this(start, end, 0, "", "", "", fixedHeader, fixedTrailer); } - RangeEntry(final PsiElement start, - final PsiElement end, + RangeEntry(@Nullable final PsiElement start, + @Nullable final PsiElement end, final int modifiers, final String modifierString, - final String name, + @Nullable final String name, final String type) { this(start, end, modifiers, modifierString, name, type, false, false); } - private RangeEntry(final PsiElement start, - final PsiElement end, + private RangeEntry(@Nullable final PsiElement start, + @Nullable final PsiElement end, final int modifiers, final String modifierString, - final String name, + @Nullable final String name, final String type, final boolean fixedHeader, final boolean fixedTrailer) { - this.start = start; - this.end = end; - this.modifiers = modifiers; - this.modifierString = modifierString; - this.fixedHeader = fixedHeader; - this.fixedTrailer = fixedTrailer; - this.name = name; - this.type = type; - alternateValue = null; + myStart = start; + myEnd = end; + myModifiers = modifiers; + myModifierString = modifierString; + myFixedHeader = fixedHeader; + myFixedTrailer = fixedTrailer; + myName = name; + myType = type; + myAlternateValue = null; } // --------------------- GETTER / SETTER METHODS --------------------- public PsiElement getEnd() { - return end; + return myEnd; } public RuleInstance getMatchedRule() { @@ -109,59 +113,59 @@ abstract public class RangeEntry implements IPopupTreeRangeEntry { } public int getModifiers() { - return modifiers; + return myModifiers; } public String getModifierString() { - return modifierString; + return myModifierString; } public String getName() { - return name; + return myName; } public String getType() { - return type; + return myType; } public PsiElement getStart() { - return start; + return myStart; } public boolean isFixedHeader() { - return fixedHeader; + return myFixedHeader; } public boolean isFixedTrailer() { - return fixedTrailer; + return myFixedTrailer; } // ------------------------ CANONICAL METHODS ------------------------ public String toString() { - String result = (name == null ? "" : name); - if (start != null && end != null) { + String result = (myName == null ? "" : myName); + if (myStart != null && myEnd != null) { result += "; range from " + - start.toString() + + myStart.toString() + " [" + - start.getTextRange().getStartOffset() + + myStart.getTextRange().getStartOffset() + "] to " + - end.toString() + + myEnd.toString() + " [" + - end.getTextRange().getEndOffset() + + myEnd.getTextRange().getEndOffset() + "]; modifiers=0x" + - Integer.toHexString(modifiers); + Integer.toHexString(myModifiers); } else { result += "; no start/end specified"; } - if (fixedHeader) { + if (myFixedHeader) { result = "Header: " + result; } - if (fixedTrailer) { + if (myFixedTrailer) { result = "Trailer: " + result; } - if (alternateValue != null) { + if (myAlternateValue != null) { result += "; comments removed"; } return result; @@ -173,7 +177,7 @@ abstract public class RangeEntry implements IPopupTreeRangeEntry { // --------------------- Interface IPopupTreeRangeEntry --------------------- public DefaultMutableTreeNode addToPopupTree(DefaultMutableTreeNode parent, RearrangerSettings settings) { - DefaultMutableTreeNode myNode = new RearrangerTreeNode(this, name); + DefaultMutableTreeNode myNode = new RearrangerTreeNode(this, myName); parent.add(myNode); return myNode; } @@ -189,40 +193,37 @@ abstract public class RangeEntry implements IPopupTreeRangeEntry { * for each separator comment specified by the user, check to see if this comment matches. */ for (Matcher matcher : CommentUtil.getCommentMatchers()) { - matcher.reset(alternateValue); + matcher.reset(myAlternateValue); boolean foundMatch = matcher.find(); if (foundMatch) { LOG.debug("found comment pattern '" + matcher.pattern().pattern().replaceAll("\n", "#") + "' in '" + - alternateValue.replaceAll("\n", "#") + + myAlternateValue.replaceAll("\n", "#") + "'"); - StringBuffer sb = new StringBuffer(alternateValue.length()); + StringBuffer sb = new StringBuffer(myAlternateValue.length()); do { - boolean leadingNewlines = start.getTextRange().getStartOffset() > 0; + boolean leadingNewlines = myStart.getTextRange().getStartOffset() > 0; matcher.appendReplacement(sb, leadingNewlines ? "\n" : ""); foundMatch = matcher.find(); } while (foundMatch); matcher.appendTail(sb); - alternateValue = sb.toString(); - LOG.debug("RangeEntry alternateValue=" + alternateValue.replaceAll("\n", "#")); + myAlternateValue = sb.toString(); + LOG.debug("RangeEntry alternateValue=" + myAlternateValue.replaceAll("\n", "#")); } } } protected void createAlternateValueString() { - if (alternateValue != null) { + if (myAlternateValue != null) { return; } - final StringBuffer sb = new StringBuffer( - end.getTextRange().getEndOffset() - - start.getTextRange().getStartOffset() - ); - PsiElement e = start; - while (e != null && e != end) { - if (e == end.getParent()) { + final StringBuilder sb = new StringBuilder(myEnd.getTextRange().getEndOffset() - myStart.getTextRange().getStartOffset()); + PsiElement e = myStart; + while (e != null && e != myEnd) { + if (e == myEnd.getParent()) { e = e.getFirstChild(); } else { @@ -230,58 +231,52 @@ abstract public class RangeEntry implements IPopupTreeRangeEntry { e = e.getNextSibling(); } } - if (e == end) { - sb.append(end.getText()); + if (e == myEnd) { + sb.append(myEnd.getText()); } - alternateValue = sb.toString(); + myAlternateValue = sb.toString(); } public void emit(Emitter emitter) { - emitAllElements(emitter.getStringBuffer(), emitter.getDocument()); + emitAllElements(emitter.getTextBuffer(), emitter.getDocument()); } - protected void emitAllElements(StringBuffer sb, Document document) { - if (alternateValue != null) { - String result = alternateValue; - if (separatorCommentPrecedes) { + protected void emitAllElements(StringBuilder buffer, Document document) { + if (myAlternateValue != null) { + String result = myAlternateValue; + if (mySeparatorCommentPrecedes) { // remove all leading blank lines. The only blank lines we want are the ones explicitly appended // to the preceding separator comment. LOG.debug("emitAllElements: separator comment precedes " + - name + "; original value=" + - alternateValue.replaceAll("\n", "#")); - result = alternateValue.replaceFirst("\n[ \t\n]*\n", "\n"); + myName + "; original value=" + + myAlternateValue.replaceAll("\n", "#")); + result = myAlternateValue.replaceFirst("\n[ \t\n]*\n", "\n"); LOG.debug("emitAllElements: resulting value=" + - alternateValue.replaceAll("\n", "#")); + myAlternateValue.replaceAll("\n", "#")); } - sb.append(result); + buffer.append(result); } else { - PsiElement curr = start; - while (curr != null && curr != end) { - if (curr == end.getParent()) { + PsiElement curr = myStart; + while (curr != null && curr != myEnd) { + if (curr == myEnd.getParent()) { curr = curr.getFirstChild(); } else { - emitElement(curr, sb, document); + emitElement(curr, buffer, document); curr = curr.getNextSibling(); } } - if (curr == end) { - emitElement(end, sb, document); + if (curr == myEnd) { + emitElement(myEnd, buffer, document); } } } - private void emitElement(final PsiElement curr, - final StringBuffer sb, - final Document document) - { + private static void emitElement(@NotNull final PsiElement curr, @NotNull final StringBuilder sb, @NotNull final Document document) { + final TextRange range = curr.getTextRange(); try { - sb.append( - document.getCharsSequence().toString().toCharArray(), // for Irida (builds 3185 etc). - curr.getTextRange().getStartOffset(), - curr.getTextRange().getEndOffset() - curr.getTextRange().getStartOffset() - ); + sb.append(document.getCharsSequence(), range.getStartOffset(), range.getEndOffset()); } catch (ArrayIndexOutOfBoundsException oob) { LOG.error("internal error attempting to append text to document"); @@ -290,17 +285,17 @@ abstract public class RangeEntry implements IPopupTreeRangeEntry { LOG.error("document...toCharArray.length=" + document.getCharsSequence().toString().toCharArray().length); LOG.error("current PSI element=" + curr.toString()); LOG.error("current PSI element text=" + curr.getText()); - LOG.error("current PSI element text range, start offset=" + curr.getTextRange().getStartOffset()); - LOG.error("current PSI element text range, end offset=" + curr.getTextRange().getEndOffset()); - LOG.error("current PSI element text range, length=" + curr.getTextRange().getLength()); + LOG.error("current PSI element text range, start offset=" + range.getStartOffset()); + LOG.error("current PSI element text range, end offset=" + range.getEndOffset()); + LOG.error("current PSI element text range, length=" + range.getLength()); LOG.error(oob); throw oob; } } public void setSeparatorCommentPrecedes(boolean precedes) { - this.separatorCommentPrecedes = precedes; - LOG.debug("emitAllElements: set separator comment precedes " + name); + this.mySeparatorCommentPrecedes = precedes; + LOG.debug("emitAllElements: set separator comment precedes " + myName); } } diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/IRelatableEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/RelatableEntry.java similarity index 98% rename from plugins/rearranger/src/com/wrq/rearranger/entry/IRelatableEntry.java rename to plugins/rearranger/src/com/wrq/rearranger/entry/RelatableEntry.java index 317360a1a093..1b893f6197d4 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/IRelatableEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/RelatableEntry.java @@ -30,7 +30,7 @@ import java.util.List; * Defines methods implemented by entries which may be related to others, i.e. getters and setters, * method entries which call other methods, and overloaded method entries. */ -public interface IRelatableEntry { +public interface RelatableEntry { /** * Determine if the entry is a getter/setter or is excluded from extracted method consideration by an * overriding rule. diff --git a/plugins/rearranger/src/com/wrq/rearranger/popup/FilePopupEntry.java b/plugins/rearranger/src/com/wrq/rearranger/popup/FilePopupEntry.java index b1fbb6dd6229..4df540539a80 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/popup/FilePopupEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/popup/FilePopupEntry.java @@ -29,6 +29,7 @@ import javax.swing.*; /** Interface implemented by objects which can appear as entries in the file structure popup. */ public interface FilePopupEntry { /** @return the name of the icon representing the popup entry's type of Java object (method, class, etc.) */ + @Nullable String getTypeIconName(); /** @@ -39,5 +40,6 @@ public interface FilePopupEntry { String[] getAdditionalIconNames(); /** @return a JLabel containing the text of the popup tree entry. */ + @Nullable JLabel getPopupEntryText(RearrangerSettings settings); } diff --git a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Emitter.java b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Emitter.java index 6e6b7ddba87c..77287d0d9a13 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Emitter.java +++ b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Emitter.java @@ -24,41 +24,48 @@ package com.wrq.rearranger.rearrangement; import com.intellij.openapi.editor.Document; import com.intellij.psi.PsiFile; import com.wrq.rearranger.ruleinstance.RuleInstance; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; import java.util.List; /** Emits a new document from the rearranged entries. */ public final class Emitter { - private final PsiFile psiFile; - private final List myResultRuleInstances; - private final Document document; - private StringBuffer stringBuffer; - public Emitter(final PsiFile psiFile, final List resultRuleInstances, final Document document) { - this.psiFile = psiFile; - this.myResultRuleInstances = resultRuleInstances; - this.document = document; - stringBuffer = new StringBuffer(psiFile.getText().length() + 100); // room for inserted blank lines + @NotNull private final StringBuilder myStringBuffer = new StringBuilder(); + @NotNull private final List myResultRuleInstances = new ArrayList(); + + @NotNull private final PsiFile myFile; + @NotNull private final Document myDocument; + + public Emitter(@NotNull final PsiFile file, @NotNull final List resultRuleInstances, @NotNull final Document document) { + myFile = file; + myResultRuleInstances.addAll(resultRuleInstances); + myDocument = document; + myStringBuffer.ensureCapacity(myFile.getText().length() + 100 /* room for inserted blank lines */); } + @NotNull public Document getDocument() { - return document; + return myDocument; } - public StringBuffer getStringBuffer() { - return stringBuffer; + @NotNull + public StringBuilder getTextBuffer() { + return myStringBuffer; } public void emitRearrangedDocument() { emitRuleInstances(myResultRuleInstances); - document.replaceString( - psiFile.getTextRange().getStartOffset(), - psiFile.getTextRange().getEndOffset(), - stringBuffer.toString() + myDocument.replaceString( + myFile.getTextRange().getStartOffset(), + myFile.getTextRange().getEndOffset(), + myStringBuffer.toString() ); } - public void emitRuleInstances(List resultRuleInstances) { + public void emitRuleInstances(@Nullable List resultRuleInstances) { if (resultRuleInstances == null) { return; } diff --git a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/GenericRearranger.java b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/GenericRearranger.java index fb1232ee1650..34d7d42ee334 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/GenericRearranger.java +++ b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/GenericRearranger.java @@ -24,7 +24,7 @@ package com.wrq.rearranger.rearrangement; import com.intellij.openapi.diagnostic.Logger; import com.wrq.rearranger.entry.ClassContentsEntry; import com.wrq.rearranger.entry.ClassEntry; -import com.wrq.rearranger.entry.IRelatableEntry; +import com.wrq.rearranger.entry.RelatableEntry; import com.wrq.rearranger.entry.RangeEntry; import com.wrq.rearranger.ruleinstance.CommentRuleInstance; import com.wrq.rearranger.ruleinstance.RuleInstance; @@ -37,23 +37,24 @@ import java.util.ListIterator; /** Template for generic rearrangement of items in a class or in a Java file. */ public abstract class GenericRearranger { + private static final Logger LOG = Logger.getInstance("#" + GenericRearranger.class.getName()); - private final List rules; - private final List entries; - private final List myResultRuleInstances; - private final int nestingLevel; - private final RearrangerSettings settings; + + private final List myRules; + private final List myEntries; + private final List myResultRuleInstances; + private final int myNestingLevel; + private final RearrangerSettings mySettings; @SuppressWarnings({"AssignmentToCollectionOrArrayFieldFromParameter"}) protected GenericRearranger(final List rules, final List outerClasses, final int nestingLevel, - final RearrangerSettings settings) - { - this.rules = rules; - entries = outerClasses; - this.nestingLevel = nestingLevel; - this.settings = settings; + final RearrangerSettings settings) { + this.myRules = rules; + myEntries = outerClasses; + this.myNestingLevel = nestingLevel; + this.mySettings = settings; myResultRuleInstances = new ArrayList(rules.size() + 4); } @@ -66,27 +67,23 @@ public abstract class GenericRearranger { public final List rearrangeEntries() { final List prioritizedRuleInstances = new ArrayList(); buildRuleInstanceLists(prioritizedRuleInstances); - /** - * recursively reorder contents of every nested ClassEntry. - */ - for (ClassContentsEntry entry : entries) { + + // Recursively reorder contents of every nested ClassEntry + for (ClassContentsEntry entry : myEntries) { if (entry instanceof ClassEntry) { ((ClassEntry)entry).rearrangeContents(); } } matchPrioritizedRules(prioritizedRuleInstances); - /** - * Move related methods together. Extracted methods and setters (emitted with getters) - * were not moved by the rearrangement code ("MatchPrioritizedRules()") just above. - */ - rearrangeRelatedItems(entries, myResultRuleInstances); - /** - * Now go back and determine which comments are going to be emitted, based on their criteria and the - * state of the immediately surrounding rules. Ignore inner classes if no rearrangement of inner - * classes is taking place. - */ - if (nestingLevel <= 1 || settings.isRearrangeInnerClasses()) { + // Move related methods together. Extracted methods and setters (emitted with getters) + // were not moved by the rearrangement code ("MatchPrioritizedRules()") just above. + rearrangeRelatedItems(myEntries, myResultRuleInstances); + + // Now go back and determine which comments are going to be emitted, based on their criteria and the + // state of the immediately surrounding rules. Ignore inner classes if no rearrangement of inner + // classes is taking place. + if (myNestingLevel <= 1 || mySettings.isRearrangeInnerClasses()) { determineEmittedComments(); } return myResultRuleInstances; @@ -103,7 +100,9 @@ public abstract class GenericRearranger { for (int j = i + 1; j < myResultRuleInstances.size(); j++) { RuleInstance instance = myResultRuleInstances.get(j); if (instance.hasMatches()) { - RangeEntry entry = (instance.getMatches().get(0)); + final List matches = instance.getMatches(); + assert matches != null; + RangeEntry entry = (matches.get(0)); entry.setSeparatorCommentPrecedes(true); break; } @@ -125,14 +124,14 @@ public abstract class GenericRearranger { private void matchPrioritizedRules(List prioritizedRules) { for (RuleInstance ruleInstance : prioritizedRules) { final Rule rule = ruleInstance.getRule(); - final ListIterator entryIterator = entries.listIterator(); + final ListIterator entryIterator = myEntries.listIterator(); while (entryIterator.hasNext()) { final RangeEntry entry = (RangeEntry)entryIterator.next(); - if (entry instanceof IRelatableEntry) { + if (entry instanceof RelatableEntry) { // if this is an extracted (i.e. related) method, or // if this is a setter that will be emitted under the corresponding getter, // don't test it for match against the rule. - final IRelatableEntry relatableEntry = ((IRelatableEntry)entry); + final RelatableEntry relatableEntry = ((RelatableEntry)entry); if (relatableEntry.isRelatedMethod() || relatableEntry.isEmittableSetter()) { continue; } @@ -154,18 +153,14 @@ public abstract class GenericRearranger { * @param prioritizedRuleInstances */ private void buildRuleInstanceLists(final List prioritizedRuleInstances) { - /** - * add a HeaderTrailerRuleInstance to pick up any headers that might exist. - */ + // Add a HeaderTrailerRuleInstance to pick up any headers that might exist. RuleInstance hri = new HeaderRule().createRuleInstance(); myResultRuleInstances.add(hri); prioritizedRuleInstances.add(hri); - for (Rule rule : rules) { + for (Rule rule : myRules) { RuleInstance instance = rule.createRuleInstance(); myResultRuleInstances.add(instance); - /** - * now insert the rule instance into the prioritized list; highest priority first; stable insertion. - */ + // Now insert the rule instance into the prioritized list; highest priority first; stable insertion. boolean inserted = false; for (int i = prioritizedRuleInstances.size() - 1; i >= 0; i--) { RuleInstance entry = (prioritizedRuleInstances.get(i)); @@ -196,7 +191,6 @@ public abstract class GenericRearranger { * @param entries * @param rearrangedEntries */ - public abstract void rearrangeRelatedItems(List entries, - List rearrangedEntries); + public abstract void rearrangeRelatedItems(List entries, List rearrangedEntries); } diff --git a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Mover.java b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Mover.java index 97c77425d617..89b4b6f1e1c4 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Mover.java +++ b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Mover.java @@ -30,22 +30,21 @@ import java.util.List; /** Moves (rearranges) classes and class members according to rules specified by the user. */ public final class Mover { - private final List outerClasses; - private final RearrangerSettings settings; - public Mover(final List outerClasses, - final RearrangerSettings settings) - { - this.outerClasses = new ArrayList(outerClasses); - this.settings = settings; + private final List myOuterClasses = new ArrayList(); + private final RearrangerSettings mySettings; + + public Mover(final List outerClasses, final RearrangerSettings settings) { + myOuterClasses.addAll(outerClasses); + mySettings = settings; } public List rearrangeOuterClasses() { final GenericRearranger outerClassRearranger = new GenericRearranger( - settings.getClassOrderAttributeList(), - outerClasses, + mySettings.getClassOrderAttributeList(), + myOuterClasses, 0, - settings) + mySettings) { /** * There are no items related to outer classes -- outer classes are completely disjoint @@ -55,9 +54,7 @@ public final class Mover { @param rearrangedEntries */ - public void rearrangeRelatedItems(List entries, - List rearrangedEntries) - { + public void rearrangeRelatedItems(List entries, List rearrangedEntries) { } }; diff --git a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Parser.java b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Parser.java index 53033b2d264f..6f4f5badea06 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Parser.java +++ b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Parser.java @@ -29,34 +29,36 @@ import com.wrq.rearranger.entry.ClassEntry; import com.wrq.rearranger.entry.PsiFileEntry; import com.wrq.rearranger.entry.RangeEntry; import com.wrq.rearranger.settings.RearrangerSettings; +import org.jetbrains.annotations.NotNull; import java.util.List; /** Creates a list of entries for classes and class members by parsing the Java file. */ public final class Parser { - private static final Logger LOG = Logger.getInstance("#" + Parser.class.getName()); - private final Project project; - private final RearrangerSettings settings; - private final PsiFile psiFile; - public Parser(final Project project, - final RearrangerSettings settings, - final PsiFile psiFile) - { - this.project = project; - this.settings = settings; - this.psiFile = psiFile; + private static final Logger LOG = Logger.getInstance("#" + Parser.class.getName()); + + private final Project myProject; + private final RearrangerSettings mySettings; + private final PsiFile myPsiFile; + + public Parser(final @NotNull Project project, final @NotNull RearrangerSettings settings, final @NotNull PsiFile psiFile) { + myProject = project; + mySettings = settings; + myPsiFile = psiFile; } + @NotNull public List parseOuterLevel() { /** * Parse the top level contents of the PsiFile here. */ - PsiFileEntry fileEntry = new PsiFileEntry(settings); - return fileEntry.parseFile(project, psiFile, settings.getClassOrderAttributeList()); + PsiFileEntry fileEntry = new PsiFileEntry(mySettings); + return fileEntry.parseFile(myProject, myPsiFile); } - private void dumpOuterClasses(final List outerClasses) { + @SuppressWarnings("UnusedDeclaration") + private static void dumpOuterClasses(final List outerClasses) { LOG.debug("Outer class entries:"); for (ClassEntry classEntry : outerClasses) { LOG.debug(classEntry.toString()); diff --git a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Spacer.java b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Spacer.java index 0158aff9e423..ad04c62930f6 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Spacer.java +++ b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Spacer.java @@ -23,7 +23,6 @@ package com.wrq.rearranger.rearrangement; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; -import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.wrq.rearranger.settings.ForceBlankLineSetting; import com.wrq.rearranger.settings.RearrangerSettings; @@ -34,24 +33,22 @@ import java.util.Map; /** Responsible for adjusting the number of blank lines at strategic places in the source file. */ public class Spacer { + private static final Logger LOG = Logger.getInstance("#" + Spacer.class.getName()); - private final Project project; - private final PsiFile psiFile; - private final Document document; - private final PsiElementFactory factory; - private final RearrangerSettings settings; - private final char[] newlineChars; - private boolean changesMade; - private StringBuffer sb; + + private final PsiFile myFile; + private final Document myDocument; + private final RearrangerSettings mySettings; + private final char[] myNewlineChars; + private boolean myChangesMade; + private StringBuilder myBuffer; private Map virtualElements = new HashMap(); - public Spacer(Project project, PsiFile psiFile, Document document, RearrangerSettings settings) { - this.project = project; - this.psiFile = psiFile; - this.document = document; - this.settings = settings; - changesMade = false; - factory = JavaPsiFacade.getInstance(project).getElementFactory(); + public Spacer(PsiFile psiFile, Document document, RearrangerSettings settings) { + myFile = psiFile; + myDocument = document; + mySettings = settings; + myChangesMade = false; int size = 0; size += settings.getAfterClassLBrace().getnBlankLines() + 1; size += settings.getBeforeMethodLBrace().getnBlankLines() + 1; @@ -61,9 +58,9 @@ public class Spacer { size += settings.getBeforeClassRBrace().getnBlankLines() + 1; size += settings.getAfterClassRBrace().getnBlankLines() + 1; LOG.debug("constructor allocating " + size + " newline chars for max insertion"); - newlineChars = new char[size]; + myNewlineChars = new char[size]; while (size > 0) { - newlineChars[--size] = '\n'; + myNewlineChars[--size] = '\n'; } LOG.debug(settings.getAfterClassLBrace().toString()); LOG.debug(settings.getBeforeMethodLBrace().toString()); @@ -74,7 +71,7 @@ public class Spacer { LOG.debug(settings.getAfterClassRBrace().toString()); final int ROOM_FOR_EXPANSION = 100; int maxSize = document.getTextLength() + ROOM_FOR_EXPANSION; - sb = new StringBuffer(maxSize); + myBuffer = new StringBuilder(maxSize); } private class AbortRespacing extends RuntimeException { @@ -86,7 +83,7 @@ public class Spacer { } } - private void handleBadPsiElementException(BadPsiElement bpe, String desc, PsiElement element) + private void handleBadPsiElementException(String desc, PsiElement element) throws AbortRespacing { JOptionPane.showMessageDialog(null, @@ -96,7 +93,7 @@ public class Spacer { } public boolean respace() { - sb.append(document.getText()); + myBuffer.append(myDocument.getText()); JavaElementVisitor visitor = new JavaRecursiveElementVisitor() { private int bias = 0; @@ -106,13 +103,13 @@ public class Spacer { public void visitFile(PsiFile psiFile) { super.visitFile(psiFile); - if (settings.getNewLinesAtEOF().isForce()) { + if (mySettings.getNewLinesAtEOF().isForce()) { // remove all newlines at end of file, then append as many as are declared in configuration. - while (sb.length() > 0 && sb.charAt(sb.length() - 1) == '\n') { - sb.setLength(sb.length() - 1); + while (myBuffer.length() > 0 && myBuffer.charAt(myBuffer.length() - 1) == '\n') { + myBuffer.setLength(myBuffer.length() - 1); } - for (int count = 0; count < settings.getNewLinesAtEOF().getnBlankLines(); count++) { - sb.append('\n'); + for (int count = 0; count < mySettings.getNewLinesAtEOF().getnBlankLines(); count++) { + myBuffer.append('\n'); } } } @@ -131,32 +128,28 @@ public class Spacer { bias += adjustSpacing( psiClass.getLBrace(), psiClass.getRBrace(), - settings.getAfterClassLBrace(), + mySettings.getAfterClassLBrace(), bias ); } catch (BadPsiElement badPsiElement) { - handleBadPsiElementException(badPsiElement, - "class " + psiClass.getName() + " missing left brace. Body follows:", - psiClass); + handleBadPsiElementException("class " + psiClass.getName() + " missing left brace. Body follows:", psiClass); } - log(settings.getAfterClassLBrace(), psiClass.getName(), oldbias, bias); + log(mySettings.getAfterClassLBrace(), psiClass.getName(), oldbias, bias); super.visitClass(psiClass); oldbias = bias; try { bias += adjustSpacing( psiClass.getRBrace(), psiClass.getLBrace(), - settings.getBeforeClassRBrace(), + mySettings.getBeforeClassRBrace(), bias ); } catch (BadPsiElement badPsiElement) { - handleBadPsiElementException(badPsiElement, - "class " + psiClass.getName() + " missing right brace. Body follows:", - psiClass); + handleBadPsiElementException("class " + psiClass.getName() + " missing right brace. Body follows:", psiClass); } - log(settings.getBeforeClassRBrace(), psiClass.getName(), oldbias, bias); + log(mySettings.getBeforeClassRBrace(), psiClass.getName(), oldbias, bias); if (anonymous) { return; @@ -176,16 +169,14 @@ public class Spacer { bias += adjustSpacing( psiClass.getRBrace(), psiClass.getLBrace(), - settings.getAfterClassRBrace(), + mySettings.getAfterClassRBrace(), bias ); } catch (BadPsiElement badPsiElement) { - handleBadPsiElementException(badPsiElement, - "class " + psiClass.getName() + " missing left brace. Body follows:", - psiClass); + handleBadPsiElementException("class " + psiClass.getName() + " missing left brace. Body follows:", psiClass); } - log(settings.getAfterClassRBrace(), psiClass.getName(), oldbias, bias); + log(mySettings.getAfterClassRBrace(), psiClass.getName(), oldbias, bias); } else { LOG.debug( @@ -230,38 +221,34 @@ public class Spacer { bias += adjustSpacing( psiMethod.getBody().getLBrace(), psiMethod.getBody().getRBrace(), - settings.getBeforeMethodLBrace(), + mySettings.getBeforeMethodLBrace(), bias ); bias += adjustSpacing( psiMethod.getBody().getLBrace(), psiMethod.getBody().getRBrace(), - settings.getAfterMethodLBrace(), + mySettings.getAfterMethodLBrace(), bias ); } catch (BadPsiElement badPsiElement) { - handleBadPsiElementException(badPsiElement, - "body of method " + psiMethod.getName() + " missing left brace. Body follows:", - psiMethod); + handleBadPsiElementException("body of method " + psiMethod.getName() + " missing left brace. Body follows:", psiMethod); } - log(settings.getAfterMethodLBrace(), psiMethod.getName(), oldbias, bias); + log(mySettings.getAfterMethodLBrace(), psiMethod.getName(), oldbias, bias); super.visitMethod(psiMethod); oldbias = bias; try { bias += adjustSpacing( psiMethod.getBody().getRBrace(), psiMethod.getBody().getLBrace(), - settings.getBeforeMethodRBrace(), + mySettings.getBeforeMethodRBrace(), bias ); } catch (BadPsiElement badPsiElement) { - handleBadPsiElementException(badPsiElement, - "body of method " + psiMethod.getName() + " missing right brace. Body follows:", - psiMethod); + handleBadPsiElementException("body of method " + psiMethod.getName() + " missing right brace. Body follows:", psiMethod); } - log(settings.getBeforeMethodRBrace(), psiMethod.getName(), oldbias, bias); + log(mySettings.getBeforeMethodRBrace(), psiMethod.getName(), oldbias, bias); } else { LOG.debug("method " + psiMethod.getName() + " is empty, no internal spacing changes"); @@ -285,16 +272,14 @@ public class Spacer { bias += adjustSpacing( psiMethod.getBody().getRBrace(), psiMethod.getBody().getLBrace(), - settings.getAfterMethodRBrace(), + mySettings.getAfterMethodRBrace(), bias ); } catch (BadPsiElement badPsiElement) { - handleBadPsiElementException(badPsiElement, - "body of method " + psiMethod.getName() + " missing right brace. Body follows:", - psiMethod); + handleBadPsiElementException("body of method " + psiMethod.getName() + " missing right brace. Body follows:", psiMethod); } - log(settings.getAfterMethodRBrace(), psiMethod.getName(), oldbias, bias); + log(mySettings.getAfterMethodRBrace(), psiMethod.getName(), oldbias, bias); } else { LOG.debug( @@ -308,7 +293,7 @@ public class Spacer { public void visitCodeBlock(PsiCodeBlock psiCodeBlock) { int oldbias; if (!(psiCodeBlock.getParent() instanceof PsiMethod) && - settings.isRemoveBlanksInsideCodeBlocks()) + mySettings.isRemoveBlanksInsideCodeBlocks()) { oldbias = bias; try { @@ -316,43 +301,41 @@ public class Spacer { psiCodeBlock.getRBrace(), false, 0, bias); } catch (BadPsiElement badPsiElement) { - handleBadPsiElementException(badPsiElement, - "code block missing left brace. Content follows:\n", psiCodeBlock); + handleBadPsiElementException("code block missing left brace. Content follows:\n", psiCodeBlock); } log("code block left brace", oldbias, bias); } super.visitCodeBlock(psiCodeBlock); if (!(psiCodeBlock.getParent() instanceof PsiMethod) && - settings.isRemoveBlanksInsideCodeBlocks()) + mySettings.isRemoveBlanksInsideCodeBlocks()) { oldbias = bias; try { bias += adjustSpacing(psiCodeBlock.getRBrace(), psiCodeBlock.getLBrace(), true, 0, bias); } catch (BadPsiElement badPsiElement) { - handleBadPsiElementException(badPsiElement, - "code block missing right brace. Content follows:\n", psiCodeBlock); + handleBadPsiElementException("code block missing right brace. Content follows:\n", psiCodeBlock); } log("code block right brace", oldbias, bias); } } }; try { - psiFile.accept(visitor); + myFile.accept(visitor); } catch (AbortRespacing ar) { return false; } - if (changesMade) { + if (myChangesMade) { LOG.debug( "changes made to document; old length=" + - document.getTextLength() + ", new=" + sb.length() + myDocument.getTextLength() + ", new=" + myBuffer.length() ); - LOG.debug("old document is:\n" + document.getText()); - LOG.debug("new document is:\n" + sb.toString()); - document.replaceString(0, document.getTextLength(), sb.toString()); + LOG.debug("old document is:\n" + myDocument.getText()); + LOG.debug("new document is:\n" + myBuffer.toString()); + myDocument.replaceString(0, myDocument.getTextLength(), myBuffer.toString()); } - return changesMade; + return myChangesMade; } /** @@ -478,17 +461,17 @@ public class Spacer { int direction = before ? -1 : +1; int count = 0; { - char braceChar = sb.charAt(offset); + char braceChar = myBuffer.charAt(offset); if (braceChar != '{' && braceChar != '}') { int L = offset - 50; int R = offset + 50; if (L < 0) { L = 0; } - if (R > sb.length()) { - R = sb.length(); + if (R > myBuffer.length()) { + R = myBuffer.length(); } - String context = sb.toString().substring(L, R); + String context = myBuffer.toString().substring(L, R); throw new RuntimeException( "adjustSpacing: char at offset " + offset + @@ -539,7 +522,7 @@ public class Spacer { /** * first count the number of existing blank lines. */ - if (offset + direction >= sb.length()) { + if (offset + direction >= myBuffer.length()) { LOG.debug("at EOF, don't append any extra blank lines"); // we're at end of file. Don't append any extra blank lines. nBlankLines = 0; @@ -607,31 +590,31 @@ public class Spacer { endIndex += offset + 1; } else { - offset = endIndex = sb.length(); + offset = endIndex = myBuffer.length(); } try { - changesMade = true; + myChangesMade = true; LOG.debug( "sb.replace(" + offset + "," + endIndex + ") with " + desiredNewlineChars + " newline characters" ); - sb.replace(offset, endIndex, new String(newlineChars, 0, desiredNewlineChars)); + myBuffer.replace(offset, endIndex, new String(myNewlineChars, 0, desiredNewlineChars)); result = desiredNewlineChars - (endIndex - offset); // now update virtualWhiteSpace accordingly. if (virtualWhiteSpace != null) { offset -= virtualWhiteSpace.getTextOffset(); endIndex -= virtualWhiteSpace.getTextOffset(); StringBuffer vsb = new StringBuffer(virtualWhiteSpace.getText()); - vsb.replace(offset, endIndex, new String(newlineChars, 0, desiredNewlineChars)); + vsb.replace(offset, endIndex, new String(myNewlineChars, 0, desiredNewlineChars)); virtualWhiteSpace.setTextValue(vsb.toString()); } } catch (StringIndexOutOfBoundsException si) { throw new RuntimeException( "sb.length()=" + - sb.length() + + myBuffer.length() + ", offset=" + offset + ", before=" + @@ -640,7 +623,7 @@ public class Spacer { count + ", desiredNewlineChars=" + desiredNewlineChars + - ", charAt offset=" + (offset < sb.length() ? "" + sb.charAt(offset) : "OOB"), si + ", charAt offset=" + (offset < myBuffer.length() ? "" + myBuffer.charAt(offset) : "OOB"), si ); } return result; diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommentRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommentRuleInstance.java index a8493481dd7c..71ec06a4812e 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommentRuleInstance.java +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommentRuleInstance.java @@ -33,32 +33,30 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; import java.awt.*; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** Used to store a generated comment, and to determine if it should be emitted. */ -public abstract class CommentRuleInstance - implements RuleInstance, - FilePopupEntry -{ - protected final CommentRule commentRule; - protected boolean emit; +public abstract class CommentRuleInstance implements RuleInstance, FilePopupEntry { + + protected final CommentRule myCommentRule; + protected boolean myEmit; public CommentRuleInstance(final CommentRule commentRule) { - this.commentRule = commentRule; - emit = false; + this.myCommentRule = commentRule; + myEmit = false; } public boolean isEmit() { - return emit; + return myEmit; } public void setEmit(final boolean emit) { - this.emit = emit; + this.myEmit = emit; } public Rule getRule() { - return commentRule; + return myCommentRule; } /** Determine if this comment, in this instance, should be emitted. */ @@ -69,15 +67,15 @@ public abstract class CommentRuleInstance } public void emit(Emitter emitter) { - StringBuffer sb = emitter.getStringBuffer(); - if (emit) { + StringBuilder sb = emitter.getTextBuffer(); + if (myEmit) { // emit a comment. Precede with a newline unless this is the first line of the file. if (sb.length() > 0) { sb.append('\n'); - sb.append(commentRule.getExpandedCommentText()); + sb.append(myCommentRule.getExpandedCommentText()); } else { - sb.append(commentRule.getExpandedCommentText()); + sb.append(myCommentRule.getExpandedCommentText()); sb.append('\n'); } } @@ -91,12 +89,10 @@ public abstract class CommentRuleInstance } public List getMatches() { - return new ArrayList(); + return Collections.emptyList(); } - public void rearrangeRuleItems(List entries, - RearrangerSettings settings) - { + public void rearrangeRuleItems(List entries, RearrangerSettings settings) { } public void addRuleInstanceToPopupTree(DefaultMutableTreeNode node, RearrangerSettings settings) { @@ -117,7 +113,7 @@ public abstract class CommentRuleInstance * append the comment if generated and if showComments is set. */ if (isEmit()) { - commentRule.addToPopupTree(top, settings); + myCommentRule.addToPopupTree(top, settings); } } @@ -131,14 +127,14 @@ public abstract class CommentRuleInstance } public JLabel getPopupEntryText(RearrangerSettings settings) { - JLabel label = new JLabel(commentRule.toString()); + JLabel label = new JLabel(myCommentRule.toString()); Font font = label.getFont().deriveFont(Font.ITALIC); label.setFont(font); return label; } public String toString() { - return "instance of:" + commentRule.toString(); + return "instance of:" + myCommentRule.toString(); } /** diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommonRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommonRuleInstance.java index 502418ae4a7f..810315c9e902 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommonRuleInstance.java +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/CommonRuleInstance.java @@ -23,7 +23,7 @@ package com.wrq.rearranger.ruleinstance; import com.intellij.openapi.diagnostic.Logger; import com.wrq.rearranger.entry.ClassContentsEntry; -import com.wrq.rearranger.entry.IPopupTreeRangeEntry; +import com.wrq.rearranger.entry.PopupTreeRangeEntry; import com.wrq.rearranger.entry.MethodEntry; import com.wrq.rearranger.entry.RangeEntry; import com.wrq.rearranger.popup.FilePopupEntry; @@ -65,7 +65,7 @@ public abstract class CommonRuleInstance */ public void addEntry(RangeEntry entry) { if (myRule instanceof CommonAttributes) { - SortOptions sortOptions = ((CommonAttributes)myRule).getSortAttr(); + SortOptions sortOptions = ((CommonAttributes)myRule).getSortOptions(); insertionSort(entry, sortOptions); } else { @@ -135,7 +135,7 @@ public abstract class CommonRuleInstance /** * append each of the matches to the top level. */ - for (IPopupTreeRangeEntry entry : getMatches()) { + for (PopupTreeRangeEntry entry : getMatches()) { entry.addToPopupTree(top, settings); } } diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/HeaderTrailerRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/HeaderTrailerRuleInstance.java index 677740beea2b..cc8aa53d3655 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/HeaderTrailerRuleInstance.java +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/HeaderTrailerRuleInstance.java @@ -26,19 +26,20 @@ import com.wrq.rearranger.entry.RangeEntry; import com.wrq.rearranger.rearrangement.Emitter; import com.wrq.rearranger.settings.RearrangerSettings; import com.wrq.rearranger.settings.attributeGroups.Rule; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.tree.DefaultMutableTreeNode; import java.util.ArrayList; import java.util.List; /** Instance to pick up header text. */ -public class HeaderTrailerRuleInstance - implements RuleInstance -{ - private final Rule myRule; - private RangeEntry myEntry; +public class HeaderTrailerRuleInstance implements RuleInstance { - public HeaderTrailerRuleInstance(Rule rule) { + @NotNull private final Rule myRule; + @Nullable private RangeEntry myEntry; + + public HeaderTrailerRuleInstance(@NotNull Rule rule) { myRule = rule; } @@ -55,12 +56,13 @@ public class HeaderTrailerRuleInstance return list; } + @NotNull public Rule getRule() { return myRule; } - public void addEntry(RangeEntry entry) { - this.myEntry = entry; // a header only has one entry + public void addEntry(@Nullable RangeEntry entry) { + myEntry = entry; // a header only has one entry } public void emit(Emitter emitter) { diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/InterfaceInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/InterfaceInstance.java index a5c7b79cb9b9..1b289a200102 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/InterfaceInstance.java +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/InterfaceInstance.java @@ -118,20 +118,21 @@ public class InterfaceInstance } } + @SuppressWarnings("MismatchedQueryAndUpdateOfStringBuilder") void emit(Emitter emitter) { - StringBuffer sb = emitter.getStringBuffer(); + StringBuilder buffer = emitter.getTextBuffer(); String commentString = expandComment(rule.getPrecedingComment()); if (commentString.length() > 0) { - sb.append("\n"); - sb.append(commentString); + buffer.append("\n"); + buffer.append(commentString); } for (MethodEntry rangeEntry : methods) { rangeEntry.emit(emitter); } commentString = expandComment(rule.getTrailingComment()); if (commentString.length() > 0) { - sb.append("\n"); - sb.append(commentString); + buffer.append("\n"); + buffer.append(commentString); } } diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/PrecedingCommentRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/PrecedingCommentRuleInstance.java index 5dea4fbd84d6..bd1854a7ffa3 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/PrecedingCommentRuleInstance.java +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/PrecedingCommentRuleInstance.java @@ -38,10 +38,10 @@ public class PrecedingCommentRuleInstance public void determineEmit(List resultRuleInstances, int startIndex) { if (match( resultRuleInstances, - commentRule.getnPrecedingRulesToMatch(), + myCommentRule.getnPrecedingRulesToMatch(), -1, startIndex, - commentRule.isAllPrecedingRules())) + myCommentRule.isAllPrecedingRules())) { setEmit(true); } diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/RuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/RuleInstance.java index ab2e5772431d..48c4b5a9f9e5 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/RuleInstance.java +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/RuleInstance.java @@ -32,10 +32,11 @@ import javax.swing.tree.DefaultMutableTreeNode; import java.util.List; /** - * One RuleInstance exists for every execution of every rule. An execution of a rule is the process by which + * One {@link RuleInstance} exists for every execution of every rule. An execution of a rule is the process by which * items are matched to a rule. */ public interface RuleInstance { + /** @return true if one or more items matched the rule in this instance. */ boolean hasMatches(); diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SubsequentCommentRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SubsequentCommentRuleInstance.java index 267706698450..bc1b41265865 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SubsequentCommentRuleInstance.java +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SubsequentCommentRuleInstance.java @@ -38,10 +38,10 @@ public class SubsequentCommentRuleInstance public void determineEmit(List resultRuleInstances, int startIndex) { if (match( resultRuleInstances, - commentRule.getnSubsequentRulesToMatch(), + myCommentRule.getnSubsequentRulesToMatch(), +1, startIndex, - commentRule.isAllSubsequentRules() + myCommentRule.isAllSubsequentRules() )) { setEmit(true); diff --git a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SurroundingCommentRuleInstance.java b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SurroundingCommentRuleInstance.java index 33e90ff12e0a..a41874b6cdb5 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SurroundingCommentRuleInstance.java +++ b/plugins/rearranger/src/com/wrq/rearranger/ruleinstance/SurroundingCommentRuleInstance.java @@ -38,17 +38,17 @@ public class SurroundingCommentRuleInstance public void determineEmit(List resultRuleInstances, int startIndex) { if (match( resultRuleInstances, - commentRule.getnPrecedingRulesToMatch(), + myCommentRule.getnPrecedingRulesToMatch(), -1, startIndex, - commentRule.isAllPrecedingRules() + myCommentRule.isAllPrecedingRules() ) && match( resultRuleInstances, - commentRule.getnSubsequentRulesToMatch(), + myCommentRule.getnSubsequentRulesToMatch(), +1, startIndex, - commentRule.isAllSubsequentRules() + myCommentRule.isAllSubsequentRules() )) { setEmit(true); diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/CommentRule.java b/plugins/rearranger/src/com/wrq/rearranger/settings/CommentRule.java index 4e8710cb489e..c9dcc3f3467c 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/CommentRule.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/CommentRule.java @@ -21,7 +21,7 @@ */ package com.wrq.rearranger.settings; -import com.wrq.rearranger.entry.IPopupTreeRangeEntry; +import com.wrq.rearranger.entry.PopupTreeRangeEntry; import com.wrq.rearranger.entry.RangeEntry; import com.wrq.rearranger.popup.FilePopupEntry; import com.wrq.rearranger.popup.RearrangerTreeNode; @@ -32,6 +32,7 @@ import com.wrq.rearranger.settings.attributeGroups.RegexUtil; import com.wrq.rearranger.util.Constraints; import org.jdom.Attribute; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.border.Border; @@ -50,7 +51,7 @@ import java.util.List; /** Handles insertion of comment separators between sections of the rearranged file. */ public final class CommentRule implements AttributeGroup, - IPopupTreeRangeEntry, + PopupTreeRangeEntry, FilePopupEntry { // ------------------------------------------------------- FIELDS ------------------------------------------------------ @@ -417,6 +418,7 @@ public final class CommentRule // ---------------------------------------------- Interface AttributeGroup --------------------------------------------- + @NotNull public final /*CommentRule*/AttributeGroup deepCopy() { final CommentRule comment = new CommentRule(); comment.commentText = commentText; @@ -429,7 +431,7 @@ public final class CommentRule return comment; } - public final void writeExternal(final Element parent) { + public final void writeExternal(@NotNull final Element parent) { final Element me = new Element("Comment"); me.setText(escape(commentText)); me.setAttribute("condition", "" + emitCondition); @@ -464,11 +466,12 @@ public final class CommentRule // -------------------------------------------------- Interface IRule -------------------------------------------------- + @NotNull public RuleInstance createRuleInstance() { return CommentRuleInstanceFactory.buildCommentRuleInstance(this); } - public boolean isMatch(RangeEntry rangeEntry) { + public boolean isMatch(@NotNull RangeEntry rangeEntry) { return false; // comment rules match no entries -- they're just placeholders to generate comments. } diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/AttributeGroup.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/AttributeGroup.java index 3b39e9c046c8..a9b278f586e9 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/AttributeGroup.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/AttributeGroup.java @@ -22,15 +22,15 @@ package com.wrq.rearranger.settings.attributeGroups; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; /** Methods implemented by rule objects, which are saved in configuration. */ -public interface AttributeGroup - extends Rule -{ +public interface AttributeGroup extends Rule { // -------------------------- OTHER METHODS -------------------------- - public AttributeGroup deepCopy(); + @NotNull + AttributeGroup deepCopy(); - public void writeExternal(final Element parent); + void writeExternal(final @NotNull Element parent); } diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ClassAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ClassAttributes.java index 0af457a9d854..41559ecda682 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ClassAttributes.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ClassAttributes.java @@ -29,6 +29,8 @@ import com.wrq.rearranger.settings.atomicAttributes.AbstractAttribute; import com.wrq.rearranger.settings.atomicAttributes.EnumAttribute; import com.wrq.rearranger.util.Constraints; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.Border; @@ -47,6 +49,7 @@ public final class ClassAttributes // -------------------------- STATIC METHODS -------------------------- + @Nullable public static AttributeGroup readExternal(final Element element) { if (element.getName().equals("Class")) { final ClassAttributes result = new ClassAttributes(); @@ -82,11 +85,11 @@ public final class ClassAttributes // ------------------------ CANONICAL METHODS ------------------------ public final String toString() { - final StringBuffer sb = new StringBuffer(70); + final StringBuilder sb = new StringBuilder(70); sb.append(abAttr.getDescriptiveString()); - sb.append(plAttr.getProtectionLevelString()); - sb.append(stAttr.getDescriptiveString()); - sb.append(fAttr.getDescriptiveString()); + sb.append(getProtectionLevelAttributes().getProtectionLevelString()); + sb.append(getStaticAttribute().getDescriptiveString()); + sb.append(getFinalAttribute().getDescriptiveString()); sb.append(enumAttr.getDescriptiveString()); if (sb.length() == 0) { sb.append("all classes"); @@ -94,11 +97,11 @@ public final class ClassAttributes else { sb.append("classes"); } - if (nameAttr.isMatch()) { + if (getNameAttribute().isMatch()) { sb.append(' '); - sb.append(nameAttr.getDescriptiveString()); + sb.append(getNameAttribute().getDescriptiveString()); } - sb.append(sortAttr.getDescriptiveString()); + sb.append(getSortOptions().getDescriptiveString()); return sb.toString(); } @@ -107,6 +110,7 @@ public final class ClassAttributes // --------------------- Interface AttributeGroup --------------------- + @NotNull public final /*ClassAttributes*/AttributeGroup deepCopy() { final ClassAttributes result = new ClassAttributes(); deepCopyCommonItems(result); @@ -115,7 +119,8 @@ public final class ClassAttributes return result; } - public final void writeExternal(final Element parent) { + @SuppressWarnings("unchecked") + public final void writeExternal(@NotNull final Element parent) { final Element me = new Element("Class"); writeExternalCommonAttributes(me); abAttr.appendAttributes(me); @@ -146,27 +151,27 @@ public final class ClassAttributes constraints.weightx = 1.0d; constraints.weighty = 0.0d; constraints.insets = new Insets(0, 0, 10, 0); - caPanel.add(getPlAttr().getProtectionLevelPanel(), constraints); + caPanel.add(getProtectionLevelAttributes().getProtectionLevelPanel(), constraints); constraints.gridy = 4; constraints.gridheight = 1; - caPanel.add(getStAttr().getAndNotPanel(), constraints); + caPanel.add(getStaticAttribute().getAndNotPanel(), constraints); constraints.gridy++; caPanel.add(getAbAttr().getAndNotPanel(), constraints); constraints.gridy++; - caPanel.add(getfAttr().getAndNotPanel(), constraints); + caPanel.add(getFinalAttribute().getAndNotPanel(), constraints); constraints.gridy++; caPanel.add(getEnumAttr().getAndNotPanel(), constraints); constraints.gridy++; - caPanel.add(getNameAttr().getStringPanel(), constraints); + caPanel.add(getNameAttribute().getStringPanel(), constraints); constraints.gridy++; constraints.gridheight = GridBagConstraints.REMAINDER; constraints.weighty = 1.0d; constraints.insets = new Insets(0, 0, 0, 0); - caPanel.add(sortAttr.getSortOptionsPanel(), constraints); + caPanel.add(getSortOptions().getSortOptionsPanel(), constraints); return caPanel; } - public final boolean isMatch(RangeEntry entry) + public final boolean isMatch(@NotNull RangeEntry entry) // final int modifiers, final String name, final String returnType) { return entry.getEnd().getParent() instanceof PsiClass && diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/CommonAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/CommonAttributes.java index 341378944a7b..6cc94c03a37e 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/CommonAttributes.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/CommonAttributes.java @@ -27,6 +27,7 @@ import com.wrq.rearranger.ruleinstance.RuleInstance; import com.wrq.rearranger.settings.RearrangerSettings; import com.wrq.rearranger.settings.atomicAttributes.*; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -36,64 +37,63 @@ import java.util.List; * protected, package), final modifier, and static modifier. Ability to match the name to a regular * expression is also supported. */ -public abstract class CommonAttributes - implements AttributeGroup, PrioritizedRule -{ +public abstract class CommonAttributes implements AttributeGroup, PrioritizedRule { + // ------------------------------ FIELDS ------------------------------ - ProtectionLevelAttributes plAttr; - FinalAttribute fAttr; - StaticAttribute stAttr; - NameAttribute nameAttr; - SortOptions sortAttr; - int priority; // 1 = low priority, > 1 is higher priority + private ProtectionLevelAttributes myProtectionLevelAttributes; + private FinalAttribute myFinalAttribute; + private StaticAttribute myStaticAttribute; + private NameAttribute myNameAttribute; + private SortOptions mySortOptions; + private int myPriority; // 1 = low priority, > 1 is higher priority // -------------------------- STATIC METHODS -------------------------- static void readExternal(final CommonAttributes result, final Element item) { - result.plAttr = ProtectionLevelAttributes.readExternal(item); - result.stAttr = StaticAttribute.readExternal(item); - result.fAttr = FinalAttribute.readExternal(item); - result.nameAttr = NameAttribute.readExternal(item); - result.sortAttr = SortOptions.readExternal(item); - result.priority = RearrangerSettings.getIntAttribute(item, "priority", 1); + result.myProtectionLevelAttributes = ProtectionLevelAttributes.readExternal(item); + result.myStaticAttribute = StaticAttribute.readExternal(item); + result.myFinalAttribute = FinalAttribute.readExternal(item); + result.myNameAttribute = NameAttribute.readExternal(item); + result.mySortOptions = SortOptions.readExternal(item); + result.myPriority = RearrangerSettings.getIntAttribute(item, "priority", 1); } // --------------------------- CONSTRUCTORS --------------------------- public CommonAttributes() { - plAttr = new ProtectionLevelAttributes(); - fAttr = new FinalAttribute(); - stAttr = new StaticAttribute(); - nameAttr = new NameAttribute(); - sortAttr = new SortOptions(); - priority = 1; + myProtectionLevelAttributes = new ProtectionLevelAttributes(); + myFinalAttribute = new FinalAttribute(); + myStaticAttribute = new StaticAttribute(); + myNameAttribute = new NameAttribute(); + mySortOptions = new SortOptions(); + myPriority = 1; } // --------------------- GETTER / SETTER METHODS --------------------- - public final NameAttribute getNameAttr() { - return nameAttr; + public final NameAttribute getNameAttribute() { + return myNameAttribute; } - final public ProtectionLevelAttributes getPlAttr() { - return plAttr; + final public ProtectionLevelAttributes getProtectionLevelAttributes() { + return myProtectionLevelAttributes; } public int getPriority() { - return priority; + return myPriority; } public void setPriority(int priority) { - this.priority = priority; + this.myPriority = priority; } - final public StaticAttribute getStAttr() { - return stAttr; + final public StaticAttribute getStaticAttribute() { + return myStaticAttribute; } - public SortOptions getSortAttr() { - return sortAttr; + public SortOptions getSortOptions() { + return mySortOptions; } // ------------------------ CANONICAL METHODS ------------------------ @@ -103,12 +103,12 @@ public abstract class CommonAttributes return false; } final CommonAttributes ca = (CommonAttributes)obj; - return plAttr.equals(ca.plAttr) && - stAttr.equals(ca.stAttr) && - fAttr.equals(ca.fAttr) && - nameAttr.equals(ca.nameAttr) && - sortAttr.equals(ca.sortAttr) && - priority == ca.priority; + return myProtectionLevelAttributes.equals(ca.myProtectionLevelAttributes) && + myStaticAttribute.equals(ca.myStaticAttribute) && + myFinalAttribute.equals(ca.myFinalAttribute) && + myNameAttribute.equals(ca.myNameAttribute) && + mySortOptions.equals(ca.mySortOptions) && + myPriority == ca.myPriority; } // ------------------------ INTERFACE METHODS ------------------------ @@ -116,16 +116,14 @@ public abstract class CommonAttributes // --------------------- Interface IRule --------------------- + @NotNull public RuleInstance createRuleInstance() { return new DefaultRuleInstance(this); } - public boolean isMatch(RangeEntry rangeEntry) { - final boolean result = plAttr.isMatch(rangeEntry.getModifiers()) && - stAttr.isMatch(rangeEntry.getModifiers()) && - fAttr.isMatch(rangeEntry.getModifiers()) && - nameAttr.isMatch(rangeEntry.getName()); - return result; + public boolean isMatch(@NotNull RangeEntry rangeEntry) { + return myProtectionLevelAttributes.isMatch(rangeEntry.getModifiers()) && myStaticAttribute.isMatch(rangeEntry.getModifiers()) + && myFinalAttribute.isMatch(rangeEntry.getModifiers()) && myNameAttribute.isMatch(rangeEntry.getName()); } /** @@ -147,38 +145,31 @@ public abstract class CommonAttributes return 0; } - /** - * Calculates a list of regular expression patterns, one for each comment that the rule might create, which will - * match any comment that the rule might generate. These can be combined to form a global comment pattern which - * will match all possible generated comments from all rules. These patterns will be appended to the supplied - * list. - */ public void addCommentPatternsToList(List list) { - return; } // -------------------------- OTHER METHODS -------------------------- final void deepCopyCommonItems(final CommonAttributes result) { - result.plAttr = (ProtectionLevelAttributes)plAttr.deepCopy(); - result.fAttr = (FinalAttribute)fAttr.deepCopy(); - result.stAttr = (StaticAttribute)stAttr.deepCopy(); - result.nameAttr = (NameAttribute)nameAttr.deepCopy(); - result.sortAttr = (SortOptions)sortAttr.deepCopy(); - result.priority = priority; + result.myProtectionLevelAttributes = (ProtectionLevelAttributes)myProtectionLevelAttributes.deepCopy(); + result.myFinalAttribute = (FinalAttribute)myFinalAttribute.deepCopy(); + result.myStaticAttribute = (StaticAttribute)myStaticAttribute.deepCopy(); + result.myNameAttribute = (NameAttribute)myNameAttribute.deepCopy(); + result.mySortOptions = (SortOptions)mySortOptions.deepCopy(); + result.myPriority = myPriority; } - final public FinalAttribute getfAttr() { - return fAttr; + final public FinalAttribute getFinalAttribute() { + return myFinalAttribute; } final void writeExternalCommonAttributes(final Element child) { - plAttr.appendAttributes(child); - stAttr.appendAttributes(child); - fAttr.appendAttributes(child); - nameAttr.appendAttributes(child); - sortAttr.appendAttributes(child); - child.setAttribute("priority", "" + priority); + myProtectionLevelAttributes.appendAttributes(child); + myStaticAttribute.appendAttributes(child); + myFinalAttribute.appendAttributes(child); + myNameAttribute.appendAttributes(child); + mySortOptions.appendAttributes(child); + child.setAttribute("priority", String.valueOf(myPriority)); } } diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/DefaultRule.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/DefaultRule.java index 5310def3f88e..c35cc64163a5 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/DefaultRule.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/DefaultRule.java @@ -24,6 +24,7 @@ package com.wrq.rearranger.settings.attributeGroups; import com.wrq.rearranger.entry.RangeEntry; import com.wrq.rearranger.ruleinstance.DefaultRuleInstance; import com.wrq.rearranger.ruleinstance.RuleInstance; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -35,6 +36,7 @@ import java.util.List; public class DefaultRule implements Rule { + @NotNull public RuleInstance createRuleInstance() { return new DefaultRuleInstance(this); } @@ -47,7 +49,7 @@ public class DefaultRule // does nothing } - public boolean isMatch(RangeEntry entry) { + public boolean isMatch(@NotNull RangeEntry entry) { return !(entry.isFixedHeader() || entry.isFixedTrailer()); } diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/FieldAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/FieldAttributes.java index 6706b7fae11e..53c46a3a3ecb 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/FieldAttributes.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/FieldAttributes.java @@ -29,6 +29,7 @@ import com.wrq.rearranger.settings.atomicAttributes.TypeAttribute; import com.wrq.rearranger.settings.atomicAttributes.VolatileAttribute; import com.wrq.rearranger.util.Constraints; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.border.Border; @@ -88,10 +89,10 @@ public final class FieldAttributes // ------------------------ CANONICAL METHODS ------------------------ public final String toString() { - final StringBuffer sb = new StringBuffer(70); - sb.append(plAttr.getProtectionLevelString()); - sb.append(stAttr.getDescriptiveString()); - sb.append(fAttr.getDescriptiveString()); + final StringBuilder sb = new StringBuilder(70); + sb.append(getProtectionLevelAttributes().getProtectionLevelString()); + sb.append(getStaticAttribute().getDescriptiveString()); + sb.append(getFinalAttribute().getDescriptiveString()); sb.append(transientAttr.getDescriptiveString()); sb.append(volatileAttr.getDescriptiveString()); @@ -109,21 +110,21 @@ public final class FieldAttributes sb.append(" which are not initialized to an anonymous class"); } } - if (nameAttr.isMatch()) { + if (getNameAttribute().isMatch()) { if (initToAnonClassAttr.isValue()) { sb.append(" and"); } sb.append(' '); - sb.append(nameAttr.getDescriptiveString()); + sb.append(getNameAttribute().getDescriptiveString()); } if (typeAttr.isMatch()) { - if (nameAttr.isMatch() || initToAnonClassAttr.isValue()) { + if (getNameAttribute().isMatch() || initToAnonClassAttr.isValue()) { sb.append(" and"); } sb.append(' '); sb.append(typeAttr.getDescriptiveString()); } - sb.append(sortAttr.getDescriptiveString()); + sb.append(getSortOptions().getDescriptiveString()); return sb.toString(); } @@ -132,6 +133,7 @@ public final class FieldAttributes // --------------------- Interface AttributeGroup --------------------- + @NotNull public final /*FieldAttributes*/AttributeGroup deepCopy() { final FieldAttributes result = new FieldAttributes(); deepCopyCommonItems(result); @@ -142,7 +144,8 @@ public final class FieldAttributes return result; } - public final void writeExternal(final Element parent) { + @SuppressWarnings("unchecked") + public final void writeExternal(@NotNull final Element parent) { final Element child = new Element("Field"); writeExternalCommonAttributes(child); initToAnonClassAttr.appendAttributes(child); @@ -173,16 +176,16 @@ public final class FieldAttributes constraints.gridwidth = 1; constraints.gridheight = 4; constraints.weightx = 1.0d; - plPanel.add(getPlAttr().getProtectionLevelPanel(), constraints); + plPanel.add(getProtectionLevelAttributes().getProtectionLevelPanel(), constraints); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridwidth = GridBagConstraints.REMAINDER; constraints.gridy = 0; constraints.gridx = 1; constraints.gridheight = 1; constraints.weighty = 0; - plPanel.add(getStAttr().getAndNotPanel(), constraints); + plPanel.add(getStaticAttribute().getAndNotPanel(), constraints); constraints.gridy++; - plPanel.add(getfAttr().getAndNotPanel(), constraints); + plPanel.add(getFinalAttribute().getAndNotPanel(), constraints); constraints.gridy++; plPanel.add(getTransientAttr().getAndNotPanel(), constraints); constraints.gridy++; @@ -192,18 +195,18 @@ public final class FieldAttributes constraints.gridy++; plPanel.add(getInitToAnonClassAttr().getAndNotPanel(), constraints); constraints.gridy++; - plPanel.add(getNameAttr().getStringPanel(), constraints); + plPanel.add(getNameAttribute().getStringPanel(), constraints); constraints.gridy++; plPanel.add(getTypeAttr().getStringPanel(), constraints); constraints.gridy++; constraints.gridheight = GridBagConstraints.REMAINDER; constraints.weighty = 1.0d; constraints.insets = new Insets(0, 0, 0, 0); - plPanel.add(sortAttr.getSortOptionsPanel(), constraints); + plPanel.add(getSortOptions().getSortOptionsPanel(), constraints); return plPanel; } - public boolean isMatch(RangeEntry rangeEntry) { + public boolean isMatch(@NotNull RangeEntry rangeEntry) { return rangeEntry.getEnd() instanceof PsiField && initToAnonClassAttr.isMatch(rangeEntry.getModifiers()) && transientAttr.isMatch(rangeEntry.getModifiers()) && diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/HeaderRule.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/HeaderRule.java index fe32d118e50f..932046294061 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/HeaderRule.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/HeaderRule.java @@ -24,14 +24,16 @@ package com.wrq.rearranger.settings.attributeGroups; import com.wrq.rearranger.entry.RangeEntry; import com.wrq.rearranger.ruleinstance.HeaderTrailerRuleInstance; import com.wrq.rearranger.ruleinstance.RuleInstance; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; /** A rule to match header text (text which does not constitute a matchable item such as a field or method.) */ -public class HeaderRule - implements Rule -{ +public class HeaderRule implements Rule { + + @NotNull public RuleInstance createRuleInstance() { return new HeaderTrailerRuleInstance(this); } @@ -45,15 +47,15 @@ public class HeaderRule // does nothing } - public boolean isMatch(RangeEntry rangeEntry) { + public boolean isMatch(@NotNull RangeEntry rangeEntry) { return rangeEntry.isFixedHeader(); } - public boolean commentsMatchGlobalPattern(String pattern) { + public boolean commentsMatchGlobalPattern(@Nullable String pattern) { return true; } - public List getOffendingPatterns(String pattern) { + public List getOffendingPatterns(@Nullable String pattern) { return new ArrayList(1); } @@ -61,6 +63,6 @@ public class HeaderRule return 0; } - public void addCommentPatternsToList(List list) { + public void addCommentPatternsToList(@Nullable List list) { } } diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InnerClassAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InnerClassAttributes.java index 80ebd47b7766..5410312ca393 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InnerClassAttributes.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InnerClassAttributes.java @@ -28,6 +28,7 @@ import com.wrq.rearranger.entry.RangeEntry; import com.wrq.rearranger.settings.atomicAttributes.AbstractAttribute; import com.wrq.rearranger.settings.atomicAttributes.EnumAttribute; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.border.Border; @@ -72,11 +73,11 @@ public final class InnerClassAttributes // ------------------------ CANONICAL METHODS ------------------------ public final String toString() { - final StringBuffer sb = new StringBuffer(70); + final StringBuilder sb = new StringBuilder(70); sb.append(abAttr.getDescriptiveString()); - sb.append(plAttr.getProtectionLevelString()); - sb.append(stAttr.getDescriptiveString()); - sb.append(fAttr.getDescriptiveString()); + sb.append(getProtectionLevelAttributes().getProtectionLevelString()); + sb.append(getStaticAttribute().getDescriptiveString()); + sb.append(getFinalAttribute().getDescriptiveString()); sb.append(enumAttr.getDescriptiveString()); if (sb.length() == 0) { sb.append("all inner classes"); @@ -84,11 +85,11 @@ public final class InnerClassAttributes else { sb.append("inner classes"); } - if (nameAttr.isMatch()) { + if (getNameAttribute().isMatch()) { sb.append(' '); - sb.append(nameAttr.getDescriptiveString()); + sb.append(getNameAttribute().getDescriptiveString()); } - sb.append(sortAttr.getDescriptiveString()); + sb.append(getSortOptions().getDescriptiveString()); return sb.toString(); } @@ -97,6 +98,7 @@ public final class InnerClassAttributes // --------------------- Interface AttributeGroup --------------------- + @NotNull public final /*InnerClassAttributes*/AttributeGroup deepCopy() { final InnerClassAttributes result = new InnerClassAttributes(); deepCopyCommonItems(result); @@ -105,7 +107,8 @@ public final class InnerClassAttributes return result; } - public final void writeExternal(final Element parent) { + @SuppressWarnings("unchecked") + public final void writeExternal(@NotNull final Element parent) { final Element me = new Element("InnerClass"); writeExternalCommonAttributes(me); abAttr.appendAttributes(me); @@ -138,27 +141,27 @@ public final class InnerClassAttributes constraints.weighty = 0.0d; constraints.gridx = constraints.gridy = 0; constraints.insets = new Insets(0, 0, 5, 0); - caPanel.add(getPlAttr().getProtectionLevelPanel(), constraints); + caPanel.add(getProtectionLevelAttributes().getProtectionLevelPanel(), constraints); constraints.gridy = 1; constraints.gridheight = 1; - caPanel.add(getStAttr().getAndNotPanel(), constraints); + caPanel.add(getStaticAttribute().getAndNotPanel(), constraints); constraints.gridy++; caPanel.add(getAbAttr().getAndNotPanel(), constraints); constraints.gridy++; - caPanel.add(getfAttr().getAndNotPanel(), constraints); + caPanel.add(getFinalAttribute().getAndNotPanel(), constraints); constraints.gridy++; caPanel.add(getEnumAttr().getAndNotPanel(), constraints); constraints.gridy++; - caPanel.add(getNameAttr().getStringPanel(), constraints); + caPanel.add(getNameAttribute().getStringPanel(), constraints); constraints.gridy++; constraints.gridheight = GridBagConstraints.REMAINDER; constraints.weighty = 1.0d; constraints.insets = new Insets(0, 0, 0, 0); - caPanel.add(sortAttr.getSortOptionsPanel(), constraints); + caPanel.add(getSortOptions().getSortOptionsPanel(), constraints); return caPanel; } - public final boolean isMatch(RangeEntry entry) { + public final boolean isMatch(@NotNull RangeEntry entry) { // return entry.getEnd() instanceof PsiClass && // entry.getEnd() should be the LBrace of a class. return entry.getEnd().getParent() instanceof PsiClass && diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InterfaceAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InterfaceAttributes.java index 910c0c0d2dfb..fa38d741ed16 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InterfaceAttributes.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/InterfaceAttributes.java @@ -31,6 +31,7 @@ import com.wrq.rearranger.settings.RearrangerSettings; import com.wrq.rearranger.settings.atomicAttributes.NameAttribute; import com.wrq.rearranger.util.Constraints; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.border.Border; @@ -136,11 +137,12 @@ public class InterfaceAttributes return priority; } + @NotNull public RuleInstance createRuleInstance() { return new InterfaceRuleInstance(this); } - public final boolean isMatch(RangeEntry rangeEntry) { + public final boolean isMatch(@NotNull RangeEntry rangeEntry) { if (rangeEntry instanceof MethodEntry) { MethodEntry me = (MethodEntry)rangeEntry; if (me.getInterfaceName() != null) { @@ -191,6 +193,7 @@ public class InterfaceAttributes return sb.toString(); } + @NotNull public final /*InterfaceAttributes*/AttributeGroup deepCopy() { final InterfaceAttributes result = new InterfaceAttributes(); result.nameAttr = (NameAttribute)nameAttr.deepCopy(); @@ -225,7 +228,7 @@ public class InterfaceAttributes priority = RearrangerSettings.getIntAttribute(item, "priority", 1); } - public final void writeExternal(final Element parent) { + public final void writeExternal(@NotNull final Element parent) { final Element me = new Element("Interface"); parent.getChildren().add(me); nameAttr.appendAttributes(me); diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ItemAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ItemAttributes.java index 369c97c14cea..6b1465536b6f 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ItemAttributes.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/ItemAttributes.java @@ -23,14 +23,15 @@ package com.wrq.rearranger.settings.attributeGroups; import com.wrq.rearranger.settings.CommentRule; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** Routines to handle attributes common to class members (fields, methods, and inner classes.) */ -abstract public class ItemAttributes - extends CommonAttributes -{ +abstract public class ItemAttributes extends CommonAttributes { // -------------------------- STATIC METHODS -------------------------- + @Nullable public static AttributeGroup readExternal(final Element element) { if (element.getName().equals("Field")) { return FieldAttributes.readExternal(element); @@ -57,6 +58,7 @@ abstract public class ItemAttributes // --------------------- Interface AttributeGroup --------------------- + @NotNull abstract public /*ItemAttributes*/AttributeGroup deepCopy(); } diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributes.java index 79161877cbf8..886ab1d6c46f 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributes.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributes.java @@ -29,6 +29,7 @@ import com.wrq.rearranger.settings.RearrangerSettings; import com.wrq.rearranger.settings.atomicAttributes.*; import com.wrq.rearranger.util.MethodUtil; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.border.Border; @@ -252,11 +253,11 @@ public final class MethodAttributes public final String toString() { // convert settings to readable English description of the method. // - final StringBuffer sb = new StringBuffer(80); + final StringBuilder sb = new StringBuilder(80); - sb.append(plAttr.getProtectionLevelString()); - sb.append(stAttr.getDescriptiveString()); - sb.append(fAttr.getDescriptiveString()); + sb.append(getProtectionLevelAttributes().getProtectionLevelString()); + sb.append(getStaticAttribute().getDescriptiveString()); + sb.append(getFinalAttribute().getDescriptiveString()); sb.append(staticInitAttr.getDescriptiveString()); sb.append(nativeAttr.getDescriptiveString()); sb.append(syncAttr.getDescriptiveString()); @@ -332,32 +333,32 @@ public final class MethodAttributes } } } - if (nameAttr.isMatch()) { + if (getNameAttribute().isMatch()) { checkPredicate(sb, false); - nextPredicate = nameAttr.getDescriptiveString(); + nextPredicate = getNameAttribute().getDescriptiveString(); } if (returnTypeAttr.isMatch()) { checkPredicate(sb, false); nextPredicate = returnTypeAttr.getDescriptiveString(); } checkPredicate(sb, true); - sb.append(sortAttr.getDescriptiveString()); + sb.append(getSortOptions().getDescriptiveString()); if (noExtractedMethods) { sb.append(" (no extracted methods)"); } return sb.toString(); } - private void checkPredicate(StringBuffer sb, boolean finalPredicate) { + private void checkPredicate(@NotNull StringBuilder buffer, boolean finalPredicate) { if (predicateAdded && nextPredicate != null) { - sb.append(','); + buffer.append(','); if (finalPredicate) { - sb.append(" and"); + buffer.append(" and"); } } if (nextPredicate != null) { - sb.append(' '); - sb.append(nextPredicate); + buffer.append(' '); + buffer.append(nextPredicate); predicateAdded = true; nextPredicate = null; } @@ -369,6 +370,7 @@ public final class MethodAttributes // --------------------- Interface AttributeGroup --------------------- // Start Methods of Interface AttributeGroup + @NotNull public final /*ItemAttributes*/AttributeGroup deepCopy() { final MethodAttributes result = new MethodAttributes(); deepCopyCommonItems(result); @@ -393,7 +395,8 @@ public final class MethodAttributes return result; } - public final void writeExternal(final Element parent) { + @SuppressWarnings("unchecked") + public final void writeExternal(@NotNull final Element parent) { final Element me = new Element("Method"); writeExternalCommonAttributes(me); abstractAttr.appendAttributes(me); @@ -459,7 +462,7 @@ public final class MethodAttributes constraints.weightx = 0.0d; constraints.weighty = 0.0d; constraints.gridx = constraints.gridy = 0; - methodPanel.add(getPlAttr().getProtectionLevelPanel(), constraints); + methodPanel.add(getProtectionLevelAttributes().getProtectionLevelPanel(), constraints); constraints.gridwidth = GridBagConstraints.REMAINDER; constraints.gridheight = 1; constraints.gridx = 1; @@ -470,12 +473,12 @@ public final class MethodAttributes constraints.gridx = 0; constraints.gridheight = 1; constraints.gridwidth = 1; - methodPanel.add(getStAttr().getAndNotPanel(), constraints); + methodPanel.add(getStaticAttribute().getAndNotPanel(), constraints); constraints.gridx++; methodPanel.add(getAbstractAttr().getAndNotPanel(), constraints); constraints.gridx = 0; constraints.gridy++; - methodPanel.add(getfAttr().getAndNotPanel(), constraints); + methodPanel.add(getFinalAttribute().getAndNotPanel(), constraints); constraints.gridx++; methodPanel.add(getSyncAttr().getAndNotPanel(), constraints); constraints.gridx = 0; @@ -500,7 +503,7 @@ public final class MethodAttributes constraints.gridy++; methodPanel.add(getMaxParamsAttr().getIntegerPanel(), constraints); constraints.gridy++; - methodPanel.add(getNameAttr().getStringPanel(), constraints); + methodPanel.add(getNameAttribute().getStringPanel(), constraints); constraints.gridy++; methodPanel.add(getReturnTypeAttr().getStringPanel(), constraints); constraints.gridy++; @@ -509,7 +512,7 @@ public final class MethodAttributes constraints.gridy++; constraints.gridheight = GridBagConstraints.REMAINDER; constraints.weighty = 1.0d; - methodPanel.add(sortAttr.getSortOptionsPanel(), constraints); + methodPanel.add(getSortOptions().getSortOptionsPanel(), constraints); return methodPanel; } @@ -601,8 +604,8 @@ public final class MethodAttributes }); gsDefButton.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { - GetterSetterDefinition tempgsd = getterSetterDefinition.deepCopy(); - final JPanel gsDefPanel = tempgsd.getGSDefinitionPanel(); + GetterSetterDefinition tmpDefinition = getterSetterDefinition.deepCopy(); + final JPanel gsDefPanel = tmpDefinition.getGSDefinitionPanel(); final JOptionPane op = new JOptionPane( gsDefPanel, JOptionPane.PLAIN_MESSAGE, @@ -614,7 +617,7 @@ public final class MethodAttributes if (result != null && ((Integer)result) == JOptionPane.OK_OPTION) { - getterSetterDefinition = tempgsd; + getterSetterDefinition = tmpDefinition; } } }); @@ -625,7 +628,7 @@ public final class MethodAttributes // End Methods of Interface AttributeGroup // Start Methods of Interface IRule - public final boolean isMatch(RangeEntry entry) { + public final boolean isMatch(@NotNull RangeEntry entry) { final boolean result = (entry.getEnd() instanceof PsiMethod || entry.getEnd() instanceof PsiClassInitializer) && super.isMatch(entry) && @@ -640,12 +643,12 @@ public final class MethodAttributes returnTypeAttr.isMatch(entry.getType()) && minParamsAttr.isMatch(entry.getEnd()) && maxParamsAttr.isMatch(entry.getEnd()); - if (result == false) { + if (!result) { return false; } boolean typeResult = false; if (isConstructorMethodType()) { - typeResult |= (entry.getModifiers() & ModifierConstants.CONSTRUCTOR) == ModifierConstants.CONSTRUCTOR; + typeResult = (entry.getModifiers() & ModifierConstants.CONSTRUCTOR) == ModifierConstants.CONSTRUCTOR; } if (isGetterSetterMethodType() && entry.getEnd() instanceof PsiMethod) @@ -674,7 +677,7 @@ public final class MethodAttributes { typeResult = true; // true if no method type options are selected. } - return result && typeResult; + return typeResult; } } diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/Rule.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/Rule.java index 7cffb45bad01..586b58c9d5a0 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/Rule.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/Rule.java @@ -23,20 +23,23 @@ package com.wrq.rearranger.settings.attributeGroups; import com.wrq.rearranger.entry.RangeEntry; import com.wrq.rearranger.ruleinstance.RuleInstance; +import org.jetbrains.annotations.NotNull; import java.util.List; /** Interface which all rules implement. */ public interface Rule { + + @NotNull RuleInstance createRuleInstance(); // all rules have a priority; but some are not settable by the user. Those that are user settable implement - // the marker interface IPrioritizableRule. + // the marker interface PrioritizedRule. int getPriority(); void setPriority(int priority); - boolean isMatch(RangeEntry rangeEntry); + boolean isMatch(@NotNull RangeEntry rangeEntry); /** * @param pattern global pattern to which all comments should conform. diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/TrailerRule.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/TrailerRule.java index b7d42af98487..1f4ac75175ad 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/TrailerRule.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/TrailerRule.java @@ -24,6 +24,7 @@ package com.wrq.rearranger.settings.attributeGroups; import com.wrq.rearranger.entry.RangeEntry; import com.wrq.rearranger.ruleinstance.HeaderTrailerRuleInstance; import com.wrq.rearranger.ruleinstance.RuleInstance; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -32,6 +33,7 @@ import java.util.List; public class TrailerRule implements Rule { + @NotNull public RuleInstance createRuleInstance() { return new HeaderTrailerRuleInstance(this); } @@ -45,7 +47,7 @@ public class TrailerRule // does nothing } - public boolean isMatch(RangeEntry rangeEntry) { + public boolean isMatch(@NotNull RangeEntry rangeEntry) { return rangeEntry.isFixedTrailer(); } diff --git a/plugins/rearranger/src/com/wrq/rearranger/util/CommentUtil.java b/plugins/rearranger/src/com/wrq/rearranger/util/CommentUtil.java index 2ba03562ded4..f9d179c2a714 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/util/CommentUtil.java +++ b/plugins/rearranger/src/com/wrq/rearranger/util/CommentUtil.java @@ -21,8 +21,10 @@ */ package com.wrq.rearranger.util; +import com.intellij.openapi.util.text.StringUtil; import com.wrq.rearranger.settings.RearrangerSettings; import com.wrq.rearranger.settings.attributeGroups.Rule; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -30,40 +32,38 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; public class CommentUtil { - final RearrangerSettings settings; - static CommentUtil singleton; - List commentStrings; - List commentMatchers; + private final RearrangerSettings mySettings; + static CommentUtil singleton; + private final List myCommentStrings = new ArrayList(); + private final List myCommentMatchers = new ArrayList(); - public CommentUtil(RearrangerSettings settings) { - this.settings = settings; + public CommentUtil(@NotNull RearrangerSettings settings) { + mySettings = settings; createCommentPatternList(); createCommentMatcherList(); singleton = this; } public static List getCommentStrings() { - return singleton.commentStrings; + return singleton.myCommentStrings; } public static List getCommentMatchers() { - return singleton.commentMatchers; + return singleton.myCommentMatchers; } private void createCommentMatcherList() { - if (settings.getGlobalCommentPattern() != null && - settings.getGlobalCommentPattern().length() > 0) - { - // create only one Matcher for the global comment pattern. - commentMatchers = new ArrayList(1); - commentMatchers.add((getMatcher(settings.getGlobalCommentPattern()))); + if (StringUtil.isEmpty(mySettings.getGlobalCommentPattern())) { + myCommentMatchers.clear(); + for (String comment : myCommentStrings) { + Matcher matcher = getMatcher(comment); + myCommentMatchers.add(matcher); + } } else { - commentMatchers = new ArrayList(commentStrings.size()); - for (String comment : commentStrings) { - Matcher matcher = getMatcher(comment); - commentMatchers.add(matcher); - } + // create only one Matcher for the global comment pattern. + myCommentMatchers.clear(); + myCommentMatchers.add((getMatcher(mySettings.getGlobalCommentPattern()))); } } @@ -78,7 +78,7 @@ public class CommentUtil { * any leading space. */ private Matcher getMatcher(String comment) { - StringBuffer sb = new StringBuffer(comment); + StringBuilder sb = new StringBuilder(comment); /** * remove any literal newline characters or escaped equivalent ('\n') at beginning of comment. */ @@ -122,20 +122,19 @@ public class CommentUtil { } private void createCommentPatternList() { - commentStrings = new ArrayList(); - for (Rule rule : settings.getClassOrderAttributeList()) { - rule.addCommentPatternsToList(commentStrings); + for (Rule rule : mySettings.getClassOrderAttributeList()) { + rule.addCommentPatternsToList(myCommentStrings); } - for (Rule rule : settings.getItemOrderAttributeList()) { - rule.addCommentPatternsToList(commentStrings); + for (Rule rule : mySettings.getItemOrderAttributeList()) { + rule.addCommentPatternsToList(myCommentStrings); } - settings.getExtractedMethodsSettings().addCommentPatternsToList(commentStrings); + mySettings.getExtractedMethodsSettings().addCommentPatternsToList(myCommentStrings); } /** * Calculate the apparent length of a string if tabs are expanded. * Leading tabs are no problem; embedded tabs would be, if the %FS% fill string expansions are not multiples of - * "%FS%".length() == 4, because after expansion the embedded tabs would misalign. However, I'm not going to + * "%FS%".length() == 4, because after expansion the embedded tabs would mis-align. However, I'm not going to * address that yet. (This is just to fix Thomas Singer's bug with leading tab.) * * @param s @@ -171,9 +170,9 @@ public class CommentUtil { int tabSize, String fillString) { - StringBuffer result = new StringBuffer(comment.length() * 2); + StringBuilder result = new StringBuilder(comment.length() * 2); int EOLindex = 0; - StringBuffer fillChars = new StringBuffer(); + StringBuilder fillChars = new StringBuilder(); if (fillString.length() == 0) { fillString = " "; // fill with spaces if no pattern supplied } diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy b/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy index a0667d6e1593..13553851cfd5 100644 --- a/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy +++ b/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy @@ -27,6 +27,7 @@ import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import com.wrq.rearranger.settings.RearrangerSettings import org.jetbrains.annotations.NotNull import org.jetbrains.annotations.Nullable +import com.wrq.rearranger.settings.attributeGroups.FieldAttributes /** JUnit tests for the rearranger plugin. */ class RearrangerTest extends LightCodeInsightFixtureTestCase { @@ -46,26 +47,21 @@ class RearrangerTest extends LightCodeInsightFixtureTestCase { mySettings.showParameterNames = true mySettings.showParameterTypes = true mySettings.showRules = true - mySettings.rearrangeInnerClasses =true + mySettings.rearrangeInnerClasses = true } public final void testNoRearrangement() throws Exception { doTest('RearrangementTest', 'NoRearrangementResult1') } -// public final void testPublicFieldRearrangement() throws Exception { -// configureByFile("/com/wrq/rearranger/RearrangementTest.java"); -// final PsiFile file = getFile(); -// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); -// final FieldAttributes fa; -// fa = new FieldAttributes(); -// fa.getPlAttr().setPlPublic(true); -// rs.addItem(fa, 0); -// final RearrangerActionHandler rah = new RearrangerActionHandler(); -// rah.rearrangeDocument(getProject(), file, rs, doc); -// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult2.java"); -// } -// + public final void testPublicFieldRearrangement() throws Exception { + doTest('RearrangementTest', 'RearrangementResult2') { + def attributes = new FieldAttributes() + attributes.protectionLevelAttributes.plPublic = true + mySettings.addItem(attributes, 0) + } + } + // public final void testNotPublicFieldRearrangement() throws Exception { // configureByFile("/com/wrq/rearranger/RearrangementTest.java"); // final PsiFile file = getFile(); @@ -2178,8 +2174,11 @@ class RearrangerTest extends LightCodeInsightFixtureTestCase { // super.checkResultByFile("/com/wrq/rearranger/BitFieldResult.java"); // } - private void doTest(@NotNull String srcFileName, @Nullable String expectedResultFileName) { + private void doTest(@NotNull String srcFileName, @Nullable String expectedResultFileName, @Nullable Closure adjustment = null) { myFixture.configureByFile("${srcFileName}.java") + if (adjustment) { + adjustment.call() + } ApplicationManager.application.runWriteAction { new RearrangerActionHandler().rearrangeDocument(myFixture.project, myFixture.file, mySettings, myFixture.editor.document); } diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributesTest.java b/plugins/rearranger/test/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributesTest.java index ccb6a4281ad3..e854f418c2e7 100644 --- a/plugins/rearranger/test/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributesTest.java +++ b/plugins/rearranger/test/src/com/wrq/rearranger/settings/attributeGroups/MethodAttributesTest.java @@ -14,7 +14,7 @@ public class MethodAttributesTest public void testToString() throws Exception { ma = new MethodAttributes(); // test various combinations of min/max parameters, name, and return type. - ma.getPlAttr().setPlPublic(true); + ma.getProtectionLevelAttributes().setPlPublic(true); // min = ? max = ? name = ? return = ? setma(false, 0, false, 0, null, null, "public methods"); // min = 1 max = ? name = ? return = ? @@ -57,8 +57,8 @@ public class MethodAttributesTest ma.getMinParamsAttr().setValue(min); ma.getMaxParamsAttr().setMatch(maxMatch); ma.getMaxParamsAttr().setValue(max); - ma.getNameAttr().setMatch(name != null); - ma.getNameAttr().setExpression(name); + ma.getNameAttribute().setMatch(name != null); + ma.getNameAttribute().setExpression(name); ma.getReturnTypeAttr().setMatch(returnValue != null); ma.getReturnTypeAttr().setExpression(returnValue); assertEquals("wrong description", description, ma.toString()); diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult2.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult2.java index 186f0581ef94..1c4b9471883d 100644 --- a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult2.java +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult2.java @@ -10,8 +10,8 @@ public class RearrangementTest { /** field 1. */ private int field1; private int field2; - final int field5 = 5; - protected int field6 = 6; + final int field5 = 5; + protected int field6 = 6; /** method 1 comment. */ void method1() { From 7f914d8d82552eaf672556d1d68c49b817cef126 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 15 May 2012 13:29:47 +0400 Subject: [PATCH 11/61] IDEA-86088 Fix title in Local Changes Refresh dialog for cherry-pick. --- plugins/git4idea/src/git4idea/history/browser/CherryPicker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java b/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java index 13491fd91270..52c77d4516cb 100644 --- a/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java +++ b/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java @@ -212,7 +212,7 @@ public class CherryPicker { public void run() { changeList.set(createChangeList(changes, commitMessage)); } - }, InvokeAfterUpdateMode.SYNCHRONOUS_NOT_CANCELLABLE, "", + }, InvokeAfterUpdateMode.SYNCHRONOUS_NOT_CANCELLABLE, "Cherry-pick", new Consumer() { public void consume(VcsDirtyScopeManager vcsDirtyScopeManager) { vcsDirtyScopeManager.filePathsDirty(paths, null); From 4fa7cf781927f3c32c8eb052868372ee184dbc4c Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 15 May 2012 15:15:29 +0400 Subject: [PATCH 12/61] GitQuickListContentProvider: return "Commit File" and remove "Fetch". * Fetch is rarely used since Update Project fetches all branches of the current remote. * Commit File is used by some people. * Removing Commit File broke the shortcut numbers sequence which people were used to. --- .../src/git4idea/actions/GitQuickListContentProvider.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/git4idea/src/git4idea/actions/GitQuickListContentProvider.java b/plugins/git4idea/src/git4idea/actions/GitQuickListContentProvider.java index 4c72d48e355b..6771129b7fbb 100644 --- a/plugins/git4idea/src/git4idea/actions/GitQuickListContentProvider.java +++ b/plugins/git4idea/src/git4idea/actions/GitQuickListContentProvider.java @@ -47,14 +47,16 @@ public class GitQuickListContentProvider implements VcsQuickListContentProvider actions.add(new Separator(activeVcs.getDisplayName())); add("CheckinProject", manager, actions); + add("CheckinFiles", manager, actions); add("ChangesView.Rollback", manager, actions); + + addSeparator(actions); add("Vcs.ShowTabbedFileHistory", manager, actions); add("Annotate", manager, actions); add("Compare.SameVersion", manager, actions); addSeparator(actions); add("Git.Branches", manager, actions); - add("Git.Fetch", manager, actions); add("Git.Push", manager, actions); add("Git.Stash", manager, actions); add("Git.Unstash", manager, actions); From 40a8b3f9a9d0a91b6e92b55edb202ac5400a2af5 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 15 May 2012 15:54:23 +0400 Subject: [PATCH 13/61] IDEA-86085 MultipleFileMergeDialog: resolve initial focus problem, set the default button. * Make "Merge" button default. * Make the table to be preferred component to solve the issue with focus being left in the editor. --- .../vcs/merge/MultipleFileMergeDialog.form | 2 +- .../vcs/merge/MultipleFileMergeDialog.java | 21 ++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.form b/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.form index 38e9bfe42b08..15724dc45ceb 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.form +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.form @@ -37,7 +37,7 @@ - + diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java index 52fd4fce9305..4959cf997cf3 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java @@ -151,11 +151,6 @@ public class MultipleFileMergeDialog extends DialogWrapper { acceptRevision(false); } }); - myMergeButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - showMergeDialog(); - } - }); myTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { public void valueChanged(final ListSelectionEvent e) { updateButtonState(); @@ -327,6 +322,22 @@ public class MultipleFileMergeDialog extends DialogWrapper { MergeVersion.MergeDocumentVersion.reportProjectFileChangeIfNeeded(myProject, file); } + private void createUIComponents() { + Action mergeAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + showMergeDialog(); + } + }; + mergeAction.putValue(DEFAULT_ACTION, Boolean.TRUE); + myMergeButton = createJButtonForAction(mergeAction); + } + + @Override + public JComponent getPreferredFocusedComponent() { + return myTable; + } + private static String decodeContent(final VirtualFile file, final byte[] content) { return StringUtil.convertLineSeparators(CharsetToolkit.bytesToString(content, file.getCharset())); } From 612d3eefcc4d008b54db343b57bd4fb47509b28e Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 15 May 2012 15:44:42 +0400 Subject: [PATCH 14/61] hide additional project scope ( IDEA-86057) --- .../analysis/BaseAnalysisActionDialog.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/analysis/BaseAnalysisActionDialog.java b/platform/lang-impl/src/com/intellij/analysis/BaseAnalysisActionDialog.java index d6948196e6a1..9c503fd61774 100644 --- a/platform/lang-impl/src/com/intellij/analysis/BaseAnalysisActionDialog.java +++ b/platform/lang-impl/src/com/intellij/analysis/BaseAnalysisActionDialog.java @@ -90,7 +90,7 @@ public class BaseAnalysisActionDialog extends DialogWrapper { myAnalysisOptions.ANALYZE_TEST_SOURCES = scope.isAnalyzeTestsByDefault(); } myProject = project; - myFileName = scope.getShortenName(); + myFileName = scope.getScopeType() == AnalysisScope.PROJECT || scope.getScopeType() == AnalysisScope.MODULE ? null : scope.getShortenName(); myModuleName = moduleName; myRememberScope = rememberScope; myAnalysisNoon = analysisNoon; @@ -141,8 +141,12 @@ public class BaseAnalysisActionDialog extends DialogWrapper { myChangeLists.setVisible(hasVCS); //file/package/directory/module scope - myFileButton.setText(myFileName); - myFileButton.setMnemonic(myFileName.charAt(getSelectedScopeMnemonic())); + if (myFileName != null) { + myFileButton.setText(myFileName); + myFileButton.setMnemonic(myFileName.charAt(getSelectedScopeMnemonic())); + } else { + myFileButton.setVisible(false); + } VirtualFile file = PsiUtilBase.getVirtualFile(myContext); ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex(); @@ -165,9 +169,10 @@ public class BaseAnalysisActionDialog extends DialogWrapper { myScopeCombo.init(myProject, searchInLib, true, preselect); //correct selection - myProjectButton.setSelected(myRememberScope && myAnalysisOptions.SCOPE_TYPE == AnalysisScope.PROJECT); - myFileButton.setSelected(!myRememberScope || - myAnalysisOptions.SCOPE_TYPE != AnalysisScope.PROJECT && !useModuleScope && myAnalysisOptions.SCOPE_TYPE != AnalysisScope.CUSTOM && !useUncommitedFiles); + myProjectButton.setSelected(myRememberScope && myAnalysisOptions.SCOPE_TYPE == AnalysisScope.PROJECT || myFileName == null); + myFileButton.setSelected(myFileName != null && + (!myRememberScope || + myAnalysisOptions.SCOPE_TYPE != AnalysisScope.PROJECT && !useModuleScope && myAnalysisOptions.SCOPE_TYPE != AnalysisScope.CUSTOM && !useUncommitedFiles)); myScopeCombo.setEnabled(myCustomScopeButton.isSelected()); From b66e463eb62c8dc6a2e3f267f08dc616ec1c77f2 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 15 May 2012 16:12:50 +0400 Subject: [PATCH 15/61] clear cached installation status in place, otherwise it would be cleared after leaving modal context only (IDEA-86090) --- .../intellij/ide/plugins/PluginInstaller.java | 1 + .../ide/plugins/PluginManagerMain.java | 23 +++++++------------ 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java index 08cc5c2d995f..069c6274969e 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java @@ -67,6 +67,7 @@ public class PluginInstaller { Messages.showErrorDialog(pluginNode.getName() + ": " + e.getMessage(), CommonBundle.message("title.error")); } }); + return false; } } return result; diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java index 4d533fc3a724..a074c9363748 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java @@ -300,22 +300,15 @@ public abstract class PluginManagerMain implements Disposable { ProgressManager.getInstance().run(new Task.Backgroundable(null, IdeBundle.message("progress.download.plugins"), true) { @Override public void run(@NotNull ProgressIndicator indicator) { - if (PluginInstaller.prepareToInstall(plugins, allPlugins)) { - ApplicationManager.getApplication().invokeLater(onSuccess); - result[0] = true; + try { + if (PluginInstaller.prepareToInstall(plugins, allPlugins)) { + ApplicationManager.getApplication().invokeLater(onSuccess); + result[0] = true; + } + } + finally { + cleanup.run(); } - } - - @Override - public void onCancel() { - cleanup.run(); - super.onCancel(); - } - - @Override - public void onSuccess() { - super.onSuccess(); - cleanup.run(); } }); } From fb40f6109591285ec9a2a61d7f57a3b5f71306c8 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 15 May 2012 14:22:27 +0200 Subject: [PATCH 16/61] NPE in case of default project --- .../intellij/execution/ui/layout/impl/RunnerContentUi.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java index b3519b762f96..1b6198e808e6 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -258,7 +258,10 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac Disposer.register((Disposable)myRunnerUi, manager); manager.getComponent(); } else { - DockManager.getInstance(myProject).register(this); + final DockManager dockManager = DockManager.getInstance(myProject); + if (dockManager != null) { //default project + dockManager.register(this); + } } } From 09cc895da6007e1033135ad2e49e223591b7e067 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Tue, 15 May 2012 16:26:00 +0400 Subject: [PATCH 17/61] IDEA-85100 Deleting wrapped lines with Ctrl+Y doen't work properly with "soft wrapped" lines Correct processing for the empty document --- .../codeInsight/DuplicateActionTest.groovy | 17 ++++++++++++++++- .../openapi/editor/actions/DuplicateAction.java | 5 +++++ .../editor/actions/DuplicateLinesAction.java | 6 ++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/DuplicateActionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/DuplicateActionTest.groovy index 00e1a2a41cf0..fe9ced59cc21 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/DuplicateActionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/DuplicateActionTest.groovy @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.codeInsight; @@ -14,7 +29,7 @@ xxx } public void testEmpty() { - doTest '', "txt", '\n' + doTest '', "txt", '' } private void doTest(String before, @NonNls String ext, String after) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java index 72a05fb0fc29..551d8efcc8d9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java @@ -31,6 +31,7 @@ import com.intellij.openapi.editor.actionSystem.EditorAction; import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler; import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.util.Pair; +import org.jetbrains.annotations.Nullable; public class DuplicateAction extends EditorAction { public DuplicateAction() { @@ -68,6 +69,7 @@ public class DuplicateAction extends EditorAction { } } + @Nullable static Pair duplicateLinesRange(Editor editor, Document document, VisualPosition rangeStart, VisualPosition rangeEnd) { Pair lines = EditorUtil.calcSurroundingRange(editor, rangeStart, rangeEnd); int offset = editor.getCaretModel().getOffset(); @@ -76,6 +78,9 @@ public class DuplicateAction extends EditorAction { LogicalPosition nextLineStart = lines.second; int start = editor.logicalPositionToOffset(lineStart); int end = editor.logicalPositionToOffset(nextLineStart); + if (end <= start) { + return null; + } String s = document.getCharsSequence().subSequence(start, end).toString(); final int lineToCheck = nextLineStart.line - 1; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateLinesAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateLinesAction.java index fc3c86c50aed..2560098f9902 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateLinesAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateLinesAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,7 +40,9 @@ public class DuplicateLinesAction extends EditorAction { VisualPosition rangeEnd = editor.offsetToVisualPosition(Math.max(selStart, selEnd)); final Pair copiedRange = DuplicateAction.duplicateLinesRange(editor, editor.getDocument(), rangeStart, rangeEnd); - editor.getSelectionModel().setSelection(copiedRange.first, copiedRange.second); + if (copiedRange != null) { + editor.getSelectionModel().setSelection(copiedRange.first, copiedRange.second); + } } else { VisualPosition caretPos = editor.getCaretModel().getVisualPosition(); From b19753d01208c51bdaed4ffb555f799ce073d587 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 15 May 2012 17:48:30 +0400 Subject: [PATCH 18/61] correct exit code --- .../intellij/refactoring/rename/inplace/InplaceRefactoring.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java index b3f0a517a0d9..9439abe27109 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java @@ -252,7 +252,7 @@ public abstract class InplaceRefactoring { if (oldDocument != myEditor.getDocument()) { final int exitCode = Messages.showYesNoCancelDialog(myProject, e.getMessage(), getCommandName(), "Navigate to Started", "Cancel Started", "Cancel", Messages.getErrorIcon()); - if (exitCode == -1) return true; + if (exitCode == Messages.CANCEL) return true; navigateToAlreadyStarted(oldDocument, exitCode); return true; } From 460756a8377b557fa4585d9c689584711c619ad6 Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Wed, 9 May 2012 06:34:21 +0400 Subject: [PATCH 19/61] breakpoints dialog removed. initial --- .../debugger/ui/JavaDebuggerSupport.java | 22 +- .../ui/breakpoints/BreakpointFactory.java | 51 +- .../intellij/ui/popup/util/DetailView.java | 41 ++ .../intellij/ui/popup/util/ItemWrapper.java | 43 ++ .../intellij/ide/bookmarks/BookmarkItem.java | 121 +++++ .../bookmarks/actions/BookmarksAction.java | 503 ++---------------- .../actions/DeleteBookmarkAction.java | 62 +++ .../EditBookmarkDescriptionAction.java | 83 +++ .../actions/MoveBookmarkDownAction.java | 66 +++ .../actions/MoveBookmarkUpAction.java | 58 ++ .../ui/popup/util/DetailViewImpl.java | 133 +++++ .../popup/util/MasterDetailPopupBuilder.java | 234 ++++++++ .../breakpoints/XBreakpointType.java | 3 + .../breakpoints/ui/BreakpointItem.java | 30 ++ .../actions/ViewBreakpointsActionNew.java | 68 +++ .../ui/BreakpointPanelProvider.java | 2 + .../BreakpointsMasterDetailPopupFactory.java | 100 ++++ .../ui/XBreakpointPanelProvider.java | 52 ++ 18 files changed, 1198 insertions(+), 474 deletions(-) create mode 100644 platform/lang-api/src/com/intellij/ui/popup/util/DetailView.java create mode 100644 platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java create mode 100644 platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java create mode 100644 platform/lang-impl/src/com/intellij/ide/bookmarks/actions/DeleteBookmarkAction.java create mode 100644 platform/lang-impl/src/com/intellij/ide/bookmarks/actions/EditBookmarkDescriptionAction.java create mode 100644 platform/lang-impl/src/com/intellij/ide/bookmarks/actions/MoveBookmarkDownAction.java create mode 100644 platform/lang-impl/src/com/intellij/ide/bookmarks/actions/MoveBookmarkUpAction.java create mode 100644 platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java create mode 100644 platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java create mode 100644 platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java create mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ViewBreakpointsActionNew.java create mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java index 6d50a9264241..bb0d0d5a58ca 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java @@ -19,13 +19,9 @@ import com.intellij.debugger.DebuggerManagerEx; import com.intellij.debugger.actions.*; import com.intellij.debugger.impl.DebuggerContextImpl; import com.intellij.debugger.settings.*; -import com.intellij.debugger.ui.breakpoints.Breakpoint; -import com.intellij.debugger.ui.breakpoints.BreakpointFactory; -import com.intellij.debugger.ui.breakpoints.BreakpointPanel; -import com.intellij.debugger.ui.breakpoints.BreakpointWithHighlighter; +import com.intellij.debugger.ui.breakpoints.*; import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.markup.GutterIconRenderer; import com.intellij.openapi.editor.markup.RangeHighlighter; @@ -33,6 +29,7 @@ import com.intellij.openapi.options.Configurable; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.util.Key; import com.intellij.xdebugger.AbstractDebuggerSession; import com.intellij.xdebugger.impl.DebuggerSupport; import com.intellij.xdebugger.impl.actions.DebuggerActionHandler; @@ -40,6 +37,7 @@ import com.intellij.xdebugger.impl.actions.DebuggerToggleActionHandler; import com.intellij.xdebugger.impl.actions.EditBreakpointActionHandler; import com.intellij.xdebugger.impl.actions.MarkObjectActionHandler; import com.intellij.xdebugger.impl.breakpoints.ui.AbstractBreakpointPanel; +import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointPanelProvider; import com.intellij.xdebugger.impl.evaluate.quick.common.QuickEvaluateHandler; import com.intellij.xdebugger.impl.settings.DebuggerSettingsPanelProvider; @@ -187,7 +185,7 @@ public class JavaDebuggerSupport extends DebuggerSupport { @NotNull public Collection> getBreakpointPanels(@NotNull final Project project, @NotNull final DialogWrapper parentDialog) { List> panels = new ArrayList>(); - final BreakpointFactory[] allFactories = ApplicationManager.getApplication().getExtensions(BreakpointFactory.EXTENSION_POINT_NAME); + final BreakpointFactory[] allFactories = BreakpointFactory.getBreakpointFactories(); for (BreakpointFactory factory : allFactories) { BreakpointPanel panel = factory.createBreakpointPanel(project, parentDialog); if (panel != null) { @@ -220,6 +218,18 @@ public class JavaDebuggerSupport extends DebuggerSupport { public void onDialogClosed(final Project project) { DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().updateAllRequests(); } + + @Override + public void provideBreakpointItems(Project project, Collection items) { + for (BreakpointFactory breakpointFactory : BreakpointFactory.getBreakpointFactories()) { + Key category = breakpointFactory.getBreakpointCategory(); + Breakpoint[] breakpoints = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().getBreakpoints(category); + + for (Breakpoint breakpoint : breakpoints) { + items.add(breakpointFactory.createBreakpointItem(breakpoint)); + } + } + } } public static class JavaDebuggerSettingsPanelProvider extends DebuggerSettingsPanelProvider { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java index 4829f5866a64..b013e98bbf32 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java @@ -15,12 +15,19 @@ */ package com.intellij.debugger.ui.breakpoints; +import com.intellij.debugger.SourcePosition; import com.intellij.debugger.ui.breakpoints.actions.BreakpointPanelAction; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.Key; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.ColoredListCellRenderer; +import com.intellij.ui.popup.util.DetailView; +import com.intellij.ui.popup.util.DetailViewImpl; +import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; import org.jdom.Element; import org.jetbrains.annotations.Nullable; @@ -32,6 +39,10 @@ import javax.swing.*; public abstract class BreakpointFactory { public static final ExtensionPointName EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.debugger.breakpointFactory"); + public static BreakpointFactory[] getBreakpointFactories() { + return ApplicationManager.getApplication().getExtensions(EXTENSION_POINT_NAME); + } + public abstract Breakpoint createBreakpoint(Project project, final Element element); public abstract Key getBreakpointCategory(); @@ -51,7 +62,7 @@ public abstract class BreakpointFactory { @Nullable public static BreakpointFactory getInstance(Key category) { - final BreakpointFactory[] allFactories = ApplicationManager.getApplication().getExtensions(BreakpointFactory.EXTENSION_POINT_NAME); + final BreakpointFactory[] allFactories = getBreakpointFactories(); for (final BreakpointFactory factory : allFactories) { if (category.equals(factory.getBreakpointCategory())) { return factory; @@ -69,4 +80,42 @@ public abstract class BreakpointFactory { public abstract BreakpointPropertiesPanel createBreakpointPropertiesPanel(Project project, boolean compact); protected abstract BreakpointPanelAction[] createBreakpointPanelActions(Project project, DialogWrapper parentDialog); + + public BreakpointItem createBreakpointItem(final Breakpoint breakpoint) { + return new BreakpointItem() { + @Override + public void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected) { + renderer.setIcon(breakpoint.getIcon()); + } + + @Override + public void updateMnemonicLabel(JLabel label) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void execute(Project project) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String speedSearchText() { + return breakpoint.getDisplayName(); + } + + @Override + public String footerText() { + return breakpoint.getDisplayName(); + } + + @Override + public void updateDetailView(DetailView panel) { + if (breakpoint instanceof LineBreakpoint) { + SourcePosition sourcePosition = ((LineBreakpoint)breakpoint).getSourcePosition(); + VirtualFile virtualFile = sourcePosition.getFile().getVirtualFile(); + panel.navigateInPreviewEditor(virtualFile,new LogicalPosition(sourcePosition.getLine(), 0)); + } + } + }; + } } diff --git a/platform/lang-api/src/com/intellij/ui/popup/util/DetailView.java b/platform/lang-api/src/com/intellij/ui/popup/util/DetailView.java new file mode 100644 index 000000000000..9063521e29d1 --- /dev/null +++ b/platform/lang-api/src/com/intellij/ui/popup/util/DetailView.java @@ -0,0 +1,41 @@ +/* + * 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.ui.popup.util; + +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.LogicalPosition; +import com.intellij.openapi.vfs.VirtualFile; + +import javax.swing.*; + +/** + * Created with IntelliJ IDEA. + * User: zajac + * Date: 5/9/12 + * Time: 5:34 AM + * To change this template use File | Settings | File Templates. + */ +public interface DetailView { + void updateWithItem(ItemWrapper wrapper); + + Editor getEditor(); + + void navigateInPreviewEditor(VirtualFile file, LogicalPosition positionToNavigate); + + JPanel getDetailPanel(); + + void setDetailPanel(JPanel panel); +} diff --git a/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java b/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java new file mode 100644 index 000000000000..3aa7a30dee80 --- /dev/null +++ b/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java @@ -0,0 +1,43 @@ +/* + * 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.ui.popup.util; + +import com.intellij.openapi.project.Project; +import com.intellij.ui.ColoredListCellRenderer; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +/** +* Created with IntelliJ IDEA. +* User: zajac +* Date: 5/6/12 +* Time: 2:05 AM +* To change this template use File | Settings | File Templates. +*/ +public interface ItemWrapper { + void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected); + void updateMnemonicLabel(JLabel label); + + void execute(Project project); + + String speedSearchText(); + + @Nullable + String footerText(); + + void updateDetailView(DetailView panel); +} diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java new file mode 100644 index 000000000000..5dcf7f015e37 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java @@ -0,0 +1,121 @@ +/* + * 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.ide.bookmarks; + +import com.intellij.openapi.editor.LogicalPosition; +import com.intellij.openapi.editor.markup.EffectType; +import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.openapi.project.Project; +import com.intellij.ui.popup.util.DetailView; +import com.intellij.ui.popup.util.DetailViewImpl; +import com.intellij.ui.popup.util.ItemWrapper; +import com.intellij.openapi.util.Iconable; +import com.intellij.openapi.vcs.FileStatus; +import com.intellij.openapi.vcs.FileStatusManager; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.intellij.ui.ColoredListCellRenderer; +import com.intellij.ui.FileColorManager; +import com.intellij.ui.SimpleTextAttributes; + +import javax.swing.*; +import java.awt.*; + +/** +* Created with IntelliJ IDEA. +* User: zajac +* Date: 5/6/12 +* Time: 2:06 AM +* To change this template use File | Settings | File Templates. +*/ +public class BookmarkItem implements ItemWrapper { + private final Bookmark myBookmark; + + public BookmarkItem(Bookmark bookmark) { + myBookmark = bookmark; + } + + public Bookmark getBookmark() { + return myBookmark; + } + + public void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected) { + VirtualFile file = myBookmark.getFile(); + + PsiManager psiManager = PsiManager.getInstance(project); + + PsiElement fileOrDir = file.isDirectory() ? psiManager.findDirectory(file) : psiManager.findFile(file); + if (fileOrDir != null) { + renderer.setIcon(fileOrDir.getIcon(Iconable.ICON_FLAG_CLOSED)); + } + + + FileStatus fileStatus = FileStatusManager.getInstance(project).getStatus(file); + TextAttributes attributes = new TextAttributes(fileStatus.getColor(), null, null, EffectType.LINE_UNDERSCORE, Font.PLAIN); + renderer.append(file.getName(), SimpleTextAttributes.fromTextAttributes(attributes)); + if (myBookmark.getLine() >= 0) { + renderer.append(":", SimpleTextAttributes.GRAYED_ATTRIBUTES); + renderer.append(String.valueOf(myBookmark.getLine() + 1), SimpleTextAttributes.GRAYED_ATTRIBUTES); + } + + if (!selected) { + FileColorManager colorManager = FileColorManager.getInstance(project); + if (fileOrDir instanceof PsiFile) { + Color color = colorManager.getRendererBackground((PsiFile)fileOrDir); + if (color != null) { + renderer.setBackground(color); + } + } + } + + String description = myBookmark.getDescription(); + if (description != null) { + renderer.append(" " + description, SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES); + } + } + + public void updateMnemonicLabel(JLabel label) { + final char mnemonic = myBookmark.getMnemonic(); + if (mnemonic != 0) { + label.setText(Character.toString(mnemonic) + '.'); + } + else { + label.setText(""); + } + } + + public String speedSearchText() { + return myBookmark.getFile().getName() + " " + myBookmark.getDescription(); + } + + public void execute(Project project) { + myBookmark.navigate(); + } + + public String footerText() { + return myBookmark.getFile().getPresentableUrl(); + } + + @Override + public void updateDetailView(final DetailView panel) { + VirtualFile file = myBookmark.getFile(); + LogicalPosition positionToNavigate = new LogicalPosition(myBookmark.getLine(), 0); + + panel.navigateInPreviewEditor(file, positionToNavigate); + } +} diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java index 53c9d8c4e43a..67ca0576093b 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java @@ -20,58 +20,34 @@ package com.intellij.ide.bookmarks.actions; import com.intellij.ide.bookmarks.Bookmark; +import com.intellij.ide.bookmarks.BookmarkItem; import com.intellij.ide.bookmarks.BookmarkManager; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.*; -import com.intellij.openapi.editor.colors.EditorColorsManager; -import com.intellij.openapi.editor.ex.EditorEx; -import com.intellij.openapi.editor.highlighter.EditorHighlighter; -import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory; -import com.intellij.openapi.editor.markup.EffectType; -import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.InputValidator; -import com.intellij.openapi.ui.Messages; +import com.intellij.ui.popup.util.ItemWrapper; import com.intellij.openapi.ui.popup.JBPopup; -import com.intellij.openapi.ui.popup.PopupChooserBuilder; -import com.intellij.openapi.util.IconLoader; -import com.intellij.openapi.util.Iconable; -import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.vcs.FileStatus; -import com.intellij.openapi.vcs.FileStatusManager; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.ToolWindowManager; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiManager; import com.intellij.ui.*; import com.intellij.ui.components.JBList; +import com.intellij.ui.popup.util.MasterDetailPopupBuilder; import com.intellij.ui.speedSearch.FilteringListModel; -import com.intellij.util.Alarm; -import com.intellij.util.Function; import com.intellij.util.ui.UIUtil; -import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; import java.awt.*; -import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; -import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; // TODO: remove duplication with BaseShowRecentFilesAction, there's quite a bit of it -public class BookmarksAction extends AnAction implements DumbAware { - private static final Color BORDER_COLOR = Gray._135; - - private final Alarm myPreviewUpdateAlarm = new Alarm(); +public class BookmarksAction extends AnAction implements DumbAware, MasterDetailPopupBuilder.Delegate { @Override public void update(AnActionEvent e) { @@ -89,177 +65,50 @@ public class BookmarksAction extends AnAction implements DumbAware { final DefaultListModel model = buildModel(project); - - final JLabel pathLabel = new JLabel(" "); - pathLabel.setHorizontalAlignment(SwingConstants.RIGHT); - - final Font font = pathLabel.getFont(); - pathLabel.setFont(font.deriveFont((float)10)); - final JBList list = new JBList(model); list.getEmptyText().setText("No Bookmarks"); - - final PreviewPanel previewPanel = new PreviewPanel(project); - - list.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - private String getTitle2Text(String fullText) { - int labelWidth = pathLabel.getWidth(); - if (fullText == null || fullText.length() == 0) return " "; - while (pathLabel.getFontMetrics(pathLabel.getFont()).stringWidth(fullText) > labelWidth) { - int sep = fullText.indexOf(File.separatorChar, 4); - if (sep < 0) return fullText; - fullText = "..." + fullText.substring(sep); - } - - return fullText; - } - - public void valueChanged(final ListSelectionEvent e) { - //noinspection SSBasedInspection - SwingUtilities.invokeLater(new Runnable() { - public void run() { - updatePathLabel(); - } - }); - } - - private void updatePreviewPanel(final ItemWrapper wrapper) { - myPreviewUpdateAlarm.cancelAllRequests(); - myPreviewUpdateAlarm.addRequest(new Runnable() { - public void run() { - previewPanel.updateWithItem(wrapper); - } - }, 300); - } - - private void updatePathLabel() { - final Object[] values = list.getSelectedValues(); - if (values != null && values.length == 1) { - ItemWrapper wrapper = (ItemWrapper)values[0]; - pathLabel.setText(getTitle2Text(wrapper.footerText())); - updatePreviewPanel(wrapper); - } - else { - updatePreviewPanel(null); - pathLabel.setText(" "); - } - } - }); - - Runnable runnable = new Runnable() { - public void run() { - IdeFocusManager.getInstance(project).doWhenFocusSettlesDown(new Runnable() { - public void run() { - Object[] values = list.getSelectedValues(); - - if (values.length == 1) { - ((ItemWrapper)values[0]).execute(project); - } - else { - for (Object value : values) { - if (value instanceof BookmarkItem) { - ((BookmarkItem)value).execute(project); - } - } - } - } - }); - } - }; - - if (list.getModel().getSize() == 0) { - list.clearSelection(); - } - list.setCellRenderer(new ItemRenderer(project)); - - JPanel footerPanel = new JPanel(new BorderLayout()) { - @Override - protected void paintComponent(Graphics g) { - super.paintComponent(g); - g.setColor(BORDER_COLOR); - g.drawLine(0, 0, getWidth(), 0); - } - }; - - footerPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); - footerPanel.add(pathLabel); - - DefaultActionGroup actions = new DefaultActionGroup(); EditBookmarkDescriptionAction editDescriptionAction = new EditBookmarkDescriptionAction(project, list); + DefaultActionGroup actions = new DefaultActionGroup(); actions.add(editDescriptionAction); actions.add(new DeleteBookmarkAction(project, list)); actions.add(new MoveBookmarkUpAction(project, list)); actions.add(new MoveBookmarkDownAction(project, list)); - ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar("", actions, true); - actionToolbar.setReservePlaceAutoPopupIcon(false); - actionToolbar.setMinimumButtonSize(new Dimension(20, 20)); - final JComponent toolBar = actionToolbar.getComponent(); - toolBar.setOpaque(false); - - final JBPopup popup = new PopupChooserBuilder(list). - setTitle("Bookmarks"). - setMovable(true). - setAutoselectOnMouseMove(false). - setSettingButton(toolBar). - setSouthComponent(footerPanel). - setEastComponent(previewPanel). - setItemChoosenCallback(runnable). - setMayBeParent(true). - setFilteringEnabled(new Function() { - public String fun(Object o) { - return ((ItemWrapper)o).speedSearchText(); - } - }).createPopup(); - - list.addKeyListener(new KeyAdapter() { - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_DELETE) { - int index = list.getSelectedIndex(); - if (index == -1 || index >= list.getModel().getSize()) { - return; - } - Object[] values = list.getSelectedValues(); - for (Object value : values) { - if (value instanceof BookmarkItem) { - BookmarkItem item = (BookmarkItem)value; - model.removeElement(item); - if (model.getSize() > 0) { - if (model.getSize() == index) { - list.setSelectedIndex(model.getSize() - 1); - } - else if (model.getSize() > index) { - list.setSelectedIndex(index); - } - } - else { - list.clearSelection(); - } - BookmarkManager.getInstance(project).removeBookmark(item.myBookmark); - } - } - } - else if (e.getModifiersEx() == 0) { - char mnemonic = e.getKeyChar(); - final Bookmark bookmark = BookmarkManager.getInstance(project).findBookmarkForMnemonic(mnemonic); - if (bookmark != null) { - popup.cancel(); - IdeFocusManager.getInstance(project).doWhenFocusSettlesDown(new Runnable() { - public void run() { - bookmark.navigate(); - } - }); - } - } - } - }); + final JBPopup popup = new MasterDetailPopupBuilder(project). + setActionsGroup(actions). + setList(list). + setDelegate(this).createMasterDetailPopup(); editDescriptionAction.setPopup(popup); popup.showCenteredInCurrentWindow(project); } + @Override + public String getTitle() { + return "Bookmarks"; + } + + @Override + public void handleMnemonic(KeyEvent e, Project project, JBPopup popup) { + char mnemonic = e.getKeyChar(); + final Bookmark bookmark = BookmarkManager.getInstance(project).findBookmarkForMnemonic(mnemonic); + if (bookmark != null) { + popup.cancel(); + IdeFocusManager.getInstance(project).doWhenFocusSettlesDown(new Runnable() { + public void run() { + bookmark.navigate(); + } + }); + } + } + + @Override + public void itemRemoved(ItemWrapper item, Project project) { + BookmarkManager.getInstance(project).removeBookmark(((BookmarkItem)item).getBookmark()); + } + private static DefaultListModel buildModel(Project project) { final DefaultListModel model = new DefaultListModel(); @@ -270,120 +119,6 @@ public class BookmarksAction extends AnAction implements DumbAware { return model; } - private interface ItemWrapper { - void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected); - void updateMnemonicLabel(JLabel label); - - void execute(Project project); - - String speedSearchText(); - - @Nullable - String footerText(); - - void updatePreviewPanel(PreviewPanel panel); - } - - private static class BookmarkItem implements ItemWrapper { - private final Bookmark myBookmark; - - private BookmarkItem(Bookmark bookmark) { - myBookmark = bookmark; - } - - public void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected) { - VirtualFile file = myBookmark.getFile(); - - PsiManager psiManager = PsiManager.getInstance(project); - - PsiElement fileOrDir = file.isDirectory() ? psiManager.findDirectory(file) : psiManager.findFile(file); - if (fileOrDir != null) { - renderer.setIcon(fileOrDir.getIcon(Iconable.ICON_FLAG_CLOSED)); - } - - - FileStatus fileStatus = FileStatusManager.getInstance(project).getStatus(file); - TextAttributes attributes = new TextAttributes(fileStatus.getColor(), null, null, EffectType.LINE_UNDERSCORE, Font.PLAIN); - renderer.append(file.getName(), SimpleTextAttributes.fromTextAttributes(attributes)); - if (myBookmark.getLine() >= 0) { - renderer.append(":", SimpleTextAttributes.GRAYED_ATTRIBUTES); - renderer.append(String.valueOf(myBookmark.getLine() + 1), SimpleTextAttributes.GRAYED_ATTRIBUTES); - } - - if (!selected) { - FileColorManager colorManager = FileColorManager.getInstance(project); - if (fileOrDir instanceof PsiFile) { - Color color = colorManager.getRendererBackground((PsiFile)fileOrDir); - if (color != null) { - renderer.setBackground(color); - } - } - } - - String description = myBookmark.getDescription(); - if (description != null) { - renderer.append(" " + description, SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES); - } - } - - public void updateMnemonicLabel(JLabel label) { - final char mnemonic = myBookmark.getMnemonic(); - if (mnemonic != 0) { - label.setText(Character.toString(mnemonic) + '.'); - } - else { - label.setText(""); - } - } - - public String speedSearchText() { - return myBookmark.getFile().getName() + " " + myBookmark.getDescription(); - } - - public void execute(Project project) { - myBookmark.navigate(); - } - - public String footerText() { - return myBookmark.getFile().getPresentableUrl(); - } - - public void updatePreviewPanel(final PreviewPanel panel) { - VirtualFile file = myBookmark.getFile(); - Document document = FileDocumentManager.getInstance().getDocument(file); - Project project = panel.myProject; - - if (document != null) { - if (panel.myEditor == null || panel.myEditor.getDocument() != document) { - panel.cleanup(); - panel.myEditor = EditorFactory.getInstance().createViewer(document, project); - EditorHighlighter highlighter = EditorHighlighterFactory.getInstance() - .createEditorHighlighter(file, EditorColorsManager.getInstance().getGlobalScheme(), project); - ((EditorEx)panel.myEditor).setHighlighter(highlighter); - ((EditorEx)panel.myEditor).setFile(file); - - panel.myEditor.getSettings().setAnimatedScrolling(false); - panel.myEditor.getSettings().setRefrainFromScrolling(false); - panel.myEditor.getSettings().setLineNumbersShown(true); - panel.myEditor.getSettings().setFoldingOutlineShown(false); - - panel.add(panel.myEditor.getComponent(), BorderLayout.CENTER); - } - - panel.myEditor.getCaretModel().moveToLogicalPosition(new LogicalPosition(myBookmark.getLine(), 0)); - panel.validate(); - panel.myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER); - } - else { - panel.cleanup(); - - JLabel label = new JLabel("Navigate to selected " + (file.isDirectory() ? "directory " : "file ") + "in Project View"); - label.setHorizontalAlignment(JLabel.CENTER); - panel.add(label); - } - } - } - private static class ItemRenderer extends JPanel implements ListCellRenderer { private final Project myProject; private final ColoredListCellRenderer myRenderer; @@ -476,53 +211,12 @@ public class BookmarksAction extends AnAction implements DumbAware { } } - private static class PreviewPanel extends JPanel { - private final Project myProject; - private Editor myEditor; - private ItemWrapper myWrapper; - - public PreviewPanel(Project project) { - super(new BorderLayout()); - myProject = project; - setPreferredSize(new Dimension(600, 400)); - } - - public void updateWithItem(ItemWrapper wrapper) { - if (myWrapper != wrapper) { - myWrapper = wrapper; - if (wrapper != null) { - wrapper.updatePreviewPanel(this); - } - else { - cleanup(); - repaint(); - } - - revalidate(); - } - } - - private void cleanup() { - removeAll(); - if (myEditor != null) { - EditorFactory.getInstance().releaseEditor(myEditor); - myEditor = null; - } - } - - @Override - public void removeNotify() { - super.removeNotify(); - cleanup(); - } - } - - private static List getSelectedBookmarks(JList list) { + static List getSelectedBookmarks(JList list) { List answer = new ArrayList(); for (Object value : list.getSelectedValues()) { if (value instanceof BookmarkItem) { - answer.add(((BookmarkItem)value).myBookmark); + answer.add(((BookmarkItem)value).getBookmark()); } else { return Collections.emptyList(); @@ -532,135 +226,10 @@ public class BookmarksAction extends AnAction implements DumbAware { return answer; } - private static class EditBookmarkDescriptionAction extends AnAction { - private final JList myList; - private final Project myProject; - private JBPopup myPopup; - - private EditBookmarkDescriptionAction(Project project, JList list) { - super("Edit Description", "Assign short description for the bookmark to be shown along the file name", IconLoader.getIcon("/actions/properties.png")); - myProject = project; - myList = list; - registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(SystemInfo.isMac ? "meta ENTER" : "control ENTER")), list); - } - - @Override - public void update(AnActionEvent e) { - e.getPresentation().setEnabled(getSelectedBookmarks(myList).size() == 1); - } - - @Override - public void actionPerformed(AnActionEvent e) { - Bookmark b = getSelectedBookmarks(myList).get(0); - myPopup.setUiVisible(false); - - String description = Messages - .showInputDialog(myProject, "Enter short bookmark description", "Bookmark Description", Messages.getQuestionIcon(), b.getDescription(), - new InputValidator() { - public boolean checkInput(String inputString) { - return true; - } - - public boolean canClose(String inputString) { - return true; - } - }); - - BookmarkManager.getInstance(myProject).setDescription(b, description); - - myPopup.setUiVisible(true); - myPopup.setSize(myPopup.getContent().getPreferredSize()); - } - - public void setPopup(JBPopup popup) { - myPopup = popup; - } - } - - private static class DeleteBookmarkAction extends AnAction { - private final Project myProject; - private final JList myList; - - private DeleteBookmarkAction(Project project, JList list) { - super("Delete", "Delete current bookmark", IconLoader.getIcon("/general/remove.png")); - myProject = project; - myList = list; - registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke("DELETE")), list); - } - - @Override - public void update(AnActionEvent e) { - e.getPresentation().setEnabled(getSelectedBookmarks(myList).size() > 0); - } - - @Override - public void actionPerformed(AnActionEvent e) { - List bookmarks = getSelectedBookmarks(myList); - ListUtil.removeSelectedItems(myList); - - for (Bookmark bookmark : bookmarks) { - BookmarkManager.getInstance(myProject).removeBookmark(bookmark); - } - } - } - - private static boolean notFiltered(JList list) { + static boolean notFiltered(JList list) { if (!(list.getModel() instanceof FilteringListModel)) return true; final FilteringListModel model = (FilteringListModel)list.getModel(); return model.getOriginalModel().getSize() == model.getSize(); } - private static class MoveBookmarkUpAction extends AnAction { - private final Project myProject; - private final JList myList; - - private MoveBookmarkUpAction(Project project, JList list) { - super("Up", "Move current bookmark up", IconLoader.getIcon("/actions/previousOccurence.png")); - myProject = project; - myList = list; - registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(SystemInfo.isMac ? "meta UP" : "control UP")), list); - } - - @Override - public void update(AnActionEvent e) { - e.getPresentation().setEnabled(notFiltered(myList) && getSelectedBookmarks(myList).size() == 1 && myList.getSelectedIndex() > 0); - } - - @Override - public void actionPerformed(AnActionEvent e) { - ListUtil.moveSelectedItemsUp(myList); - BookmarkManager.getInstance(myProject).moveBookmarkUp(getSelectedBookmarks(myList).get(0)); - } - } - - private static class MoveBookmarkDownAction extends AnAction { - private final Project myProject; - private final JList myList; - - private MoveBookmarkDownAction(Project project, JList list) { - super("Down", "Move current bookmark down", IconLoader.getIcon("/actions/nextOccurence.png")); - myProject = project; - myList = list; - registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(SystemInfo.isMac ? "meta DOWN" : "control DOWN")), list); - } - - @Override - public void update(AnActionEvent e) { - int modelSize = myList.getModel().getSize(); - if (modelSize == 0 || !notFiltered(myList)) { - e.getPresentation().setEnabled(false); - } - else { - int lastIndex = modelSize - 1; - if (!(myList.getModel().getElementAt(lastIndex) instanceof BookmarkItem)) lastIndex--; - e.getPresentation().setEnabled(getSelectedBookmarks(myList).size() == 1 && myList.getSelectedIndex() < lastIndex); - } - } - - @Override - public void actionPerformed(AnActionEvent e) { - ListUtil.moveSelectedItemsDown(myList); - BookmarkManager.getInstance(myProject).moveBookmarkDown(getSelectedBookmarks(myList).get(0)); - } - } } diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/DeleteBookmarkAction.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/DeleteBookmarkAction.java new file mode 100644 index 000000000000..4bf704ff34d6 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/DeleteBookmarkAction.java @@ -0,0 +1,62 @@ +/* + * 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.ide.bookmarks.actions; + +import com.intellij.ide.bookmarks.Bookmark; +import com.intellij.ide.bookmarks.BookmarkManager; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CustomShortcutSet; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.IconLoader; +import com.intellij.ui.ListUtil; + +import javax.swing.*; +import java.util.List; + +/** +* Created with IntelliJ IDEA. +* User: zajac +* Date: 5/6/12 +* Time: 2:09 AM +* To change this template use File | Settings | File Templates. +*/ +class DeleteBookmarkAction extends AnAction { + private final Project myProject; + private final JList myList; + + DeleteBookmarkAction(Project project, JList list) { + super("Delete", "Delete current bookmark", IconLoader.getIcon("/general/remove.png")); + myProject = project; + myList = list; + registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke("DELETE")), list); + } + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setEnabled(BookmarksAction.getSelectedBookmarks(myList).size() > 0); + } + + @Override + public void actionPerformed(AnActionEvent e) { + List bookmarks = BookmarksAction.getSelectedBookmarks(myList); + ListUtil.removeSelectedItems(myList); + + for (Bookmark bookmark : bookmarks) { + BookmarkManager.getInstance(myProject).removeBookmark(bookmark); + } + } +} diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/EditBookmarkDescriptionAction.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/EditBookmarkDescriptionAction.java new file mode 100644 index 000000000000..87203dd12c70 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/EditBookmarkDescriptionAction.java @@ -0,0 +1,83 @@ +/* + * 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.ide.bookmarks.actions; + +import com.intellij.ide.bookmarks.Bookmark; +import com.intellij.ide.bookmarks.BookmarkManager; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CustomShortcutSet; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.InputValidator; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.SystemInfo; + +import javax.swing.*; + +/** +* Created with IntelliJ IDEA. +* User: zajac +* Date: 5/6/12 +* Time: 2:08 AM +* To change this template use File | Settings | File Templates. +*/ +class EditBookmarkDescriptionAction extends AnAction { + private final JList myList; + private final Project myProject; + private JBPopup myPopup; + + EditBookmarkDescriptionAction(Project project, JList list) { + super("Edit Description", "Assign short description for the bookmark to be shown along the file name", IconLoader + .getIcon("/actions/properties.png")); + myProject = project; + myList = list; + registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(SystemInfo.isMac ? "meta ENTER" : "control ENTER")), list); + } + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setEnabled(BookmarksAction.getSelectedBookmarks(myList).size() == 1); + } + + @Override + public void actionPerformed(AnActionEvent e) { + Bookmark b = BookmarksAction.getSelectedBookmarks(myList).get(0); + myPopup.setUiVisible(false); + + String description = Messages + .showInputDialog(myProject, "Enter short bookmark description", "Bookmark Description", Messages.getQuestionIcon(), + b.getDescription(), new InputValidator() { + public boolean checkInput(String inputString) { + return true; + } + + public boolean canClose(String inputString) { + return true; + } + }); + + BookmarkManager.getInstance(myProject).setDescription(b, description); + + myPopup.setUiVisible(true); + myPopup.setSize(myPopup.getContent().getPreferredSize()); + } + + public void setPopup(JBPopup popup) { + myPopup = popup; + } +} diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/MoveBookmarkDownAction.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/MoveBookmarkDownAction.java new file mode 100644 index 000000000000..fd43d4207c07 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/MoveBookmarkDownAction.java @@ -0,0 +1,66 @@ +/* + * 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.ide.bookmarks.actions; + +import com.intellij.ide.bookmarks.BookmarkItem; +import com.intellij.ide.bookmarks.BookmarkManager; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CustomShortcutSet; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.ui.ListUtil; + +import javax.swing.*; + +/** +* Created with IntelliJ IDEA. +* User: zajac +* Date: 5/6/12 +* Time: 2:09 AM +* To change this template use File | Settings | File Templates. +*/ +class MoveBookmarkDownAction extends AnAction { + private final Project myProject; + private final JList myList; + + MoveBookmarkDownAction(Project project, JList list) { + super("Down", "Move current bookmark down", IconLoader.getIcon("/actions/nextOccurence.png")); + myProject = project; + myList = list; + registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(SystemInfo.isMac ? "meta DOWN" : "control DOWN")), list); + } + + @Override + public void update(AnActionEvent e) { + int modelSize = myList.getModel().getSize(); + if (modelSize == 0 || !BookmarksAction.notFiltered(myList)) { + e.getPresentation().setEnabled(false); + } + else { + int lastIndex = modelSize - 1; + if (!(myList.getModel().getElementAt(lastIndex) instanceof BookmarkItem)) lastIndex--; + e.getPresentation().setEnabled(BookmarksAction.getSelectedBookmarks(myList).size() == 1 && myList.getSelectedIndex() < lastIndex); + } + } + + @Override + public void actionPerformed(AnActionEvent e) { + ListUtil.moveSelectedItemsDown(myList); + BookmarkManager.getInstance(myProject).moveBookmarkDown(BookmarksAction.getSelectedBookmarks(myList).get(0)); + } +} diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/MoveBookmarkUpAction.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/MoveBookmarkUpAction.java new file mode 100644 index 000000000000..16d86518bc11 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/MoveBookmarkUpAction.java @@ -0,0 +1,58 @@ +/* + * 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.ide.bookmarks.actions; + +import com.intellij.ide.bookmarks.BookmarkManager; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CustomShortcutSet; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.ui.ListUtil; + +import javax.swing.*; + +/** +* Created with IntelliJ IDEA. +* User: zajac +* Date: 5/6/12 +* Time: 2:09 AM +* To change this template use File | Settings | File Templates. +*/ +class MoveBookmarkUpAction extends AnAction { + private final Project myProject; + private final JList myList; + + MoveBookmarkUpAction(Project project, JList list) { + super("Up", "Move current bookmark up", IconLoader.getIcon("/actions/previousOccurence.png")); + myProject = project; + myList = list; + registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(SystemInfo.isMac ? "meta UP" : "control UP")), list); + } + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setEnabled( + BookmarksAction.notFiltered(myList) && BookmarksAction.getSelectedBookmarks(myList).size() == 1 && myList.getSelectedIndex() > 0); + } + + @Override + public void actionPerformed(AnActionEvent e) { + ListUtil.moveSelectedItemsUp(myList); + BookmarkManager.getInstance(myProject).moveBookmarkUp(BookmarksAction.getSelectedBookmarks(myList).get(0)); + } +} diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java new file mode 100644 index 000000000000..990d1ead0a93 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java @@ -0,0 +1,133 @@ +/* + * 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.ui.popup.util; + +import com.intellij.openapi.editor.*; +import com.intellij.openapi.editor.colors.EditorColorsManager; +import com.intellij.openapi.editor.ex.EditorEx; +import com.intellij.openapi.editor.highlighter.EditorHighlighter; +import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; + +import javax.swing.*; +import java.awt.*; + +/** +* Created with IntelliJ IDEA. +* User: zajac +* Date: 5/6/12 +* Time: 2:04 AM +* To change this template use File | Settings | File Templates. +*/ +public class DetailViewImpl extends JPanel implements DetailView { + private final Project myProject; + private Editor myEditor; + private ItemWrapper myWrapper; + private JPanel myDetailPanel; + + public DetailViewImpl(Project project) { + super(new BorderLayout()); + myProject = project; + setPreferredSize(new Dimension(600, 400)); + } + + @Override + public void updateWithItem(ItemWrapper wrapper) { + if (myWrapper != wrapper) { + myWrapper = wrapper; + if (wrapper != null) { + wrapper.updateDetailView(this); + } + else { + cleanup(); + repaint(); + } + + revalidate(); + } + } + + private void cleanup() { + removeAll(); + if (getEditor() != null) { + EditorFactory.getInstance().releaseEditor(getEditor()); + setEditor(null); + } + } + + @Override + public void removeNotify() { + super.removeNotify(); + cleanup(); + } + + @Override + public Editor getEditor() { + return myEditor; + } + + public void setEditor(Editor editor) { + myEditor = editor; + } + + @Override + public void navigateInPreviewEditor(VirtualFile file, LogicalPosition positionToNavigate) { + Document document = FileDocumentManager.getInstance().getDocument(file); + Project project = myProject; + + if (document != null) { + if (getEditor() == null || getEditor().getDocument() != document) { + cleanup(); + setEditor(EditorFactory.getInstance().createViewer(document, project)); + EditorHighlighter highlighter = EditorHighlighterFactory.getInstance() + .createEditorHighlighter(file, EditorColorsManager.getInstance().getGlobalScheme(), project); + ((EditorEx)getEditor()).setHighlighter(highlighter); + ((EditorEx)getEditor()).setFile(file); + + getEditor().getSettings().setAnimatedScrolling(false); + getEditor().getSettings().setRefrainFromScrolling(false); + getEditor().getSettings().setLineNumbersShown(true); + getEditor().getSettings().setFoldingOutlineShown(false); + + add(getEditor().getComponent(), BorderLayout.CENTER); + } + + getEditor().getCaretModel().moveToLogicalPosition(positionToNavigate); + validate(); + getEditor().getScrollingModel().scrollToCaret(ScrollType.CENTER); + } + else { + cleanup(); + + JLabel label = new JLabel("Navigate to selected " + (file.isDirectory() ? "directory " : "file ") + "in Project View"); + label.setHorizontalAlignment(JLabel.CENTER); + add(label); + } + } + + @Override + public JPanel getDetailPanel() { + return myDetailPanel; + } + + @Override + public void setDetailPanel(JPanel panel) { + myDetailPanel = panel; + add(panel, BorderLayout.SOUTH); + } +} diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java new file mode 100644 index 000000000000..26f193c4926c --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java @@ -0,0 +1,234 @@ +/* + * 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.ui.popup.util; + +import com.intellij.ide.bookmarks.BookmarkItem; +import com.intellij.openapi.actionSystem.ActionGroup; +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.actionSystem.ActionToolbar; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.ui.popup.PopupChooserBuilder; +import com.intellij.openapi.wm.IdeFocusManager; +import com.intellij.ui.Gray; +import com.intellij.ui.components.JBList; +import com.intellij.util.Alarm; +import com.intellij.util.Function; + +import javax.swing.*; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import java.awt.*; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.io.File; + +/** + * Created with IntelliJ IDEA. + * User: zajac + * Date: 5/6/12 + * Time: 2:06 PM + * To change this template use File | Settings | File Templates. + */ +public class MasterDetailPopupBuilder { + + private static final Color BORDER_COLOR = Gray._135; + private Project myProject; + private ActionGroup myActions; + private JBList myList; + private Delegate myDelegate; + + public MasterDetailPopupBuilder(Project project) { + + myProject = project; + } + + + public JBPopup createMasterDetailPopup() { + final JLabel pathLabel = new JLabel(" "); + pathLabel.setHorizontalAlignment(SwingConstants.RIGHT); + + final Font font = pathLabel.getFont(); + pathLabel.setFont(font.deriveFont((float)10)); + + final Alarm updateAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); + final DetailViewImpl detailView = new DetailViewImpl(myProject); + + myList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + private String getTitle2Text(String fullText) { + int labelWidth = pathLabel.getWidth(); + if (fullText == null || fullText.length() == 0) return " "; + while (pathLabel.getFontMetrics(pathLabel.getFont()).stringWidth(fullText) > labelWidth) { + int sep = fullText.indexOf(File.separatorChar, 4); + if (sep < 0) return fullText; + fullText = "..." + fullText.substring(sep); + } + + return fullText; + } + + public void valueChanged(final ListSelectionEvent e) { + //noinspection SSBasedInspection + SwingUtilities.invokeLater(new Runnable() { + public void run() { + updatePathLabel(); + } + }); + } + + private void updatePreviewPanel(final ItemWrapper wrapper) { + updateAlarm.cancelAllRequests(); + updateAlarm.addRequest(new Runnable() { + public void run() { + detailView.updateWithItem(wrapper); + } + }, 300); + } + + private void updatePathLabel() { + final Object[] values = myList.getSelectedValues(); + ItemWrapper wrapper = null; + if (values != null && values.length == 1) { + wrapper = (ItemWrapper)values[0]; + pathLabel.setText(getTitle2Text(wrapper.footerText())); + } + else { + pathLabel.setText(" "); + } + updatePreviewPanel(wrapper); + } + }); + + Runnable runnable = new Runnable() { + public void run() { + IdeFocusManager.getInstance(myProject).doWhenFocusSettlesDown(new Runnable() { + public void run() { + Object[] values = myList.getSelectedValues(); + + if (values.length == 1) { + ((ItemWrapper)values[0]).execute(myProject); + } + else { + for (Object value : values) { + if (value instanceof BookmarkItem) { + ((ItemWrapper)value).execute(myProject); + } + } + } + } + }); + } + }; + + if (myList.getModel().getSize() == 0) { + myList.clearSelection(); + } + + JPanel footerPanel = new JPanel(new BorderLayout()) { + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + g.setColor(BORDER_COLOR); + g.drawLine(0, 0, getWidth(), 0); + } + }; + + footerPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); + footerPanel.add(pathLabel); + + ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar("", myActions, true); + actionToolbar.setReservePlaceAutoPopupIcon(false); + actionToolbar.setMinimumButtonSize(new Dimension(20, 20)); + final JComponent toolBar = actionToolbar.getComponent(); + toolBar.setOpaque(false); + + final JBPopup popup = new PopupChooserBuilder(myList). + setTitle(myDelegate.getTitle()). + setMovable(true). + setAutoselectOnMouseMove(false). + setSettingButton(toolBar). + setSouthComponent(footerPanel). + setEastComponent(detailView). + setItemChoosenCallback(runnable). + setMayBeParent(true). + setFilteringEnabled(new Function() { + public String fun(Object o) { + return ((ItemWrapper)o).speedSearchText(); + } + }).createPopup(); + + myList.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_DELETE) { + int index = myList.getSelectedIndex(); + if (index == -1 || index >= myList.getModel().getSize()) { + return; + } + Object[] values = myList.getSelectedValues(); + for (Object value : values) { + ItemWrapper item = (ItemWrapper)value; + + assert myList.getModel() instanceof DefaultListModel; + + DefaultListModel model = (DefaultListModel)myList.getModel(); + model.removeElement(item); + + if (model.getSize() > 0) { + if (model.getSize() == index) { + myList.setSelectedIndex(model.getSize() - 1); + } + else if (model.getSize() > index) { + myList.setSelectedIndex(index); + } + } + else { + myList.clearSelection(); + } + + myDelegate.itemRemoved(item, myProject); + } + } + else if (e.getModifiersEx() == 0) { + myDelegate.handleMnemonic(e, myProject, popup); + } + } + }); + return popup; + } + + public MasterDetailPopupBuilder setActionsGroup(ActionGroup actions) { + myActions = actions; + return this; + } + + public MasterDetailPopupBuilder setList(JBList list) { + myList = list; + return this; + } + + public MasterDetailPopupBuilder setDelegate(Delegate delegate) { + myDelegate = delegate; + return this; + } + + public interface Delegate { + String getTitle(); + + void handleMnemonic(KeyEvent e, Project project, JBPopup popup); + + void itemRemoved(ItemWrapper item, Project project); + } +} diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java index 405fdbf069fc..1a24a22fa731 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java @@ -18,8 +18,11 @@ package com.intellij.xdebugger.breakpoints; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.project.Project; +import com.intellij.ui.ColoredListCellRenderer; +import com.intellij.ui.popup.util.DetailView; import com.intellij.xdebugger.XDebuggerUtil; import com.intellij.xdebugger.XSourcePosition; +import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel; import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroupingRule; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java new file mode 100644 index 000000000000..42de3a795c37 --- /dev/null +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java @@ -0,0 +1,30 @@ +/* + * 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.xdebugger.breakpoints.ui; + +import com.intellij.openapi.util.Key; +import com.intellij.ui.popup.util.ItemWrapper; + +/** + * Created with IntelliJ IDEA. + * User: zajac + * Date: 5/9/12 + * Time: 4:48 AM + * To change this template use File | Settings | File Templates. + */ +public interface BreakpointItem extends ItemWrapper { + +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ViewBreakpointsActionNew.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ViewBreakpointsActionNew.java new file mode 100644 index 000000000000..40d9a6123b7a --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ViewBreakpointsActionNew.java @@ -0,0 +1,68 @@ +/* + * 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.xdebugger.impl.actions; + +import com.intellij.idea.ActionsBundle; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.xdebugger.impl.breakpoints.XBreakpointUtil; +import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointsMasterDetailPopupFactory; +import org.jetbrains.annotations.Nullable; + +public class ViewBreakpointsActionNew extends AnAction implements AnAction.TransparentUpdate { + @Nullable + private Object myInitialBreakpoint; + + public ViewBreakpointsActionNew() { + this(ActionsBundle.actionText(XDebuggerActions.VIEW_BREAKPOINTS), null); + } + + public ViewBreakpointsActionNew(String name, Object initialBreakpoint) { + super(name); + myInitialBreakpoint = initialBreakpoint; + } + + public void actionPerformed(AnActionEvent e) { + DataContext dataContext = e.getDataContext(); + Project project = PlatformDataKeys.PROJECT.getData(dataContext); + if (project == null) return; + + if (myInitialBreakpoint == null) { + Editor editor = PlatformDataKeys.EDITOR.getData(dataContext); + if (editor != null) { + myInitialBreakpoint = XBreakpointUtil.findSelectedBreakpoint(project, editor).second; + } + } + + BreakpointsMasterDetailPopupFactory. + getInstance(project).createPopup(myInitialBreakpoint).showCenteredInCurrentWindow(project); + + myInitialBreakpoint = null; + } + + public void update(AnActionEvent event) { + Presentation presentation = event.getPresentation(); + Project project = PlatformDataKeys.PROJECT.getData(event.getDataContext()); + if (project == null) { + presentation.setEnabled(false); + return; + } + presentation.setEnabled(true); + } + +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointPanelProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointPanelProvider.java index d9c48a7fd76d..269520e410b0 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointPanelProvider.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointPanelProvider.java @@ -19,6 +19,7 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.markup.GutterIconRenderer; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -41,4 +42,5 @@ public abstract class BreakpointPanelProvider { public abstract void onDialogClosed(final Project project); + public abstract void provideBreakpointItems(Project project, Collection items); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java new file mode 100644 index 000000000000..47b26379e61d --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java @@ -0,0 +1,100 @@ +/* + * 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.xdebugger.impl.breakpoints.ui; + +import com.intellij.openapi.actionSystem.DefaultActionGroup; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.ui.components.JBList; +import com.intellij.ui.popup.util.ItemWrapper; +import com.intellij.ui.popup.util.MasterDetailPopupBuilder; +import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; +import com.intellij.xdebugger.impl.DebuggerSupport; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.event.KeyEvent; +import java.util.*; + +/** + * Created with IntelliJ IDEA. + * User: zajac + * Date: 5/9/12 + * Time: 3:11 AM + * To change this template use File | Settings | File Templates. + */ +public class BreakpointsMasterDetailPopupFactory { + + private final List myBreakpointPanelProviders; + private Project myProject; + + public BreakpointsMasterDetailPopupFactory(Project project) { + myProject = project; + myBreakpointPanelProviders = new ArrayList(); + for (DebuggerSupport debuggerSupport : DebuggerSupport.getDebuggerSupports()) { + myBreakpointPanelProviders.add(debuggerSupport.getBreakpointPanelProvider()); + } + Collections.sort(myBreakpointPanelProviders, new Comparator() { + @Override + public int compare(BreakpointPanelProvider breakpointPanelProvider, BreakpointPanelProvider breakpointPanelProvider1) { + return breakpointPanelProvider.getPriority() - breakpointPanelProvider1.getPriority(); + } + }); + } + + public static BreakpointsMasterDetailPopupFactory getInstance(Project project) { + return ServiceManager.getService(project, BreakpointsMasterDetailPopupFactory.class); + } + + public JBPopup createPopup(@Nullable Object initialBreakpoint) { + DefaultListModel model = createBreakpointsItemsList(); + final JBList list = new JBList(model); + list.getEmptyText().setText("No Bookmarks"); + + DefaultActionGroup actions = new DefaultActionGroup(); + + final JBPopup popup = new MasterDetailPopupBuilder(myProject). + setActionsGroup(actions). + setList(list). + setDelegate(new MasterDetailPopupBuilder.Delegate() { + @Override + public String getTitle() { + return "Breakpoints"; + } + + @Override + public void handleMnemonic(KeyEvent e, Project project, JBPopup popup) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void itemRemoved(ItemWrapper item, Project project) { + //To change body of implemented methods use File | Settings | File Templates. + } + }).createMasterDetailPopup(); + + return popup; + } + + private DefaultListModel createBreakpointsItemsList() { + DefaultListModel model = new DefaultListModel(); + for (BreakpointPanelProvider panelProvider : myBreakpointPanelProviders) { + panelProvider.provideBreakpointItems(myProject, new ArrayList()); + } + return model; + } +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointPanelProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointPanelProvider.java index 3d20b62da368..34cc81fad3d6 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointPanelProvider.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointPanelProvider.java @@ -15,6 +15,7 @@ */ package com.intellij.xdebugger.impl.breakpoints.ui; +import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.markup.GutterIconRenderer; import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.project.Project; @@ -22,14 +23,20 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.ColoredListCellRenderer; +import com.intellij.ui.popup.util.DetailView; +import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.breakpoints.*; import com.intellij.xdebugger.XDebuggerManager; import com.intellij.xdebugger.XDebuggerUtil; +import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; +import com.intellij.xdebugger.impl.breakpoints.XBreakpointBase; import com.intellij.xdebugger.impl.breakpoints.XBreakpointUtil; import com.intellij.xdebugger.impl.breakpoints.XLineBreakpointImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; import java.util.Collection; import java.util.ArrayList; @@ -90,4 +97,49 @@ public class XBreakpointPanelProvider extends BreakpointPanelProvider items) { + XBreakpoint[] allBreakpoints = XDebuggerManager.getInstance(project).getBreakpointManager().getAllBreakpoints(); + for (XBreakpoint breakpoint : allBreakpoints) { + createBreakpointItem(breakpoint); + } + } + + private BreakpointItem createBreakpointItem(final XBreakpoint breakpoint) { + return new BreakpointItem() { + @Override + public void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected) { + renderer.setIcon(((XBreakpointBase)breakpoint).getIcon()); + } + + @Override + public void updateMnemonicLabel(JLabel label) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void execute(Project project) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String speedSearchText() { + return ((XBreakpointBase)breakpoint).getType().getDisplayText(breakpoint); + } + + @Override + public String footerText() { + return ((XBreakpointBase)breakpoint).getType().getDisplayText(breakpoint); + } + + @Override + public void updateDetailView(DetailView panel) { + XSourcePosition sourcePosition = breakpoint.getSourcePosition(); + if (sourcePosition != null) { + panel.navigateInPreviewEditor(sourcePosition.getFile(), new LogicalPosition(sourcePosition.getLine(), sourcePosition.getOffset())); + } + } + }; + } } From 7b1ee931f923bb7497935b8a74c6fc89829547bb Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Wed, 9 May 2012 17:38:36 +0400 Subject: [PATCH 20/61] breakpoints ui. popup added --- .../ui/breakpoints/BreakpointFactory.java | 26 ++++++--- .../bookmarks/actions/BookmarksAction.java | 43 +------------- .../popup/util/MasterDetailPopupBuilder.java | 57 ++++++++++++++++++- .../src/META-INF/xdebugger.xml | 3 + .../src/idea/LangActions.xml | 3 +- .../BreakpointsMasterDetailPopupFactory.java | 11 +++- 6 files changed, 90 insertions(+), 53 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java index b013e98bbf32..4263d7c3a93b 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java @@ -37,7 +37,8 @@ import javax.swing.*; * Used to deexternalize breakpoints of certain category while reading saved configuration and for creating configuration UI */ public abstract class BreakpointFactory { - public static final ExtensionPointName EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.debugger.breakpointFactory"); + public static final ExtensionPointName EXTENSION_POINT_NAME = + ExtensionPointName.create("com.intellij.debugger.breakpointFactory"); public static BreakpointFactory[] getBreakpointFactories() { return ApplicationManager.getApplication().getExtensions(EXTENSION_POINT_NAME); @@ -48,10 +49,9 @@ public abstract class BreakpointFactory { public abstract Key getBreakpointCategory(); public BreakpointPanel createBreakpointPanel(final Project project, final DialogWrapper parentDialog) { - BreakpointPanel panel = new BreakpointPanel(project, - createBreakpointPropertiesPanel(project, false), - createBreakpointPanelActions(project, parentDialog), - getBreakpointCategory(), getDisplayName(), getHelpID()); + BreakpointPanel panel = + new BreakpointPanel(project, createBreakpointPropertiesPanel(project, false), createBreakpointPanelActions(project, parentDialog), + getBreakpointCategory(), getDisplayName(), getHelpID()); configureBreakpointPanel(panel); return panel; } @@ -71,12 +71,16 @@ public abstract class BreakpointFactory { return null; } - protected void configureBreakpointPanel(BreakpointPanel panel){}; + protected void configureBreakpointPanel(BreakpointPanel panel) { + } + + ; protected abstract String getHelpID(); public abstract String getDisplayName(); + @Nullable public abstract BreakpointPropertiesPanel createBreakpointPropertiesPanel(Project project, boolean compact); protected abstract BreakpointPanelAction[] createBreakpointPanelActions(Project project, DialogWrapper parentDialog); @@ -86,6 +90,7 @@ public abstract class BreakpointFactory { @Override public void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected) { renderer.setIcon(breakpoint.getIcon()); + renderer.append(breakpoint.getDisplayName()); } @Override @@ -113,7 +118,14 @@ public abstract class BreakpointFactory { if (breakpoint instanceof LineBreakpoint) { SourcePosition sourcePosition = ((LineBreakpoint)breakpoint).getSourcePosition(); VirtualFile virtualFile = sourcePosition.getFile().getVirtualFile(); - panel.navigateInPreviewEditor(virtualFile,new LogicalPosition(sourcePosition.getLine(), 0)); + panel.navigateInPreviewEditor(virtualFile, new LogicalPosition(sourcePosition.getLine(), 0)); + } + + BreakpointPropertiesPanel breakpointPropertiesPanel = createBreakpointPropertiesPanel(breakpoint.getProject(), false); + if (breakpointPropertiesPanel != null) { + breakpointPropertiesPanel.initFrom(breakpoint, false); + final JPanel mainPanel = breakpointPropertiesPanel.getPanel(); + panel.setDetailPanel(mainPanel); } } }; diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java index 67ca0576093b..77fe90dc886d 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java @@ -32,14 +32,11 @@ import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.ToolWindowManager; -import com.intellij.ui.*; import com.intellij.ui.components.JBList; import com.intellij.ui.popup.util.MasterDetailPopupBuilder; import com.intellij.ui.speedSearch.FilteringListModel; -import com.intellij.util.ui.UIUtil; import javax.swing.*; -import java.awt.*; import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.Collections; @@ -67,7 +64,6 @@ public class BookmarksAction extends AnAction implements DumbAware, MasterDetail final JBList list = new JBList(model); list.getEmptyText().setText("No Bookmarks"); - list.setCellRenderer(new ItemRenderer(project)); EditBookmarkDescriptionAction editDescriptionAction = new EditBookmarkDescriptionAction(project, list); DefaultActionGroup actions = new DefaultActionGroup(); @@ -119,43 +115,8 @@ public class BookmarksAction extends AnAction implements DumbAware, MasterDetail return model; } - private static class ItemRenderer extends JPanel implements ListCellRenderer { - private final Project myProject; - private final ColoredListCellRenderer myRenderer; - - private ItemRenderer(Project project) { - super(new BorderLayout()); - myProject = project; - - setBackground(UIUtil.getListBackground()); - - final JLabel label = new JLabel(); - label.setFont(Bookmark.MNEMONIC_FONT); - - label.setPreferredSize(new JLabel("W.").getPreferredSize()); - label.setOpaque(false); - - if (BookmarkManager.getInstance(project).hasBookmarksWithMnemonics()) { - add(label, BorderLayout.WEST); - } - - myRenderer = new ColoredListCellRenderer() { - @Override - protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { - if (value instanceof ItemWrapper) { - final ItemWrapper wrapper = (ItemWrapper)value; - wrapper.setupRenderer(this, myProject, selected); - wrapper.updateMnemonicLabel(label); - } - } - }; - add(myRenderer, BorderLayout.CENTER); - } - - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - myRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - return this; - } + public boolean hasItemsWithMnemonic(Project project) { + return BookmarkManager.getInstance(project).hasBookmarksWithMnemonics(); } protected static class BookmarkInContextInfo { diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java index 26f193c4926c..85c0d8c78790 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java @@ -15,6 +15,7 @@ */ package com.intellij.ui.popup.util; +import com.intellij.ide.bookmarks.Bookmark; import com.intellij.ide.bookmarks.BookmarkItem; import com.intellij.openapi.actionSystem.ActionGroup; import com.intellij.openapi.actionSystem.ActionManager; @@ -23,10 +24,13 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.PopupChooserBuilder; import com.intellij.openapi.wm.IdeFocusManager; +import com.intellij.ui.ColoredListCellRenderer; import com.intellij.ui.Gray; import com.intellij.ui.components.JBList; +import com.intellij.ui.speedSearch.FilteringListModel; import com.intellij.util.Alarm; import com.intellij.util.Function; +import com.intellij.util.ui.UIUtil; import javax.swing.*; import javax.swing.event.ListSelectionEvent; @@ -67,6 +71,8 @@ public class MasterDetailPopupBuilder { final Alarm updateAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); final DetailViewImpl detailView = new DetailViewImpl(myProject); + myList.setCellRenderer(new ItemRenderer(myProject)); + myList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { private String getTitle2Text(String fullText) { int labelWidth = pathLabel.getWidth(); @@ -158,6 +164,7 @@ public class MasterDetailPopupBuilder { final JBPopup popup = new PopupChooserBuilder(myList). setTitle(myDelegate.getTitle()). setMovable(true). + setResizable(true). setAutoselectOnMouseMove(false). setSettingButton(toolBar). setSouthComponent(footerPanel). @@ -181,9 +188,8 @@ public class MasterDetailPopupBuilder { for (Object value : values) { ItemWrapper item = (ItemWrapper)value; - assert myList.getModel() instanceof DefaultListModel; - - DefaultListModel model = (DefaultListModel)myList.getModel(); + DefaultListModel model = myList.getModel() instanceof DefaultListModel ? (DefaultListModel)myList.getModel() : + (DefaultListModel)((FilteringListModel)myList.getModel()).getOriginalModel(); model.removeElement(item); if (model.getSize() > 0) { @@ -230,5 +236,50 @@ public class MasterDetailPopupBuilder { void handleMnemonic(KeyEvent e, Project project, JBPopup popup); void itemRemoved(ItemWrapper item, Project project); + + boolean hasItemsWithMnemonic(Project project); } + + public class ItemRenderer extends JPanel implements ListCellRenderer { + private final Project myProject; + private final ColoredListCellRenderer myRenderer; + + private ItemRenderer(Project project) { + super(new BorderLayout()); + myProject = project; + + setBackground(UIUtil.getListBackground()); + + final JLabel mnemonicLabel = new JLabel(); + mnemonicLabel.setFont(Bookmark.MNEMONIC_FONT); + + mnemonicLabel.setPreferredSize(new JLabel("W.").getPreferredSize()); + mnemonicLabel.setOpaque(false); + + final boolean hasMnemonics = myDelegate.hasItemsWithMnemonic(project); + if (hasMnemonics) { + add(mnemonicLabel, BorderLayout.WEST); + } + + myRenderer = new ColoredListCellRenderer() { + @Override + protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { + if (value instanceof ItemWrapper) { + final ItemWrapper wrapper = (ItemWrapper)value; + wrapper.setupRenderer(this, myProject, selected); + if (hasMnemonics) { + wrapper.updateMnemonicLabel(mnemonicLabel); + } + } + } + }; + add(myRenderer, BorderLayout.CENTER); + } + + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + myRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + return this; + } + } + } diff --git a/platform/platform-resources/src/META-INF/xdebugger.xml b/platform/platform-resources/src/META-INF/xdebugger.xml index 9653aa92091e..39d5de208ebe 100644 --- a/platform/platform-resources/src/META-INF/xdebugger.xml +++ b/platform/platform-resources/src/META-INF/xdebugger.xml @@ -26,6 +26,9 @@ + + diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index 2d20bcfcaefb..cd8a65c6998c 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -628,7 +628,8 @@ - + + diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java index 47b26379e61d..b63287f7ea45 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java @@ -15,6 +15,7 @@ */ package com.intellij.xdebugger.impl.breakpoints.ui; +import com.intellij.ide.bookmarks.BookmarkManager; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; @@ -85,6 +86,10 @@ public class BreakpointsMasterDetailPopupFactory { public void itemRemoved(ItemWrapper item, Project project) { //To change body of implemented methods use File | Settings | File Templates. } + + public boolean hasItemsWithMnemonic(Project project) { + return false; + } }).createMasterDetailPopup(); return popup; @@ -92,8 +97,12 @@ public class BreakpointsMasterDetailPopupFactory { private DefaultListModel createBreakpointsItemsList() { DefaultListModel model = new DefaultListModel(); + ArrayList items = new ArrayList(); for (BreakpointPanelProvider panelProvider : myBreakpointPanelProviders) { - panelProvider.provideBreakpointItems(myProject, new ArrayList()); + panelProvider.provideBreakpointItems(myProject, items); + } + for (BreakpointItem item : items) { + model.addElement(item); } return model; } From 371b345d317d765a5bb27f68d6d692615ded04ef Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Thu, 10 May 2012 01:03:04 +0400 Subject: [PATCH 21/61] breakpoints ui. xbreakpoints properties panel --- .../ui/breakpoints/BreakpointFactory.java | 2 +- .../bookmarks/actions/BookmarksAction.java | 5 ++++ .../popup/util/MasterDetailPopupBuilder.java | 29 +++++++++++-------- .../xdebugger/impl/XDebuggerSupport.java | 2 +- .../{ui => }/XBreakpointPanelProvider.java | 13 ++++++++- .../BreakpointsMasterDetailPopupFactory.java | 5 ++++ 6 files changed, 41 insertions(+), 15 deletions(-) rename platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/{ui => }/XBreakpointPanelProvider.java (88%) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java index 4263d7c3a93b..79816ec5e8aa 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java @@ -123,7 +123,7 @@ public abstract class BreakpointFactory { BreakpointPropertiesPanel breakpointPropertiesPanel = createBreakpointPropertiesPanel(breakpoint.getProject(), false); if (breakpointPropertiesPanel != null) { - breakpointPropertiesPanel.initFrom(breakpoint, false); + breakpointPropertiesPanel.initFrom(breakpoint, true); final JPanel mainPanel = breakpointPropertiesPanel.getPanel(); panel.setDetailPanel(mainPanel); } diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java index 77fe90dc886d..59b667dc2f22 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java @@ -119,6 +119,11 @@ public class BookmarksAction extends AnAction implements DumbAware, MasterDetail return BookmarkManager.getInstance(project).hasBookmarksWithMnemonics(); } + @Override + public boolean allowedToRemoveItem(ItemWrapper item) { + return true; + } + protected static class BookmarkInContextInfo { private final DataContext myDataContext; private final Project myProject; diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java index 85c0d8c78790..d14ffd793b82 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java @@ -188,23 +188,26 @@ public class MasterDetailPopupBuilder { for (Object value : values) { ItemWrapper item = (ItemWrapper)value; - DefaultListModel model = myList.getModel() instanceof DefaultListModel ? (DefaultListModel)myList.getModel() : - (DefaultListModel)((FilteringListModel)myList.getModel()).getOriginalModel(); - model.removeElement(item); + DefaultListModel model = myList.getModel() instanceof DefaultListModel + ? (DefaultListModel)myList.getModel() + : (DefaultListModel)((FilteringListModel)myList.getModel()).getOriginalModel(); + if (myDelegate.allowedToRemoveItem(item)) { + model.removeElement(item); - if (model.getSize() > 0) { - if (model.getSize() == index) { - myList.setSelectedIndex(model.getSize() - 1); + if (model.getSize() > 0) { + if (model.getSize() == index) { + myList.setSelectedIndex(model.getSize() - 1); + } + else if (model.getSize() > index) { + myList.setSelectedIndex(index); + } } - else if (model.getSize() > index) { - myList.setSelectedIndex(index); + else { + myList.clearSelection(); } - } - else { - myList.clearSelection(); + myDelegate.itemRemoved(item, myProject); } - myDelegate.itemRemoved(item, myProject); } } else if (e.getModifiersEx() == 0) { @@ -238,6 +241,8 @@ public class MasterDetailPopupBuilder { void itemRemoved(ItemWrapper item, Project project); boolean hasItemsWithMnemonic(Project project); + + boolean allowedToRemoveItem(ItemWrapper item); } public class ItemRenderer extends JPanel implements ListCellRenderer { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java index 691a8a9363fb..b8c45e8f0b6f 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java @@ -22,8 +22,8 @@ import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XDebuggerManager; import com.intellij.xdebugger.impl.actions.*; import com.intellij.xdebugger.impl.actions.handlers.*; +import com.intellij.xdebugger.impl.breakpoints.XBreakpointPanelProvider; import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointPanelProvider; -import com.intellij.xdebugger.impl.breakpoints.ui.XBreakpointPanelProvider; import com.intellij.xdebugger.impl.evaluate.quick.XQuickEvaluateHandler; import com.intellij.xdebugger.impl.evaluate.quick.common.QuickEvaluateHandler; import com.intellij.xdebugger.impl.settings.DebuggerSettingsPanelProvider; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointPanelProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java similarity index 88% rename from platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointPanelProvider.java rename to platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java index 34cc81fad3d6..c5f4f86e5c47 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointPanelProvider.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.xdebugger.impl.breakpoints.ui; +package com.intellij.xdebugger.impl.breakpoints; import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.markup.GutterIconRenderer; @@ -33,6 +33,10 @@ import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; import com.intellij.xdebugger.impl.breakpoints.XBreakpointBase; import com.intellij.xdebugger.impl.breakpoints.XBreakpointUtil; import com.intellij.xdebugger.impl.breakpoints.XLineBreakpointImpl; +import com.intellij.xdebugger.impl.breakpoints.ui.AbstractBreakpointPanel; +import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointPanelProvider; +import com.intellij.xdebugger.impl.breakpoints.ui.XBreakpointPropertiesPanel; +import com.intellij.xdebugger.impl.breakpoints.ui.XBreakpointsPanel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -139,6 +143,13 @@ public class XBreakpointPanelProvider extends BreakpointPanelProvider> propertiesPanel = + new XBreakpointPropertiesPanel>(project, ((XBreakpointBase)breakpoint).getBreakpointManager(), breakpoint); + + panel.setDetailPanel(propertiesPanel.getMainPanel()); } }; } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java index b63287f7ea45..390df565d72b 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java @@ -90,6 +90,11 @@ public class BreakpointsMasterDetailPopupFactory { public boolean hasItemsWithMnemonic(Project project) { return false; } + + @Override + public boolean allowedToRemoveItem(ItemWrapper item) { + return false; + } }).createMasterDetailPopup(); return popup; From 42efc41fa143fcba28682bb64626d3a2294a9cec Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Thu, 10 May 2012 06:05:21 +0400 Subject: [PATCH 22/61] breakpoints ui. add breakpoint action --- .../debugger/ui/JavaDebuggerSupport.java | 34 ++++++ .../ui/breakpoints/BreakpointFactory.java | 62 ++-------- .../ExceptionBreakpointFactory.java | 106 ++++++++-------- .../breakpoints/FieldBreakpointFactory.java | 113 +++++++++--------- .../ui/breakpoints/JavaBreakpointItem.java | 96 +++++++++++++++ .../breakpoints/MethodBreakpointFactory.java | 32 +++-- .../ui/breakpoints/actions/AddAction.java | 21 +++- .../intellij/ui/popup/util/ItemWrapper.java | 2 + .../intellij/ide/bookmarks/BookmarkItem.java | 5 + .../bookmarks/actions/BookmarksAction.java | 5 - .../ui/popup/util/DetailViewImpl.java | 5 + .../popup/util/MasterDetailPopupBuilder.java | 4 +- .../breakpoints/ui/BreakpointItem.java | 2 +- .../impl/breakpoints/XBreakpointItem.java | 92 ++++++++++++++ .../breakpoints/XBreakpointPanelProvider.java | 75 ++++-------- .../ui/BreakpointPanelProvider.java | 3 + .../BreakpointsMasterDetailPopupFactory.java | 36 +++++- ...tAction.java => XAddBreakpointAction.java} | 4 +- .../breakpoints/ui/XBreakpointsPanel.java | 2 +- 19 files changed, 447 insertions(+), 252 deletions(-) create mode 100644 java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java create mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java rename platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/{AddBreakpointAction.java => XAddBreakpointAction.java} (88%) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java index bb0d0d5a58ca..98ad4ba83e75 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java @@ -21,7 +21,10 @@ import com.intellij.debugger.impl.DebuggerContextImpl; import com.intellij.debugger.settings.*; import com.intellij.debugger.ui.breakpoints.*; import com.intellij.ide.DataManager; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.markup.GutterIconRenderer; import com.intellij.openapi.editor.markup.RangeHighlighter; @@ -196,6 +199,16 @@ public class JavaDebuggerSupport extends DebuggerSupport { return panels; } + @Override + public AnAction[] getAddBreakpointActions(@NotNull Project project) { + List result = new ArrayList(); + BreakpointFactory[] breakpointFactories = BreakpointFactory.getBreakpointFactories(); + for (BreakpointFactory breakpointFactory : breakpointFactories) { + result.add(new AddJavaBreakpointAction(breakpointFactory)); + } + return result.toArray(new AnAction[result.size()]); + } + public int getPriority() { return 1; } @@ -230,6 +243,27 @@ public class JavaDebuggerSupport extends DebuggerSupport { } } } + + private static class AddJavaBreakpointAction extends AnAction { + private BreakpointFactory myBreakpointFactory; + + public AddJavaBreakpointAction(BreakpointFactory breakpointFactory) { + myBreakpointFactory = breakpointFactory; + Presentation p = getTemplatePresentation(); + p.setIcon(myBreakpointFactory.getIcon()); + p.setText(breakpointFactory.getDisplayName()); + } + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setVisible(myBreakpointFactory.canAddBreakpoints()); + } + + @Override + public void actionPerformed(AnActionEvent e) { + myBreakpointFactory.addBreakpoint(getEventProject(e)); + } + } } public static class JavaDebuggerSettingsPanelProvider extends DebuggerSettingsPanelProvider { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java index 79816ec5e8aa..45d22e2deafb 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java @@ -15,18 +15,13 @@ */ package com.intellij.debugger.ui.breakpoints; -import com.intellij.debugger.SourcePosition; import com.intellij.debugger.ui.breakpoints.actions.BreakpointPanelAction; +import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.Key; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.ui.ColoredListCellRenderer; -import com.intellij.ui.popup.util.DetailView; -import com.intellij.ui.popup.util.DetailViewImpl; import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; import org.jdom.Element; import org.jetbrains.annotations.Nullable; @@ -74,8 +69,6 @@ public abstract class BreakpointFactory { protected void configureBreakpointPanel(BreakpointPanel panel) { } - ; - protected abstract String getHelpID(); public abstract String getDisplayName(); @@ -85,49 +78,16 @@ public abstract class BreakpointFactory { protected abstract BreakpointPanelAction[] createBreakpointPanelActions(Project project, DialogWrapper parentDialog); + @Nullable + public Breakpoint addBreakpoint(Project project) { + return null; + } + + public boolean canAddBreakpoints() { + return false; + } + public BreakpointItem createBreakpointItem(final Breakpoint breakpoint) { - return new BreakpointItem() { - @Override - public void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected) { - renderer.setIcon(breakpoint.getIcon()); - renderer.append(breakpoint.getDisplayName()); - } - - @Override - public void updateMnemonicLabel(JLabel label) { - //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - public void execute(Project project) { - //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - public String speedSearchText() { - return breakpoint.getDisplayName(); - } - - @Override - public String footerText() { - return breakpoint.getDisplayName(); - } - - @Override - public void updateDetailView(DetailView panel) { - if (breakpoint instanceof LineBreakpoint) { - SourcePosition sourcePosition = ((LineBreakpoint)breakpoint).getSourcePosition(); - VirtualFile virtualFile = sourcePosition.getFile().getVirtualFile(); - panel.navigateInPreviewEditor(virtualFile, new LogicalPosition(sourcePosition.getLine(), 0)); - } - - BreakpointPropertiesPanel breakpointPropertiesPanel = createBreakpointPropertiesPanel(breakpoint.getProject(), false); - if (breakpointPropertiesPanel != null) { - breakpointPropertiesPanel.initFrom(breakpoint, true); - final JPanel mainPanel = breakpointPropertiesPanel.getPanel(); - panel.setDetailPanel(mainPanel); - } - } - }; + return new JavaBreakpointItem(this, breakpoint); } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpointFactory.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpointFactory.java index aa3165d2151f..255d3cbef5f1 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpointFactory.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpointFactory.java @@ -39,7 +39,7 @@ import java.awt.event.ActionEvent; * @author Eugene Zhuravlev * Date: Apr 26, 2005 */ -public class ExceptionBreakpointFactory extends BreakpointFactory{ +public class ExceptionBreakpointFactory extends BreakpointFactory { public Breakpoint createBreakpoint(Project project, final Element element) { return new ExceptionBreakpoint(project); } @@ -77,47 +77,43 @@ public class ExceptionBreakpointFactory extends BreakpointFactory{ protected BreakpointPanelAction[] createBreakpointPanelActions(final Project project, DialogWrapper parentDialog) { return new BreakpointPanelAction[]{ new SwitchViewAction(), - new AddExceptionBreakpointAction(project), + new AddAction(this, project), new RemoveAction(project) { - public void update() { - super.update(); - if (getButton().isEnabled()) { - Breakpoint[] selectedBreakpoints = getPanel().getSelectedBreakpoints(); - for (Breakpoint bp : selectedBreakpoints) { - if (bp instanceof AnyExceptionBreakpoint) { - getButton().setEnabled(false); - } + public void update() { + super.update(); + if (getButton().isEnabled()) { + Breakpoint[] selectedBreakpoints = getPanel().getSelectedBreakpoints(); + for (Breakpoint bp : selectedBreakpoints) { + if (bp instanceof AnyExceptionBreakpoint) { + getButton().setEnabled(false); } } } - }, - new ToggleGroupByClassesAction(), - new ToggleFlattenPackagesAction(), - }; + } + }, new ToggleGroupByClassesAction(), new ToggleFlattenPackagesAction(),}; } - public BreakpointPanel createBreakpointPanel(final Project project, final DialogWrapper parentDialog) { - BreakpointPanel panel = new BreakpointPanel(project, - createBreakpointPropertiesPanel(project, false), - createBreakpointPanelActions(project, parentDialog), - getBreakpointCategory(), getDisplayName(), getHelpID()){ - public void resetBreakpoints() { - super.resetBreakpoints(); - Breakpoint[] breakpoints = getBreakpointManager().getBreakpoints(getBreakpointCategory()); - final AnyExceptionBreakpoint anyExceptionBreakpoint = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().getAnyExceptionBreakpoint(); - boolean found = false; - for (Breakpoint breakpoint : breakpoints) { - if (breakpoint.equals(anyExceptionBreakpoint)) { - found = true; - break; + BreakpointPanel panel = + new BreakpointPanel(project, createBreakpointPropertiesPanel(project, false), createBreakpointPanelActions(project, parentDialog), + getBreakpointCategory(), getDisplayName(), getHelpID()) { + public void resetBreakpoints() { + super.resetBreakpoints(); + Breakpoint[] breakpoints = getBreakpointManager().getBreakpoints(getBreakpointCategory()); + final AnyExceptionBreakpoint anyExceptionBreakpoint = + DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().getAnyExceptionBreakpoint(); + boolean found = false; + for (Breakpoint breakpoint : breakpoints) { + if (breakpoint.equals(anyExceptionBreakpoint)) { + found = true; + break; + } + } + if (!found) { + insertBreakpointAt(anyExceptionBreakpoint, 0); } } - if (!found) { - insertBreakpointAt(anyExceptionBreakpoint, 0); - } - } - }; + }; configureBreakpointPanel(panel); return panel; } @@ -126,29 +122,27 @@ public class ExceptionBreakpointFactory extends BreakpointFactory{ return ExceptionBreakpoint.CATEGORY; } - private static class AddExceptionBreakpointAction extends AddAction { - private final Project myProject; - - public AddExceptionBreakpointAction(Project project) { - myProject = project; - } - - public void actionPerformed(ActionEvent e) { - final PsiClass throwableClass = - JavaPsiFacade.getInstance(myProject).findClass("java.lang.Throwable", GlobalSearchScope.allScope(myProject)); - TreeClassChooser chooser = - TreeClassChooserFactory.getInstance(myProject).createInheritanceClassChooser( - DebuggerBundle.message("add.exception.breakpoint.classchooser.title"), GlobalSearchScope.allScope(myProject), - throwableClass, true, true, null); - chooser.showDialog(); - PsiClass selectedClass = chooser.getSelected(); - String qName = selectedClass == null ? null : JVMNameUtil.getNonAnonymousClassName(selectedClass); - - if (qName != null && qName.length() > 0) { - ExceptionBreakpoint breakpoint = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().addExceptionBreakpoint(qName, ((PsiClassOwner)selectedClass.getContainingFile()).getPackageName()); - getPanel().addBreakpoint(breakpoint); - } - } + @Override + public boolean canAddBreakpoints() { + return true; } + @Override + public Breakpoint addBreakpoint(Project project) { + ExceptionBreakpoint breakpoint = null; + final PsiClass throwableClass = + JavaPsiFacade.getInstance(project).findClass("java.lang.Throwable", GlobalSearchScope.allScope(project)); + TreeClassChooser chooser = TreeClassChooserFactory.getInstance(project) + .createInheritanceClassChooser(DebuggerBundle.message("add.exception.breakpoint.classchooser.title"), + GlobalSearchScope.allScope(project), throwableClass, true, true, null); + chooser.showDialog(); + PsiClass selectedClass = chooser.getSelected(); + String qName = selectedClass == null ? null : JVMNameUtil.getNonAnonymousClassName(selectedClass); + + if (qName != null && qName.length() > 0) { + breakpoint = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager() + .addExceptionBreakpoint(qName, ((PsiClassOwner)selectedClass.getContainingFile()).getPackageName()); + } + return breakpoint; + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FieldBreakpointFactory.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FieldBreakpointFactory.java index c98bc77834b4..738097173c61 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FieldBreakpointFactory.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FieldBreakpointFactory.java @@ -25,6 +25,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.Ref; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import org.jdom.Element; @@ -73,7 +74,7 @@ public class FieldBreakpointFactory extends BreakpointFactory{ protected BreakpointPanelAction[] createBreakpointPanelActions(final Project project, final DialogWrapper parentDialog) { return new BreakpointPanelAction[] { new SwitchViewAction(), - new AddFieldBreakpointAction(project), + new AddAction(this, project), new GotoSourceAction(project) { public void actionPerformed(ActionEvent e) { super.actionPerformed(e); @@ -91,65 +92,61 @@ public class FieldBreakpointFactory extends BreakpointFactory{ return FieldBreakpoint.CATEGORY; } - private static class AddFieldBreakpointAction extends AddAction { - private final Project myProject; - - public AddFieldBreakpointAction(Project project) { - myProject = project; - } - - public void actionPerformed(ActionEvent e) { - AddFieldBreakpointDialog dialog = new AddFieldBreakpointDialog(myProject) { - protected boolean validateData() { - String className = getClassName(); - if (className.length() == 0) { - Messages.showMessageDialog(myProject, DebuggerBundle.message("error.field.breakpoint.class.name.not.specified"), - DebuggerBundle.message("add.field.breakpoint.dialog.title"), Messages.getErrorIcon()); - return false; - } - String fieldName = getFieldName(); - if (fieldName.length() == 0) { - Messages.showMessageDialog(myProject, DebuggerBundle.message("error.field.breakpoint.field.name.not.specified"), - DebuggerBundle.message("add.field.breakpoint.dialog.title"), Messages.getErrorIcon()); - return false; - } - PsiClass psiClass = JavaPsiFacade.getInstance(myProject).findClass(className, GlobalSearchScope.allScope(myProject)); - if (psiClass != null) { - PsiFile psiFile = psiClass.getContainingFile(); - Document document = PsiDocumentManager.getInstance(myProject).getDocument(psiFile); - if(document != null) { - PsiField field = psiClass.findFieldByName(fieldName, true); - if(field != null) { - int line = document.getLineNumber(field.getTextOffset()); - FieldBreakpoint fieldBreakpoint = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().addFieldBreakpoint(document, line, fieldName); - if (fieldBreakpoint != null) { - getPanel().addBreakpoint(fieldBreakpoint); - return true; - } - } - else { - Messages.showMessageDialog( - myProject, - DebuggerBundle.message("error.field.breakpoint.field.not.found", className, fieldName, fieldName), - CommonBundle.getErrorTitle(), - Messages.getErrorIcon() - ); - - } - } - } else { - Messages.showMessageDialog( - myProject, - DebuggerBundle.message("error.field.breakpoint.class.sources.not.found", className, fieldName, className), - CommonBundle.getErrorTitle(), - Messages.getErrorIcon() - ); - } + @Override + public Breakpoint addBreakpoint(final Project project) { + final Ref result = Ref.create(null); + AddFieldBreakpointDialog dialog = new AddFieldBreakpointDialog(project) { + protected boolean validateData() { + String className = getClassName(); + if (className.length() == 0) { + Messages.showMessageDialog(project, DebuggerBundle.message("error.field.breakpoint.class.name.not.specified"), + DebuggerBundle.message("add.field.breakpoint.dialog.title"), Messages.getErrorIcon()); return false; } - }; - dialog.show(); - } + String fieldName = getFieldName(); + if (fieldName.length() == 0) { + Messages.showMessageDialog(project, DebuggerBundle.message("error.field.breakpoint.field.name.not.specified"), + DebuggerBundle.message("add.field.breakpoint.dialog.title"), Messages.getErrorIcon()); + return false; + } + PsiClass psiClass = JavaPsiFacade.getInstance(project).findClass(className, GlobalSearchScope.allScope(project)); + if (psiClass != null) { + PsiFile psiFile = psiClass.getContainingFile(); + Document document = PsiDocumentManager.getInstance(project).getDocument(psiFile); + if(document != null) { + PsiField field = psiClass.findFieldByName(fieldName, true); + if(field != null) { + int line = document.getLineNumber(field.getTextOffset()); + FieldBreakpoint fieldBreakpoint = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().addFieldBreakpoint(document, line, fieldName); + if (fieldBreakpoint != null) { + result.set(fieldBreakpoint); + return true; + } + } + else { + Messages.showMessageDialog(project, + DebuggerBundle.message("error.field.breakpoint.field.not.found", className, fieldName, fieldName), + CommonBundle.getErrorTitle(), + Messages.getErrorIcon() + ); + } + } + } else { + Messages.showMessageDialog(project, + DebuggerBundle.message("error.field.breakpoint.class.sources.not.found", className, fieldName, className), + CommonBundle.getErrorTitle(), + Messages.getErrorIcon() + ); + } + return false; + } + }; + dialog.show(); + return result.get(); } + @Override + public boolean canAddBreakpoints() { + return true; + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java new file mode 100644 index 000000000000..417223fbdda7 --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java @@ -0,0 +1,96 @@ +/* + * 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.debugger.ui.breakpoints; + +import com.intellij.debugger.SourcePosition; +import com.intellij.openapi.editor.LogicalPosition; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.ColoredListCellRenderer; +import com.intellij.ui.popup.util.DetailView; +import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; + +import javax.swing.*; + +/** +* Created with IntelliJ IDEA. +* User: intendia +* Date: 10.05.12 +* Time: 3:16 +* To change this template use File | Settings | File Templates. +*/ +class JavaBreakpointItem implements BreakpointItem { + private final Breakpoint myBreakpoint; + private BreakpointFactory myBreakpointFactory; + + public JavaBreakpointItem(BreakpointFactory breakpointFactory, Breakpoint breakpoint) { + myBreakpointFactory = breakpointFactory; + myBreakpoint = breakpoint; + } + + @Override + public void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected) { + renderer.setIcon(myBreakpoint.getIcon()); + renderer.append(myBreakpoint.getDisplayName()); + } + + @Override + public void updateMnemonicLabel(JLabel label) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void execute(Project project) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String speedSearchText() { + return myBreakpoint.getDisplayName(); + } + + @Override + public String footerText() { + return myBreakpoint.getDisplayName(); + } + + @Override + public void updateDetailView(DetailView panel) { + if (myBreakpoint instanceof LineBreakpoint) { + SourcePosition sourcePosition = ((LineBreakpoint)myBreakpoint).getSourcePosition(); + VirtualFile virtualFile = sourcePosition.getFile().getVirtualFile(); + panel.navigateInPreviewEditor(virtualFile, new LogicalPosition(sourcePosition.getLine(), 0)); + } + + BreakpointPropertiesPanel breakpointPropertiesPanel = myBreakpointFactory + .createBreakpointPropertiesPanel(myBreakpoint.getProject(), false); + if (breakpointPropertiesPanel != null) { + breakpointPropertiesPanel.initFrom(myBreakpoint, true); + final JPanel mainPanel = breakpointPropertiesPanel.getPanel(); + panel.setDetailPanel(mainPanel); + } + } + + @Override + public boolean allowedToRemove() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public Object getBreakpoint() { + return myBreakpoint; + } +} diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpointFactory.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpointFactory.java index 1fa227eb76f3..9dd7c725a1b7 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpointFactory.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpointFactory.java @@ -63,7 +63,7 @@ public class MethodBreakpointFactory extends BreakpointFactory{ protected BreakpointPanelAction[] createBreakpointPanelActions(Project project, final DialogWrapper parentDialog) { return new BreakpointPanelAction[]{ new SwitchViewAction(), - new AddWildcardBreakpointAction(project), + new AddAction(this, project), new GotoSourceAction(project) { public void actionPerformed(ActionEvent e) { super.actionPerformed(e); @@ -87,23 +87,19 @@ public class MethodBreakpointFactory extends BreakpointFactory{ return MethodBreakpoint.CATEGORY; } - private static class AddWildcardBreakpointAction extends AddAction { - private final Project myProject; + @Override + public boolean canAddBreakpoints() { + return true; + } - public AddWildcardBreakpointAction(Project project) { - myProject = project; - } - - public void actionPerformed(ActionEvent e) { - AddWildcardBreakpointDialog dialog = new AddWildcardBreakpointDialog(myProject); - dialog.show(); - if (!dialog.isOK()) { - return; - } - final WildcardMethodBreakpoint methodBreakpoint = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().addMethodBreakpoint(dialog.getClassPattern(), dialog.getMethodName()); - if (methodBreakpoint != null) { - getPanel().addBreakpoint(methodBreakpoint); - } - } + public WildcardMethodBreakpoint addBreakpoint(Project project) { + AddWildcardBreakpointDialog dialog = new AddWildcardBreakpointDialog(project); + dialog.show(); + WildcardMethodBreakpoint methodBreakpoint; + methodBreakpoint = !dialog.isOK() + ? null + : DebuggerManagerEx.getInstanceEx(project).getBreakpointManager() + .addMethodBreakpoint(dialog.getClassPattern(), dialog.getMethodName()); + return methodBreakpoint; } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/actions/AddAction.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/actions/AddAction.java index 9ecfc0084f82..8e3b37e9bff3 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/actions/AddAction.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/actions/AddAction.java @@ -15,18 +15,28 @@ */ package com.intellij.debugger.ui.breakpoints.actions; +import com.intellij.debugger.ui.breakpoints.Breakpoint; +import com.intellij.debugger.ui.breakpoints.BreakpointFactory; import com.intellij.debugger.ui.breakpoints.BreakpointPanel; import com.intellij.ide.IdeBundle; +import com.intellij.openapi.project.Project; import javax.swing.*; +import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; /** * @author Eugene Zhuravlev * Date: May 25, 2005 - */public abstract class AddAction extends BreakpointPanelAction { - protected AddAction() { + */ +public class AddAction extends BreakpointPanelAction { + protected final Project myProject; + protected BreakpointFactory myBreakpointFactory; + + public AddAction(BreakpointFactory breakpointFactory, Project project) { super(IdeBundle.message("button.add")); + myProject = project; + this.myBreakpointFactory = breakpointFactory; } public void setPanel(BreakpointPanel panel) { @@ -36,4 +46,11 @@ import java.awt.event.KeyEvent; public void update() { } + + public void actionPerformed(ActionEvent e) { + Breakpoint breakpoint = myBreakpointFactory.addBreakpoint(myProject); + if (breakpoint != null) { + getPanel().addBreakpoint(breakpoint); + } + } } diff --git a/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java b/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java index 3aa7a30dee80..4969851d9e7e 100644 --- a/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java +++ b/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java @@ -40,4 +40,6 @@ public interface ItemWrapper { String footerText(); void updateDetailView(DetailView panel); + + boolean allowedToRemove(); } diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java index 5dcf7f015e37..60808bd5ed2e 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java @@ -118,4 +118,9 @@ public class BookmarkItem implements ItemWrapper { panel.navigateInPreviewEditor(file, positionToNavigate); } + + @Override + public boolean allowedToRemove() { + return true; + } } diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java index 59b667dc2f22..77fe90dc886d 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java @@ -119,11 +119,6 @@ public class BookmarksAction extends AnAction implements DumbAware, MasterDetail return BookmarkManager.getInstance(project).hasBookmarksWithMnemonics(); } - @Override - public boolean allowedToRemoveItem(ItemWrapper item) { - return true; - } - protected static class BookmarkInContextInfo { private final DataContext myDataContext; private final Project myProject; diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java index 990d1ead0a93..eef189f0cf57 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java @@ -127,6 +127,11 @@ public class DetailViewImpl extends JPanel implements DetailView { @Override public void setDetailPanel(JPanel panel) { + if (panel == myDetailPanel) return; + + if (myDetailPanel != null) { + remove(myDetailPanel); + } myDetailPanel = panel; add(panel, BorderLayout.SOUTH); } diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java index d14ffd793b82..ec0b67891969 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java @@ -191,7 +191,7 @@ public class MasterDetailPopupBuilder { DefaultListModel model = myList.getModel() instanceof DefaultListModel ? (DefaultListModel)myList.getModel() : (DefaultListModel)((FilteringListModel)myList.getModel()).getOriginalModel(); - if (myDelegate.allowedToRemoveItem(item)) { + if (item.allowedToRemove()) { model.removeElement(item); if (model.getSize() > 0) { @@ -241,8 +241,6 @@ public class MasterDetailPopupBuilder { void itemRemoved(ItemWrapper item, Project project); boolean hasItemsWithMnemonic(Project project); - - boolean allowedToRemoveItem(ItemWrapper item); } public class ItemRenderer extends JPanel implements ListCellRenderer { diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java index 42de3a795c37..aa6acb4c81bf 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java @@ -26,5 +26,5 @@ import com.intellij.ui.popup.util.ItemWrapper; * To change this template use File | Settings | File Templates. */ public interface BreakpointItem extends ItemWrapper { - + Object getBreakpoint(); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java new file mode 100644 index 000000000000..f43fb0c36f8c --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java @@ -0,0 +1,92 @@ +/* + * 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.xdebugger.impl.breakpoints; + +import com.intellij.openapi.editor.LogicalPosition; +import com.intellij.openapi.project.Project; +import com.intellij.ui.ColoredListCellRenderer; +import com.intellij.ui.popup.util.DetailView; +import com.intellij.xdebugger.XSourcePosition; +import com.intellij.xdebugger.breakpoints.XBreakpoint; +import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; +import com.intellij.xdebugger.impl.breakpoints.ui.XBreakpointPropertiesPanel; + +import javax.swing.*; + +/** +* Created with IntelliJ IDEA. +* User: intendia +* Date: 10.05.12 +* Time: 1:14 +* To change this template use File | Settings | File Templates. +*/ +class XBreakpointItem implements BreakpointItem { + private final XBreakpoint myBreakpoint; + + public XBreakpointItem(XBreakpoint breakpoint) { + myBreakpoint = breakpoint; + } + + @Override + public void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected) { + renderer.setIcon(((XBreakpointBase)myBreakpoint).getIcon()); + } + + @Override + public void updateMnemonicLabel(JLabel label) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void execute(Project project) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String speedSearchText() { + return ((XBreakpointBase)myBreakpoint).getType().getDisplayText(myBreakpoint); + } + + @Override + public String footerText() { + return ((XBreakpointBase)myBreakpoint).getType().getDisplayText(myBreakpoint); + } + + @Override + public void updateDetailView(DetailView panel) { + XSourcePosition sourcePosition = myBreakpoint.getSourcePosition(); + if (sourcePosition != null) { + panel.navigateInPreviewEditor(sourcePosition.getFile(), new LogicalPosition(sourcePosition.getLine(), sourcePosition.getOffset())); + } + + Project project = ((XBreakpointBase)myBreakpoint).getProject(); + + XBreakpointPropertiesPanel> propertiesPanel = + new XBreakpointPropertiesPanel>(project, ((XBreakpointBase)myBreakpoint).getBreakpointManager(), myBreakpoint); + + panel.setDetailPanel(propertiesPanel.getMainPanel()); + } + + @Override + public boolean allowedToRemove() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public Object getBreakpoint() { + return myBreakpoint; + } +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java index c5f4f86e5c47..cde8501d15aa 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java @@ -15,7 +15,8 @@ */ package com.intellij.xdebugger.impl.breakpoints; -import com.intellij.openapi.editor.LogicalPosition; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.editor.markup.GutterIconRenderer; import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.project.Project; @@ -23,26 +24,19 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.ui.ColoredListCellRenderer; -import com.intellij.ui.popup.util.DetailView; -import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.breakpoints.*; import com.intellij.xdebugger.XDebuggerManager; import com.intellij.xdebugger.XDebuggerUtil; import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; -import com.intellij.xdebugger.impl.breakpoints.XBreakpointBase; -import com.intellij.xdebugger.impl.breakpoints.XBreakpointUtil; -import com.intellij.xdebugger.impl.breakpoints.XLineBreakpointImpl; import com.intellij.xdebugger.impl.breakpoints.ui.AbstractBreakpointPanel; import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointPanelProvider; -import com.intellij.xdebugger.impl.breakpoints.ui.XBreakpointPropertiesPanel; import com.intellij.xdebugger.impl.breakpoints.ui.XBreakpointsPanel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.*; import java.util.Collection; import java.util.ArrayList; +import java.util.List; /** * @author nik @@ -95,6 +89,17 @@ public class XBreakpointPanelProvider extends BreakpointPanelProvider result = new ArrayList(); + for (XBreakpointType type : XBreakpointUtil.getBreakpointTypes()) { + if (type.isAddBreakpointButtonVisible()) { + result.add(new AddXBreakpointAction(type)); + } + } + return new AnAction[0]; + } + private static > XBreakpointsPanel createBreakpointsPanel(final Project project, DialogWrapper parentDialog, final XBreakpointType type) { return new XBreakpointsPanel(project, parentDialog, type); } @@ -106,51 +111,23 @@ public class XBreakpointPanelProvider extends BreakpointPanelProvider items) { XBreakpoint[] allBreakpoints = XDebuggerManager.getInstance(project).getBreakpointManager().getAllBreakpoints(); for (XBreakpoint breakpoint : allBreakpoints) { - createBreakpointItem(breakpoint); + items.add(new XBreakpointItem(breakpoint)); } } - private BreakpointItem createBreakpointItem(final XBreakpoint breakpoint) { - return new BreakpointItem() { - @Override - public void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected) { - renderer.setIcon(((XBreakpointBase)breakpoint).getIcon()); - } + private class AddXBreakpointAction extends AnAction { - @Override - public void updateMnemonicLabel(JLabel label) { - //To change body of implemented methods use File | Settings | File Templates. - } + private XBreakpointType myType; - @Override - public void execute(Project project) { - //To change body of implemented methods use File | Settings | File Templates. - } + public AddXBreakpointAction(XBreakpointType type) { + myType = type; + getTemplatePresentation().setIcon(type.getEnabledIcon()); + getTemplatePresentation().setText(type.getTitle()); + } - @Override - public String speedSearchText() { - return ((XBreakpointBase)breakpoint).getType().getDisplayText(breakpoint); - } - - @Override - public String footerText() { - return ((XBreakpointBase)breakpoint).getType().getDisplayText(breakpoint); - } - - @Override - public void updateDetailView(DetailView panel) { - XSourcePosition sourcePosition = breakpoint.getSourcePosition(); - if (sourcePosition != null) { - panel.navigateInPreviewEditor(sourcePosition.getFile(), new LogicalPosition(sourcePosition.getLine(), sourcePosition.getOffset())); - } - - Project project = ((XBreakpointBase)breakpoint).getProject(); - - XBreakpointPropertiesPanel> propertiesPanel = - new XBreakpointPropertiesPanel>(project, ((XBreakpointBase)breakpoint).getBreakpointManager(), breakpoint); - - panel.setDetailPanel(propertiesPanel.getMainPanel()); - } - }; + @Override + public void actionPerformed(AnActionEvent e) { + myType.addBreakpoint(getEventProject(e), null); + } } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointPanelProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointPanelProvider.java index 269520e410b0..5f63a19c0ac4 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointPanelProvider.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointPanelProvider.java @@ -15,6 +15,7 @@ */ package com.intellij.xdebugger.impl.breakpoints.ui; +import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.markup.GutterIconRenderer; import com.intellij.openapi.project.Project; @@ -40,6 +41,8 @@ public abstract class BreakpointPanelProvider { @NotNull public abstract Collection> getBreakpointPanels(@NotNull Project project, @NotNull DialogWrapper parentDialog); + public abstract AnAction[] getAddBreakpointActions(@NotNull Project project); + public abstract void onDialogClosed(final Project project); public abstract void provideBreakpointItems(Project project, Collection items); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java index 390df565d72b..9870b415f2b1 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java @@ -15,16 +15,25 @@ */ package com.intellij.xdebugger.impl.breakpoints.ui; -import com.intellij.ide.bookmarks.BookmarkManager; +import com.intellij.ide.actions.ShowPopupMenuAction; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.ui.AnActionButton; import com.intellij.ui.components.JBList; import com.intellij.ui.popup.util.ItemWrapper; import com.intellij.ui.popup.util.MasterDetailPopupBuilder; +import com.intellij.util.PlatformIcons; +import com.intellij.xdebugger.XDebuggerManager; +import com.intellij.xdebugger.breakpoints.XBreakpoint; +import com.intellij.xdebugger.breakpoints.XBreakpointListener; import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; import com.intellij.xdebugger.impl.DebuggerSupport; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -66,7 +75,7 @@ public class BreakpointsMasterDetailPopupFactory { final JBList list = new JBList(model); list.getEmptyText().setText("No Bookmarks"); - DefaultActionGroup actions = new DefaultActionGroup(); + DefaultActionGroup actions = getActions(); final JBPopup popup = new MasterDetailPopupBuilder(myProject). setActionsGroup(actions). @@ -91,15 +100,30 @@ public class BreakpointsMasterDetailPopupFactory { return false; } - @Override - public boolean allowedToRemoveItem(ItemWrapper item) { - return false; - } }).createMasterDetailPopup(); return popup; } + private DefaultActionGroup getActions() { + DefaultActionGroup actions = new DefaultActionGroup(); + final DefaultActionGroup breakpointTypes = new DefaultActionGroup(); + for (BreakpointPanelProvider provider : myBreakpointPanelProviders) { + breakpointTypes.addAll(provider.getAddBreakpointActions(myProject)); + } + actions.add(new AnAction("Add Breakpoint", null, PlatformIcons.ADD_ICON) { + @Override + public void actionPerformed(AnActionEvent e) { + + JBPopupFactory.getInstance() + .createActionGroupPopup("Choose type", breakpointTypes, e.getDataContext(), JBPopupFactory.ActionSelectionAid.NUMBERING, false) + .showInFocusCenter(); + } + }); + + return actions; + } + private DefaultListModel createBreakpointsItemsList() { DefaultListModel model = new DefaultListModel(); ArrayList items = new ArrayList(); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/AddBreakpointAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XAddBreakpointAction.java similarity index 88% rename from platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/AddBreakpointAction.java rename to platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XAddBreakpointAction.java index 6d6e2076c1a3..a0de8e158e2b 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/AddBreakpointAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XAddBreakpointAction.java @@ -25,8 +25,8 @@ import java.util.Collection; /** * @author nik */ -public class AddBreakpointAction> extends XBreakpointPanelAction { - public AddBreakpointAction(final XBreakpointsPanel breakpointsPanel) { +public class XAddBreakpointAction> extends XBreakpointPanelAction { + public XAddBreakpointAction(final XBreakpointsPanel breakpointsPanel) { super(breakpointsPanel, XDebuggerBundle.message("xbreakpoints.dialog.button.add")); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointsPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointsPanel.java index ca55ec09655e..97273c7f7cdb 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointsPanel.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointsPanel.java @@ -80,7 +80,7 @@ public class XBreakpointsPanel> extends AbstractBreakpo List> actions = new ArrayList>(); if (type.isAddBreakpointButtonVisible()) { - actions.add(new AddBreakpointAction(this)); + actions.add(new XAddBreakpointAction(this)); } actions.add(new GoToBreakpointAction(this, XDebuggerBundle.message("xbreakpoints.dialog.button.goto"), true)); actions.add(new GoToBreakpointAction(this, XDebuggerBundle.message("xbreakpoints.dialog.button.view.source"), false)); From 6d3f269f1b74dd2c0b0ced3e0fe64ca438c56206 Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Thu, 10 May 2012 21:41:45 +0400 Subject: [PATCH 23/61] breakpoints ui. breakpoints list updating with adding/removing breakpoints. --- .../debugger/ui/JavaDebuggerSupport.java | 34 +++++++ .../AnyExceptionBreakpointFactory.java | 5 + .../ui/breakpoints/BreakpointFactory.java | 5 +- .../ui/breakpoints/JavaBreakpointItem.java | 20 +++- .../intellij/ui/popup/util/DetailView.java | 3 +- .../intellij/ui/popup/util/ItemWrapper.java | 2 + .../intellij/ide/bookmarks/BookmarkItem.java | 10 +- .../ui/popup/util/DetailViewImpl.java | 4 +- .../popup/util/MasterDetailPopupBuilder.java | 2 +- .../breakpoints/ui/BreakpointItem.java | 2 +- .../impl/breakpoints/XBreakpointItem.java | 31 ++++++- .../breakpoints/XBreakpointPanelProvider.java | 46 +++++++++- .../ui/BreakpointPanelProvider.java | 9 ++ .../BreakpointsMasterDetailPopupFactory.java | 92 +++++++++++++++---- .../ui/XLightBreakpointPropertiesPanel.java | 2 +- .../xdebugger/impl/ui/DebuggerUIUtil.java | 2 +- 16 files changed, 234 insertions(+), 35 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java index 98ad4ba83e75..5d554ed6ebea 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java @@ -49,6 +49,7 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; /** * @author nik @@ -185,6 +186,8 @@ public class JavaDebuggerSupport extends DebuggerSupport { } private static class JavaBreakpointPanelProvider extends BreakpointPanelProvider { + private List myListeners = new CopyOnWriteArrayList(); + @NotNull public Collection> getBreakpointPanels(@NotNull final Project project, @NotNull final DialogWrapper parentDialog) { List> panels = new ArrayList>(); @@ -209,6 +212,23 @@ public class JavaDebuggerSupport extends DebuggerSupport { return result.toArray(new AnAction[result.size()]); } + @Override + public void addListener(final BreakpointsListener listener, Project project) { + final MyBreakpointManagerListener listener1 = new MyBreakpointManagerListener(listener); + DebuggerManagerEx.getInstanceEx(getCurrentProject()).getBreakpointManager().addBreakpointManagerListener(listener1); + myListeners.add(listener1); + } + + @Override + public void removeListener(BreakpointsListener listener) { + for (MyBreakpointManagerListener managerListener : myListeners) { + if (managerListener.myListener == listener) { + myListeners.remove(managerListener); + break; + } + } + } + public int getPriority() { return 1; } @@ -264,6 +284,20 @@ public class JavaDebuggerSupport extends DebuggerSupport { myBreakpointFactory.addBreakpoint(getEventProject(e)); } } + + private static class MyBreakpointManagerListener implements BreakpointManagerListener { + + private final BreakpointsListener myListener; + + public MyBreakpointManagerListener(BreakpointsListener listener) { + myListener = listener; + } + + @Override + public void breakpointsChanged() { + myListener.breakpointsChanged(); + } + } } public static class JavaDebuggerSettingsPanelProvider extends DebuggerSettingsPanelProvider { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpointFactory.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpointFactory.java index 3f95b3fb39a5..69e72b01342e 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpointFactory.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpointFactory.java @@ -62,6 +62,11 @@ public class AnyExceptionBreakpointFactory extends BreakpointFactory{ return new BreakpointPanelAction[0]; //To change body of implemented methods use File | Settings | File Templates. } + @Override + public boolean breakpointCanBeRemoved(Breakpoint breakpoint) { + return false; + } + public @Nullable BreakpointPanel createBreakpointPanel(Project project, DialogWrapper parentDialog) { return null; } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java index 45d22e2deafb..3d5d52fab2dc 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointFactory.java @@ -16,7 +16,6 @@ package com.intellij.debugger.ui.breakpoints; import com.intellij.debugger.ui.breakpoints.actions.BreakpointPanelAction; -import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.project.Project; @@ -87,6 +86,10 @@ public abstract class BreakpointFactory { return false; } + public boolean breakpointCanBeRemoved(Breakpoint breakpoint) { + return true; + } + public BreakpointItem createBreakpointItem(final Breakpoint breakpoint) { return new JavaBreakpointItem(this, breakpoint); } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java index 417223fbdda7..0a2cf4aa77eb 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java @@ -15,6 +15,7 @@ */ package com.intellij.debugger.ui.breakpoints; +import com.intellij.debugger.DebuggerManagerEx; import com.intellij.debugger.SourcePosition; import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.project.Project; @@ -69,8 +70,8 @@ class JavaBreakpointItem implements BreakpointItem { @Override public void updateDetailView(DetailView panel) { - if (myBreakpoint instanceof LineBreakpoint) { - SourcePosition sourcePosition = ((LineBreakpoint)myBreakpoint).getSourcePosition(); + if (myBreakpoint instanceof BreakpointWithHighlighter) { + SourcePosition sourcePosition = ((BreakpointWithHighlighter)myBreakpoint).getSourcePosition(); VirtualFile virtualFile = sourcePosition.getFile().getVirtualFile(); panel.navigateInPreviewEditor(virtualFile, new LogicalPosition(sourcePosition.getLine(), 0)); } @@ -82,15 +83,28 @@ class JavaBreakpointItem implements BreakpointItem { final JPanel mainPanel = breakpointPropertiesPanel.getPanel(); panel.setDetailPanel(mainPanel); } + else { + panel.setDetailPanel(null); + } } @Override public boolean allowedToRemove() { - return false; //To change body of implemented methods use File | Settings | File Templates. + return myBreakpointFactory.breakpointCanBeRemoved(myBreakpoint); + } + + @Override + public void removed(Project project) { + DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().removeBreakpoint(myBreakpoint); } @Override public Object getBreakpoint() { return myBreakpoint; } + + @Override + public int getPriority() { + return 0; //To change body of implemented methods use File | Settings | File Templates. + } } diff --git a/platform/lang-api/src/com/intellij/ui/popup/util/DetailView.java b/platform/lang-api/src/com/intellij/ui/popup/util/DetailView.java index 9063521e29d1..fdd166833939 100644 --- a/platform/lang-api/src/com/intellij/ui/popup/util/DetailView.java +++ b/platform/lang-api/src/com/intellij/ui/popup/util/DetailView.java @@ -18,6 +18,7 @@ package com.intellij.ui.popup.util; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -37,5 +38,5 @@ public interface DetailView { JPanel getDetailPanel(); - void setDetailPanel(JPanel panel); + void setDetailPanel(@Nullable JPanel panel); } diff --git a/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java b/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java index 4969851d9e7e..2bbb28f553d7 100644 --- a/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java +++ b/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java @@ -42,4 +42,6 @@ public interface ItemWrapper { void updateDetailView(DetailView panel); boolean allowedToRemove(); + + void removed(Project project); } diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java index 60808bd5ed2e..cf7e375bfa08 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java @@ -19,9 +19,6 @@ import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.project.Project; -import com.intellij.ui.popup.util.DetailView; -import com.intellij.ui.popup.util.DetailViewImpl; -import com.intellij.ui.popup.util.ItemWrapper; import com.intellij.openapi.util.Iconable; import com.intellij.openapi.vcs.FileStatus; import com.intellij.openapi.vcs.FileStatusManager; @@ -32,6 +29,8 @@ import com.intellij.psi.PsiManager; import com.intellij.ui.ColoredListCellRenderer; import com.intellij.ui.FileColorManager; import com.intellij.ui.SimpleTextAttributes; +import com.intellij.ui.popup.util.DetailView; +import com.intellij.ui.popup.util.ItemWrapper; import javax.swing.*; import java.awt.*; @@ -123,4 +122,9 @@ public class BookmarkItem implements ItemWrapper { public boolean allowedToRemove() { return true; } + + @Override + public void removed(Project project) { + BookmarkManager.getInstance(project).removeBookmark(getBookmark()); + } } diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java index eef189f0cf57..e4fa3434d688 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java @@ -133,6 +133,8 @@ public class DetailViewImpl extends JPanel implements DetailView { remove(myDetailPanel); } myDetailPanel = panel; - add(panel, BorderLayout.SOUTH); + if (panel != null) { + add(panel, BorderLayout.SOUTH); + } } } diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java index ec0b67891969..5c336b34a1ac 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java @@ -205,7 +205,7 @@ public class MasterDetailPopupBuilder { else { myList.clearSelection(); } - myDelegate.itemRemoved(item, myProject); + item.removed(myProject); } } diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java index aa6acb4c81bf..afb07534aa7e 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java @@ -15,7 +15,6 @@ */ package com.intellij.xdebugger.breakpoints.ui; -import com.intellij.openapi.util.Key; import com.intellij.ui.popup.util.ItemWrapper; /** @@ -27,4 +26,5 @@ import com.intellij.ui.popup.util.ItemWrapper; */ public interface BreakpointItem extends ItemWrapper { Object getBreakpoint(); + int getPriority(); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java index f43fb0c36f8c..2a77345c9909 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java @@ -15,6 +15,8 @@ */ package com.intellij.xdebugger.impl.breakpoints; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.project.Project; import com.intellij.ui.ColoredListCellRenderer; @@ -22,7 +24,7 @@ import com.intellij.ui.popup.util.DetailView; import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.breakpoints.XBreakpoint; import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; -import com.intellij.xdebugger.impl.breakpoints.ui.XBreakpointPropertiesPanel; +import com.intellij.xdebugger.impl.breakpoints.ui.XLightBreakpointPropertiesPanel; import javax.swing.*; @@ -43,6 +45,7 @@ class XBreakpointItem implements BreakpointItem { @Override public void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected) { renderer.setIcon(((XBreakpointBase)myBreakpoint).getIcon()); + renderer.append(XBreakpointUtil.getDisplayText(myBreakpoint)); } @Override @@ -74,19 +77,39 @@ class XBreakpointItem implements BreakpointItem { Project project = ((XBreakpointBase)myBreakpoint).getProject(); - XBreakpointPropertiesPanel> propertiesPanel = - new XBreakpointPropertiesPanel>(project, ((XBreakpointBase)myBreakpoint).getBreakpointManager(), myBreakpoint); + XLightBreakpointPropertiesPanel> propertiesPanel = + new XLightBreakpointPropertiesPanel>(project, getManager(), myBreakpoint, true); panel.setDetailPanel(propertiesPanel.getMainPanel()); } + private XBreakpointManagerImpl getManager() { + return ((XBreakpointBase)myBreakpoint).getBreakpointManager(); + } + @Override public boolean allowedToRemove() { - return false; //To change body of implemented methods use File | Settings | File Templates. + return !getManager().isDefaultBreakpoint(myBreakpoint); + } + + @Override + public void removed(Project project) { + final XBreakpointManagerImpl breakpointManager = getManager(); + new WriteAction() { + protected void run(final Result result) { + breakpointManager.removeBreakpoint(myBreakpoint); + } + }.execute(); + } @Override public Object getBreakpoint() { return myBreakpoint; } + + @Override + public int getPriority() { + return 0; //To change body of implemented methods use File | Settings | File Templates. + } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java index cde8501d15aa..19d9b22fdcc8 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,12 +37,32 @@ import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; /** * @author nik */ public class XBreakpointPanelProvider extends BreakpointPanelProvider { + private List myListeners = new CopyOnWriteArrayList(); + + @Override + public void addListener(BreakpointsListener listener, Project project) { + final MyXBreakpointListener listener1 = new MyXBreakpointListener(listener); + XDebuggerManager.getInstance(project).getBreakpointManager().addBreakpointListener(listener1); + myListeners.add(listener1); + } + + @Override + public void removeListener(BreakpointsListener listener) { + for (MyXBreakpointListener breakpointListener : myListeners) { + if (breakpointListener.myListener == listener) { + myListeners.remove(breakpointListener); + break; + } + } + } + public int getPriority() { return 0; } @@ -97,7 +117,7 @@ public class XBreakpointPanelProvider extends BreakpointPanelProvider> XBreakpointsPanel createBreakpointsPanel(final Project project, DialogWrapper parentDialog, final XBreakpointType type) { @@ -115,6 +135,28 @@ public class XBreakpointPanelProvider extends BreakpointPanelProvider> { + public BreakpointsListener myListener; + + public MyXBreakpointListener(BreakpointsListener listener) { + myListener = listener; + } + + @Override + public void breakpointAdded(@NotNull XBreakpoint breakpoint) { + myListener.breakpointsChanged(); + } + + @Override + public void breakpointRemoved(@NotNull XBreakpoint breakpoint) { + myListener.breakpointsChanged(); + } + + @Override + public void breakpointChanged(@NotNull XBreakpoint breakpoint) { + } + } + private class AddXBreakpointAction extends AnAction { private XBreakpointType myType; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointPanelProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointPanelProvider.java index 5f63a19c0ac4..c79ef4d37cfc 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointPanelProvider.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointPanelProvider.java @@ -30,6 +30,15 @@ import java.util.Collection; * @author nik */ public abstract class BreakpointPanelProvider { + + public interface BreakpointsListener { + void breakpointsChanged(); + } + + public abstract void addListener(BreakpointsListener listener, Project project); + + public abstract void removeListener(BreakpointsListener listener); + public abstract int getPriority(); @Nullable diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java index 9870b415f2b1..0f6ec7e5dc8a 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java @@ -15,7 +15,6 @@ */ package com.intellij.xdebugger.impl.breakpoints.ui; -import com.intellij.ide.actions.ShowPopupMenuAction; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DefaultActionGroup; @@ -23,22 +22,22 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; -import com.intellij.ui.AnActionButton; +import com.intellij.openapi.ui.popup.JBPopupListener; +import com.intellij.openapi.ui.popup.LightweightWindowEvent; import com.intellij.ui.components.JBList; import com.intellij.ui.popup.util.ItemWrapper; import com.intellij.ui.popup.util.MasterDetailPopupBuilder; import com.intellij.util.PlatformIcons; -import com.intellij.xdebugger.XDebuggerManager; -import com.intellij.xdebugger.breakpoints.XBreakpoint; -import com.intellij.xdebugger.breakpoints.XBreakpointListener; import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; import com.intellij.xdebugger.impl.DebuggerSupport; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.event.KeyEvent; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; /** * Created with IntelliJ IDEA. @@ -60,8 +59,8 @@ public class BreakpointsMasterDetailPopupFactory { } Collections.sort(myBreakpointPanelProviders, new Comparator() { @Override - public int compare(BreakpointPanelProvider breakpointPanelProvider, BreakpointPanelProvider breakpointPanelProvider1) { - return breakpointPanelProvider.getPriority() - breakpointPanelProvider1.getPriority(); + public int compare(BreakpointPanelProvider o1, BreakpointPanelProvider o2) { + return o2.getPriority() - o1.getPriority(); } }); } @@ -71,8 +70,10 @@ public class BreakpointsMasterDetailPopupFactory { } public JBPopup createPopup(@Nullable Object initialBreakpoint) { - DefaultListModel model = createBreakpointsItemsList(); + final DefaultListSelectionModel selectionModel = new DefaultListSelectionModel(); + final BreakpointListModel model = createBreakpointsItemsList(selectionModel); final JBList list = new JBList(model); + list.setSelectionModel(selectionModel); list.getEmptyText().setText("No Bookmarks"); DefaultActionGroup actions = getActions(); @@ -99,9 +100,20 @@ public class BreakpointsMasterDetailPopupFactory { public boolean hasItemsWithMnemonic(Project project) { return false; } - }).createMasterDetailPopup(); + popup.addListener(new JBPopupListener() { + @Override + public void beforeShown(LightweightWindowEvent event) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void onClosed(LightweightWindowEvent event) { + model.unsubscribe(); + } + }); + return popup; } @@ -124,15 +136,63 @@ public class BreakpointsMasterDetailPopupFactory { return actions; } - private DefaultListModel createBreakpointsItemsList() { - DefaultListModel model = new DefaultListModel(); + private BreakpointListModel createBreakpointsItemsList(DefaultListSelectionModel selectionModel) { + final BreakpointListModel model = new BreakpointListModel(); + final ArrayList items = collectItems(); + for (BreakpointItem item : items) { + model.addElement(item); + } + model.subscribe(selectionModel); + return model; + } + + + + private ArrayList collectItems() { ArrayList items = new ArrayList(); for (BreakpointPanelProvider panelProvider : myBreakpointPanelProviders) { panelProvider.provideBreakpointItems(myProject, items); } - for (BreakpointItem item : items) { - model.addElement(item); + return items; + } + + private class BreakpointListModel extends DefaultListModel { + List myListeners = new ArrayList(); + + private void subscribe(DefaultListSelectionModel selectionModel) { + for (BreakpointPanelProvider panelProvider : myBreakpointPanelProviders) { + final BreakpointPanelProvider.BreakpointsListener listener = new MyBreakpointsListener(this, selectionModel); + panelProvider.addListener(listener, myProject); + myListeners.add(listener); + } + } + + public void unsubscribe() { + for (int i = 0, size = myListeners.size(); i < size; i++) { + BreakpointPanelProvider.BreakpointsListener listener = myListeners.get(i); + myBreakpointPanelProviders.get(i).removeListener(listener); + } + } + } + + private class MyBreakpointsListener implements BreakpointPanelProvider.BreakpointsListener { + private final DefaultListModel myModel; + private DefaultListSelectionModel mySelectionModel; + + public MyBreakpointsListener(DefaultListModel model, DefaultListSelectionModel selectionModel) { + myModel = model; + mySelectionModel = selectionModel; + } + + @Override + public void breakpointsChanged() { + final int index = mySelectionModel.getLeadSelectionIndex(); + myModel.removeAllElements(); + final ArrayList items = collectItems(); + for (BreakpointItem item : items) { + myModel.addElement(item); + } + mySelectionModel.setLeadSelectionIndex(index); } - return model; } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java index 20c4cc5ff63d..29b929ddb07b 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java @@ -158,7 +158,7 @@ public class XLightBreakpointPropertiesPanel> implement } } - public JComponent getMainPanel() { + public JPanel getMainPanel() { return myMainPanel; } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java index e2059dbddfd9..11b58784b313 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java @@ -268,7 +268,7 @@ public class DebuggerUIUtil { balloon.showInCenterOf(component); } else { - balloon.show(new RelativePoint(component, whereToShow), Balloon.Position.atRight); + balloon.show(new RelativePoint(component, whereToShow), Balloon.Position.below); } return balloon; From 719456b525e596a6de1b90a9968522f36e5841a4 Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Fri, 11 May 2012 23:08:05 +0400 Subject: [PATCH 24/61] breakpoints ui. breakpoints list updating with adding/removing breakpoints. --- .../debugger/ui/JavaDebuggerSupport.java | 9 ++- .../ui/breakpoints/JavaBreakpointItem.java | 19 ++--- .../intellij/ui/popup/util/DetailView.java | 2 + .../intellij/ui/popup/util/SplitterItem.java | 81 +++++++++++++++++++ .../ui/popup/util/DetailViewImpl.java | 51 +++++++++--- .../popup/util/MasterDetailPopupBuilder.java | 7 ++ .../breakpoints/ui/BreakpointItem.java | 1 - .../impl/breakpoints/XBreakpointItem.java | 17 ++-- .../breakpoints/XBreakpointPanelProvider.java | 17 ++-- .../ui/BreakpointPanelProvider.java | 4 +- .../BreakpointsMasterDetailPopupFactory.java | 13 ++- .../src/messages/DebuggerBundle.properties | 2 +- 12 files changed, 171 insertions(+), 52 deletions(-) create mode 100644 platform/lang-api/src/com/intellij/ui/popup/util/SplitterItem.java diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java index 5d554ed6ebea..33cf0e16f211 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java @@ -33,6 +33,8 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.Key; +import com.intellij.ui.popup.util.ItemWrapper; +import com.intellij.ui.popup.util.SplitterItem; import com.intellij.xdebugger.AbstractDebuggerSession; import com.intellij.xdebugger.impl.DebuggerSupport; import com.intellij.xdebugger.impl.actions.DebuggerActionHandler; @@ -40,7 +42,6 @@ import com.intellij.xdebugger.impl.actions.DebuggerToggleActionHandler; import com.intellij.xdebugger.impl.actions.EditBreakpointActionHandler; import com.intellij.xdebugger.impl.actions.MarkObjectActionHandler; import com.intellij.xdebugger.impl.breakpoints.ui.AbstractBreakpointPanel; -import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointPanelProvider; import com.intellij.xdebugger.impl.evaluate.quick.common.QuickEvaluateHandler; import com.intellij.xdebugger.impl.settings.DebuggerSettingsPanelProvider; @@ -253,11 +254,13 @@ public class JavaDebuggerSupport extends DebuggerSupport { } @Override - public void provideBreakpointItems(Project project, Collection items) { + public void provideBreakpointItems(Project project, Collection items) { for (BreakpointFactory breakpointFactory : BreakpointFactory.getBreakpointFactories()) { Key category = breakpointFactory.getBreakpointCategory(); Breakpoint[] breakpoints = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().getBreakpoints(category); - + if (breakpoints.length > 0) { + items.add(new SplitterItem(breakpointFactory.getDisplayName())); + } for (Breakpoint breakpoint : breakpoints) { items.add(breakpointFactory.createBreakpointItem(breakpoint)); } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java index 0a2cf4aa77eb..a9c1fe5c5c26 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java @@ -70,12 +70,6 @@ class JavaBreakpointItem implements BreakpointItem { @Override public void updateDetailView(DetailView panel) { - if (myBreakpoint instanceof BreakpointWithHighlighter) { - SourcePosition sourcePosition = ((BreakpointWithHighlighter)myBreakpoint).getSourcePosition(); - VirtualFile virtualFile = sourcePosition.getFile().getVirtualFile(); - panel.navigateInPreviewEditor(virtualFile, new LogicalPosition(sourcePosition.getLine(), 0)); - } - BreakpointPropertiesPanel breakpointPropertiesPanel = myBreakpointFactory .createBreakpointPropertiesPanel(myBreakpoint.getProject(), false); if (breakpointPropertiesPanel != null) { @@ -86,6 +80,14 @@ class JavaBreakpointItem implements BreakpointItem { else { panel.setDetailPanel(null); } + + if (myBreakpoint instanceof BreakpointWithHighlighter) { + SourcePosition sourcePosition = ((BreakpointWithHighlighter)myBreakpoint).getSourcePosition(); + VirtualFile virtualFile = sourcePosition.getFile().getVirtualFile(); + panel.navigateInPreviewEditor(virtualFile, new LogicalPosition(sourcePosition.getLine(), 0)); + } else { + panel.clearEditor(); + } } @Override @@ -102,9 +104,4 @@ class JavaBreakpointItem implements BreakpointItem { public Object getBreakpoint() { return myBreakpoint; } - - @Override - public int getPriority() { - return 0; //To change body of implemented methods use File | Settings | File Templates. - } } diff --git a/platform/lang-api/src/com/intellij/ui/popup/util/DetailView.java b/platform/lang-api/src/com/intellij/ui/popup/util/DetailView.java index fdd166833939..9e760fb751be 100644 --- a/platform/lang-api/src/com/intellij/ui/popup/util/DetailView.java +++ b/platform/lang-api/src/com/intellij/ui/popup/util/DetailView.java @@ -39,4 +39,6 @@ public interface DetailView { JPanel getDetailPanel(); void setDetailPanel(@Nullable JPanel panel); + + void clearEditor(); } diff --git a/platform/lang-api/src/com/intellij/ui/popup/util/SplitterItem.java b/platform/lang-api/src/com/intellij/ui/popup/util/SplitterItem.java new file mode 100644 index 000000000000..43c50f08afa0 --- /dev/null +++ b/platform/lang-api/src/com/intellij/ui/popup/util/SplitterItem.java @@ -0,0 +1,81 @@ +/* + * 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.ui.popup.util; + +import com.intellij.openapi.project.Project; +import com.intellij.ui.ColoredListCellRenderer; + +import javax.swing.*; + +/** + * Created with IntelliJ IDEA. + * User: zajac + * Date: 11.05.12 + * Time: 21:55 + * To change this template use File | Settings | File Templates. + */ +public class SplitterItem implements ItemWrapper { + + private String myText; + + public SplitterItem(String text) { + myText = text; + } + + public String getText() { + return myText; + } + + @Override + public void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void updateMnemonicLabel(JLabel label) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void execute(Project project) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String speedSearchText() { + return ""; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String footerText() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void updateDetailView(DetailView panel) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public boolean allowedToRemove() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void removed(Project project) { + //To change body of implemented methods use File | Settings | File Templates. + } +} diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java index e4fa3434d688..1b78efec4fd6 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java @@ -23,6 +23,8 @@ import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.components.JBScrollPane; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; @@ -40,10 +42,15 @@ public class DetailViewImpl extends JPanel implements DetailView { private ItemWrapper myWrapper; private JPanel myDetailPanel; + private JBScrollPane myDetailScrollPanel; + private JPanel myDetailPanelWrapper; + private JLabel myNothingToShow = new JLabel("Nothing to show"); + public DetailViewImpl(Project project) { super(new BorderLayout()); myProject = project; setPreferredSize(new Dimension(600, 400)); + myNothingToShow.setHorizontalAlignment(JLabel.CENTER); } @Override @@ -54,7 +61,7 @@ public class DetailViewImpl extends JPanel implements DetailView { wrapper.updateDetailView(this); } else { - cleanup(); + clearEditor(); repaint(); } @@ -62,18 +69,20 @@ public class DetailViewImpl extends JPanel implements DetailView { } } - private void cleanup() { - removeAll(); + @Override + public void clearEditor() { if (getEditor() != null) { + remove(getEditor().getComponent()); EditorFactory.getInstance().releaseEditor(getEditor()); setEditor(null); + repaint(); } } @Override public void removeNotify() { super.removeNotify(); - cleanup(); + clearEditor(); } @Override @@ -92,7 +101,7 @@ public class DetailViewImpl extends JPanel implements DetailView { if (document != null) { if (getEditor() == null || getEditor().getDocument() != document) { - cleanup(); + clearEditor(); setEditor(EditorFactory.getInstance().createViewer(document, project)); EditorHighlighter highlighter = EditorHighlighterFactory.getInstance() .createEditorHighlighter(file, EditorColorsManager.getInstance().getGlobalScheme(), project); @@ -112,7 +121,7 @@ public class DetailViewImpl extends JPanel implements DetailView { getEditor().getScrollingModel().scrollToCaret(ScrollType.CENTER); } else { - cleanup(); + clearEditor(); JLabel label = new JLabel("Navigate to selected " + (file.isDirectory() ? "directory " : "file ") + "in Project View"); label.setHorizontalAlignment(JLabel.CENTER); @@ -126,15 +135,33 @@ public class DetailViewImpl extends JPanel implements DetailView { } @Override - public void setDetailPanel(JPanel panel) { + public void setDetailPanel(@Nullable final JPanel panel) { if (panel == myDetailPanel) return; - if (myDetailPanel != null) { - remove(myDetailPanel); + if (panel != null) { + if (myDetailScrollPanel == null) { + myDetailPanelWrapper = new JPanel(new GridLayout(1, 1)); + + myDetailPanelWrapper.add(panel); + + myDetailScrollPanel = + new JBScrollPane(myDetailPanelWrapper, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER) { + @Override + public Dimension getPreferredSize() { + final Dimension size = panel.getPreferredSize(); + return new Dimension(size.width, size.height + 10); + } + }; + add(myDetailScrollPanel, BorderLayout.SOUTH); + } else { + myDetailPanelWrapper.removeAll(); + myDetailPanelWrapper.add(panel); + } + } + else { + myDetailPanelWrapper.removeAll(); + myDetailPanelWrapper.add(myNothingToShow); } myDetailPanel = panel; - if (panel != null) { - add(panel, BorderLayout.SOUTH); - } } } diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java index 5c336b34a1ac..9673e7bb755a 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java @@ -26,6 +26,7 @@ import com.intellij.openapi.ui.popup.PopupChooserBuilder; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.ColoredListCellRenderer; import com.intellij.ui.Gray; +import com.intellij.ui.TitledSeparator; import com.intellij.ui.components.JBList; import com.intellij.ui.speedSearch.FilteringListModel; import com.intellij.util.Alarm; @@ -171,6 +172,7 @@ public class MasterDetailPopupBuilder { setEastComponent(detailView). setItemChoosenCallback(runnable). setMayBeParent(true). + setMinSize(new Dimension(-1, 700)). setFilteringEnabled(new Function() { public String fun(Object o) { return ((ItemWrapper)o).speedSearchText(); @@ -280,6 +282,11 @@ public class MasterDetailPopupBuilder { } public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + if (value instanceof SplitterItem) { + String label = ((SplitterItem)value).getText(); + final TitledSeparator separator = new TitledSeparator(label); + return separator; + } myRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); return this; } diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java index afb07534aa7e..bd6ed506b1b9 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java @@ -26,5 +26,4 @@ import com.intellij.ui.popup.util.ItemWrapper; */ public interface BreakpointItem extends ItemWrapper { Object getBreakpoint(); - int getPriority(); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java index 2a77345c9909..cb4f1e21fdfe 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java @@ -70,17 +70,19 @@ class XBreakpointItem implements BreakpointItem { @Override public void updateDetailView(DetailView panel) { - XSourcePosition sourcePosition = myBreakpoint.getSourcePosition(); - if (sourcePosition != null) { - panel.navigateInPreviewEditor(sourcePosition.getFile(), new LogicalPosition(sourcePosition.getLine(), sourcePosition.getOffset())); - } - Project project = ((XBreakpointBase)myBreakpoint).getProject(); XLightBreakpointPropertiesPanel> propertiesPanel = new XLightBreakpointPropertiesPanel>(project, getManager(), myBreakpoint, true); panel.setDetailPanel(propertiesPanel.getMainPanel()); + + XSourcePosition sourcePosition = myBreakpoint.getSourcePosition(); + if (sourcePosition != null) { + panel.navigateInPreviewEditor(sourcePosition.getFile(), new LogicalPosition(sourcePosition.getLine(), sourcePosition.getOffset())); + } else { + panel.clearEditor(); + } } private XBreakpointManagerImpl getManager() { @@ -107,9 +109,4 @@ class XBreakpointItem implements BreakpointItem { public Object getBreakpoint() { return myBreakpoint; } - - @Override - public int getPriority() { - return 0; //To change body of implemented methods use File | Settings | File Templates. - } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java index 19d9b22fdcc8..eaabb8bc8e7d 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java @@ -24,10 +24,11 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.popup.util.ItemWrapper; +import com.intellij.ui.popup.util.SplitterItem; import com.intellij.xdebugger.breakpoints.*; import com.intellij.xdebugger.XDebuggerManager; import com.intellij.xdebugger.XDebuggerUtil; -import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; import com.intellij.xdebugger.impl.breakpoints.ui.AbstractBreakpointPanel; import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointPanelProvider; import com.intellij.xdebugger.impl.breakpoints.ui.XBreakpointsPanel; @@ -128,10 +129,16 @@ public class XBreakpointPanelProvider extends BreakpointPanelProvider items) { - XBreakpoint[] allBreakpoints = XDebuggerManager.getInstance(project).getBreakpointManager().getAllBreakpoints(); - for (XBreakpoint breakpoint : allBreakpoints) { - items.add(new XBreakpointItem(breakpoint)); + public void provideBreakpointItems(Project project, Collection items) { + final XBreakpointType[] types = XBreakpointUtil.getBreakpointTypes(); + final XBreakpointManager manager = XDebuggerManager.getInstance(project).getBreakpointManager(); + for (XBreakpointType type : types) { + final Collection> breakpoints = manager.getBreakpoints(type); + if (breakpoints.isEmpty()) continue; + items.add(new SplitterItem(type.getTitle())); + for (XBreakpoint breakpoint : breakpoints) { + items.add(new XBreakpointItem(breakpoint)); + } } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointPanelProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointPanelProvider.java index c79ef4d37cfc..b069579512b1 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointPanelProvider.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointPanelProvider.java @@ -20,7 +20,7 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.markup.GutterIconRenderer; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; +import com.intellij.ui.popup.util.ItemWrapper; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -54,5 +54,5 @@ public abstract class BreakpointPanelProvider { public abstract void onDialogClosed(final Project project); - public abstract void provideBreakpointItems(Project project, Collection items); + public abstract void provideBreakpointItems(Project project, Collection items); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java index 0f6ec7e5dc8a..be6871b260ea 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java @@ -28,7 +28,6 @@ import com.intellij.ui.components.JBList; import com.intellij.ui.popup.util.ItemWrapper; import com.intellij.ui.popup.util.MasterDetailPopupBuilder; import com.intellij.util.PlatformIcons; -import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; import com.intellij.xdebugger.impl.DebuggerSupport; import org.jetbrains.annotations.Nullable; @@ -138,8 +137,8 @@ public class BreakpointsMasterDetailPopupFactory { private BreakpointListModel createBreakpointsItemsList(DefaultListSelectionModel selectionModel) { final BreakpointListModel model = new BreakpointListModel(); - final ArrayList items = collectItems(); - for (BreakpointItem item : items) { + final ArrayList items = collectItems(); + for (ItemWrapper item : items) { model.addElement(item); } model.subscribe(selectionModel); @@ -148,8 +147,8 @@ public class BreakpointsMasterDetailPopupFactory { - private ArrayList collectItems() { - ArrayList items = new ArrayList(); + private ArrayList collectItems() { + ArrayList items = new ArrayList(); for (BreakpointPanelProvider panelProvider : myBreakpointPanelProviders) { panelProvider.provideBreakpointItems(myProject, items); } @@ -188,8 +187,8 @@ public class BreakpointsMasterDetailPopupFactory { public void breakpointsChanged() { final int index = mySelectionModel.getLeadSelectionIndex(); myModel.removeAllElements(); - final ArrayList items = collectItems(); - for (BreakpointItem item : items) { + final ArrayList items = collectItems(); + for (ItemWrapper item : items) { myModel.addElement(item); } mySelectionModel.setLeadSelectionIndex(index); diff --git a/resources-en/src/messages/DebuggerBundle.properties b/resources-en/src/messages/DebuggerBundle.properties index afcfce689893..540078755e40 100644 --- a/resources-en/src/messages/DebuggerBundle.properties +++ b/resources-en/src/messages/DebuggerBundle.properties @@ -317,7 +317,7 @@ class.filters.dialog.inclusion.filters.group=Class Filters class.filters.dialog.exclusion.filters.group=Class Exclusion Filters instance.filters.dialog.title=Instance Filters instance.filters.dialog.instance.filters.group=Instance Filters -breakpoint.exception.breakpoint.display.name=Exception breakpoint, class ''{0}'' +breakpoint.exception.breakpoint.display.name=''{0}'' exception.breakpoints.tab.title=Exception Breakpoints field.watchpoints.tab.title=Field Watchpoints line.breakpoints.tab.title=Line Breakpoints From 0cab6dbd6468eb4b294cc0ecd8dfbd5e05290b37 Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Sat, 12 May 2012 20:26:07 +0400 Subject: [PATCH 25/61] breakpoints ui. breakpoints list selection with separators. saving breakpoint properties on deselecting breakpoint. --- .../BreakpointPropertiesPanel.java | 15 ++++---- .../ui/breakpoints/JavaBreakpointItem.java | 8 +++- .../bookmarks/actions/BookmarksAction.java | 6 --- .../popup/util/MasterDetailPopupBuilder.java | 38 ++++++++++++++++--- .../impl/breakpoints/XBreakpointItem.java | 7 +++- .../BreakpointsMasterDetailPopupFactory.java | 5 --- .../ui/XLightBreakpointPropertiesPanel.form | 2 +- .../ui/XLightBreakpointPropertiesPanel.java | 10 +++++ 8 files changed, 64 insertions(+), 27 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java index f1e295138472..580de8694afe 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java @@ -108,6 +108,7 @@ public abstract class BreakpointPropertiesPanel { private static final int MAX_COMBO_WIDTH = 300; private final FixedSizeButton myConditionMagnifierButton; private boolean myMoreOptionsVisible = true; + private Breakpoint myBreakpoint; public boolean isMoreOptionsVisible() { return myMoreOptionsVisible; @@ -116,13 +117,12 @@ public abstract class BreakpointPropertiesPanel { private void createUIComponents() { myPanel = new JPanel() { @Override - public boolean requestFocus(boolean b) { - return super.requestFocus(b); //To change body of overridden methods use File | Settings | File Templates. - } - - @Override - public void requestFocus() { - super.requestFocus(); //To change body of overridden methods use File | Settings | File Templates. + public void removeNotify() { + super.removeNotify(); + saveTo(myBreakpoint, new Runnable() { + @Override + public void run() {} + }); } }; } @@ -392,6 +392,7 @@ public abstract class BreakpointPropertiesPanel { * Init UI components with the values from Breakpoint */ public void initFrom(Breakpoint breakpoint, boolean moreOptionsVisible1) { + myBreakpoint = breakpoint; boolean moreOptionsVisible = moreOptionsVisible1; boolean actionsPanelVisible = moreOptionsVisible1; myBreakpointComboboxHandler.initFrom(breakpoint); diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java index a9c1fe5c5c26..635b595f0f28 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java @@ -55,7 +55,12 @@ class JavaBreakpointItem implements BreakpointItem { @Override public void execute(Project project) { - //To change body of implemented methods use File | Settings | File Templates. + if (myBreakpoint instanceof BreakpointWithHighlighter) { + final SourcePosition position = ((BreakpointWithHighlighter)myBreakpoint).getSourcePosition(); + if (position != null) { + position.navigate(true); + } + } } @Override @@ -72,6 +77,7 @@ class JavaBreakpointItem implements BreakpointItem { public void updateDetailView(DetailView panel) { BreakpointPropertiesPanel breakpointPropertiesPanel = myBreakpointFactory .createBreakpointPropertiesPanel(myBreakpoint.getProject(), false); + if (breakpointPropertiesPanel != null) { breakpointPropertiesPanel.initFrom(myBreakpoint, true); final JPanel mainPanel = breakpointPropertiesPanel.getPanel(); diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java index 77fe90dc886d..c69805161528 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/BookmarksAction.java @@ -27,7 +27,6 @@ import com.intellij.openapi.editor.*; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; -import com.intellij.ui.popup.util.ItemWrapper; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.IdeFocusManager; @@ -100,11 +99,6 @@ public class BookmarksAction extends AnAction implements DumbAware, MasterDetail } } - @Override - public void itemRemoved(ItemWrapper item, Project project) { - BookmarkManager.getInstance(project).removeBookmark(((BookmarkItem)item).getBookmark()); - } - private static DefaultListModel buildModel(Project project) { final DefaultListModel model = new DefaultListModel(); diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java index 9673e7bb755a..3bfcbde49875 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java @@ -74,7 +74,12 @@ public class MasterDetailPopupBuilder { myList.setCellRenderer(new ItemRenderer(myProject)); - myList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + final ListSelectionModel selectionModel = myList.getSelectionModel(); + selectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + + final boolean directionUp[] = new boolean[1]; + + selectionModel.addListSelectionListener(new ListSelectionListener() { private String getTitle2Text(String fullText) { int labelWidth = pathLabel.getWidth(); if (fullText == null || fullText.length() == 0) return " "; @@ -102,7 +107,7 @@ public class MasterDetailPopupBuilder { public void run() { detailView.updateWithItem(wrapper); } - }, 300); + }, 100); } private void updatePathLabel() { @@ -110,6 +115,26 @@ public class MasterDetailPopupBuilder { ItemWrapper wrapper = null; if (values != null && values.length == 1) { wrapper = (ItemWrapper)values[0]; + if (wrapper instanceof SplitterItem) { + if (!directionUp[0]) { + final int index = myList.getSelectedIndex(); + if (myList.getItemsCount() >= index + 1) { + myList.setSelectedIndex(index + 1); + } + else { + myList.setSelectedIndex(0); + } + } + else { + final int index = myList.getSelectedIndex(); + if (index - 1 > 0) { + myList.setSelectedIndex(index - 1); + } + else { + myList.setSelectedIndex(myList.getItemsCount() - 1); + } + } + } pathLabel.setText(getTitle2Text(wrapper.footerText())); } else { @@ -212,6 +237,11 @@ public class MasterDetailPopupBuilder { } } + else if (e.getKeyCode() == KeyEvent.VK_UP) { + directionUp[0] = true; + } else if (e.getKeyCode() == KeyEvent.VK_DOWN) { + directionUp[0] = false; + } else if (e.getModifiersEx() == 0) { myDelegate.handleMnemonic(e, myProject, popup); } @@ -240,8 +270,6 @@ public class MasterDetailPopupBuilder { void handleMnemonic(KeyEvent e, Project project, JBPopup popup); - void itemRemoved(ItemWrapper item, Project project); - boolean hasItemsWithMnemonic(Project project); } @@ -253,7 +281,7 @@ public class MasterDetailPopupBuilder { super(new BorderLayout()); myProject = project; - setBackground(UIUtil.getListBackground()); + setBackground(UIUtil.getPanelBackground()); final JLabel mnemonicLabel = new JLabel(); mnemonicLabel.setFont(Bookmark.MNEMONIC_FONT); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java index cb4f1e21fdfe..2d0b8f6f7dd0 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java @@ -55,7 +55,10 @@ class XBreakpointItem implements BreakpointItem { @Override public void execute(Project project) { - //To change body of implemented methods use File | Settings | File Templates. + final XSourcePosition position = myBreakpoint.getSourcePosition(); + if (position != null) { + position.createNavigatable(project).navigate(true); + } } @Override @@ -74,7 +77,7 @@ class XBreakpointItem implements BreakpointItem { XLightBreakpointPropertiesPanel> propertiesPanel = new XLightBreakpointPropertiesPanel>(project, getManager(), myBreakpoint, true); - + propertiesPanel.loadProperties(); panel.setDetailPanel(propertiesPanel.getMainPanel()); XSourcePosition sourcePosition = myBreakpoint.getSourcePosition(); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java index be6871b260ea..472e50fd6b0b 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java @@ -91,11 +91,6 @@ public class BreakpointsMasterDetailPopupFactory { //To change body of implemented methods use File | Settings | File Templates. } - @Override - public void itemRemoved(ItemWrapper item, Project project) { - //To change body of implemented methods use File | Settings | File Templates. - } - public boolean hasItemsWithMnemonic(Project project) { return false; } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form index 5946988f09c9..5169027b778f 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form @@ -1,6 +1,6 @@
- + diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java index 29b929ddb07b..27b426af12ee 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java @@ -55,6 +55,16 @@ public class XLightBreakpointPropertiesPanel> implement } } + private void createUIComponents() { + myMainPanel = new JPanel() { + @Override + public void removeNotify() { + super.removeNotify(); + saveProperties(); + } + }; + } + public interface Delegate { void showMoreOptions(); } From 64649816ec65726145d06eeb61ee045035e5e372 Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Mon, 14 May 2012 22:36:07 +0400 Subject: [PATCH 26/61] breakpoints ui. registry key. selection policy for chooser popups. --- .../debugger/ui/PositionHighlighter.java | 3 +- .../BreakpointPropertiesPanel.java | 40 +++++++++-- .../BreakpointWithHighlighter.java | 3 +- .../ui/breakpoints/JavaBreakpointItem.java | 5 +- .../intellij/ui/popup/util/ItemWrapper.java | 3 +- .../intellij/ui/popup/util/SplitterItem.java | 3 +- .../intellij/ide/bookmarks/BookmarkItem.java | 3 +- .../popup/util/MasterDetailPopupBuilder.java | 21 ++++-- .../openapi/ui/popup/PopupChooserBuilder.java | 33 +++++++-- .../src/misc/registry.properties | 1 + .../src/idea/LangActions.xml | 3 +- .../impl/actions/ViewBreakpointsAction.java | 12 +++- .../actions/ViewBreakpointsActionNew.java | 68 ------------------- .../impl/breakpoints/XBreakpointBase.java | 3 +- .../impl/breakpoints/XBreakpointItem.java | 4 +- .../BreakpointsMasterDetailPopupFactory.java | 20 +++++- 16 files changed, 129 insertions(+), 96 deletions(-) delete mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ViewBreakpointsActionNew.java diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java b/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java index f7232701bc4c..e2f7af092f12 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java @@ -27,6 +27,7 @@ import com.intellij.debugger.jdi.StackFrameProxyImpl; import com.intellij.debugger.jdi.ThreadReferenceProxyImpl; import com.intellij.debugger.ui.breakpoints.*; import com.intellij.openapi.actionSystem.ActionGroup; +import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; @@ -410,7 +411,7 @@ public class PositionHighlighter { DefaultActionGroup group = new DefaultActionGroup(); for (Pair eventDescriptor : myEventsOutOfLine) { Breakpoint breakpoint = eventDescriptor.getFirst(); - ViewBreakpointsAction viewBreakpointsAction = new ViewBreakpointsAction(breakpoint.getDisplayName(), breakpoint); + AnAction viewBreakpointsAction = new ViewBreakpointsAction(breakpoint.getDisplayName(), breakpoint); group.add(viewBreakpointsAction); } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java index 580de8694afe..e16066e5ddb9 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java @@ -51,6 +51,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; import java.awt.*; import java.awt.event.*; import java.util.ArrayList; @@ -110,6 +112,16 @@ public abstract class BreakpointPropertiesPanel { private boolean myMoreOptionsVisible = true; private Breakpoint myBreakpoint; + public boolean isSaveOnRemove() { + return mySaveOnRemove; + } + + public void setSaveOnRemove(boolean saveOnRemove) { + mySaveOnRemove = saveOnRemove; + } + + private boolean mySaveOnRemove = false; + public boolean isMoreOptionsVisible() { return myMoreOptionsVisible; } @@ -119,10 +131,12 @@ public abstract class BreakpointPropertiesPanel { @Override public void removeNotify() { super.removeNotify(); - saveTo(myBreakpoint, new Runnable() { - @Override - public void run() {} - }); + if (mySaveOnRemove) { + saveTo(myBreakpoint, new Runnable() { + @Override + public void run() {} + }); + } } }; } @@ -262,6 +276,24 @@ public abstract class BreakpointPropertiesPanel { myBreakpointComboboxHandler = new BreakpointComboboxHandler(myProject, baseBreakpointCombo); baseBreakpointCombo.setRenderer(new BreakpointComboRenderer(baseBreakpointCombo.getRenderer())); + baseBreakpointCombo.addPopupMenuListener(new PopupMenuListener() { + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent event) { + event.getClass();//To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent event) { + //To change body of implemented methods use File | Settings | File Templates. + event.getClass(); + } + + @Override + public void popupMenuCanceled(PopupMenuEvent event) { + //To change body of implemented methods use File | Settings | File Templates. + event.getClass(); + } + }); baseBreakpointCombo.addItemListener(new ItemListener() { public void itemStateChanged(final ItemEvent e) { ComboboxItem item = (ComboboxItem)baseBreakpointCombo.getSelectedItem(); diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java index 79cc37541e60..2e52109b5ae4 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java @@ -637,7 +637,8 @@ public abstract class BreakpointWithHighlighter extends Breakpoint { } } - ViewBreakpointsAction viewBreakpointsAction = + + AnAction viewBreakpointsAction = new ViewBreakpointsAction(ActionsBundle.actionText(XDebuggerActions.VIEW_BREAKPOINTS), this); DefaultActionGroup group = new DefaultActionGroup(); diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java index 635b595f0f28..a53489668fbb 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java @@ -19,6 +19,7 @@ import com.intellij.debugger.DebuggerManagerEx; import com.intellij.debugger.SourcePosition; import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.ColoredListCellRenderer; import com.intellij.ui.popup.util.DetailView; @@ -54,11 +55,12 @@ class JavaBreakpointItem implements BreakpointItem { } @Override - public void execute(Project project) { + public void execute(Project project, JBPopup popup) { if (myBreakpoint instanceof BreakpointWithHighlighter) { final SourcePosition position = ((BreakpointWithHighlighter)myBreakpoint).getSourcePosition(); if (position != null) { position.navigate(true); + popup.cancel(); } } } @@ -77,6 +79,7 @@ class JavaBreakpointItem implements BreakpointItem { public void updateDetailView(DetailView panel) { BreakpointPropertiesPanel breakpointPropertiesPanel = myBreakpointFactory .createBreakpointPropertiesPanel(myBreakpoint.getProject(), false); + breakpointPropertiesPanel.setSaveOnRemove(true); if (breakpointPropertiesPanel != null) { breakpointPropertiesPanel.initFrom(myBreakpoint, true); diff --git a/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java b/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java index 2bbb28f553d7..6fffcc017028 100644 --- a/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java +++ b/platform/lang-api/src/com/intellij/ui/popup/util/ItemWrapper.java @@ -16,6 +16,7 @@ package com.intellij.ui.popup.util; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.ui.ColoredListCellRenderer; import org.jetbrains.annotations.Nullable; @@ -32,7 +33,7 @@ public interface ItemWrapper { void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected); void updateMnemonicLabel(JLabel label); - void execute(Project project); + void execute(Project project, JBPopup popup); String speedSearchText(); diff --git a/platform/lang-api/src/com/intellij/ui/popup/util/SplitterItem.java b/platform/lang-api/src/com/intellij/ui/popup/util/SplitterItem.java index 43c50f08afa0..c4e1917bc439 100644 --- a/platform/lang-api/src/com/intellij/ui/popup/util/SplitterItem.java +++ b/platform/lang-api/src/com/intellij/ui/popup/util/SplitterItem.java @@ -16,6 +16,7 @@ package com.intellij.ui.popup.util; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.ui.ColoredListCellRenderer; import javax.swing.*; @@ -50,7 +51,7 @@ public class SplitterItem implements ItemWrapper { } @Override - public void execute(Project project) { + public void execute(Project project, JBPopup popup) { //To change body of implemented methods use File | Settings | File Templates. } diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java index cf7e375bfa08..621e50bb4da5 100644 --- a/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java +++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/BookmarkItem.java @@ -19,6 +19,7 @@ import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.util.Iconable; import com.intellij.openapi.vcs.FileStatus; import com.intellij.openapi.vcs.FileStatusManager; @@ -102,7 +103,7 @@ public class BookmarkItem implements ItemWrapper { return myBookmark.getFile().getName() + " " + myBookmark.getDescription(); } - public void execute(Project project) { + public void execute(Project project, JBPopup popup) { myBookmark.navigate(); } diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java index 3bfcbde49875..f2e4fb075bf9 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java @@ -23,6 +23,7 @@ import com.intellij.openapi.actionSystem.ActionToolbar; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.PopupChooserBuilder; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.ColoredListCellRenderer; import com.intellij.ui.Gray; @@ -55,6 +56,7 @@ public class MasterDetailPopupBuilder { private ActionGroup myActions; private JBList myList; private Delegate myDelegate; + private boolean myCloseOnEnter; public MasterDetailPopupBuilder(Project project) { @@ -143,6 +145,7 @@ public class MasterDetailPopupBuilder { updatePreviewPanel(wrapper); } }); + final Ref popupRef = Ref.create(null); Runnable runnable = new Runnable() { public void run() { @@ -151,12 +154,12 @@ public class MasterDetailPopupBuilder { Object[] values = myList.getSelectedValues(); if (values.length == 1) { - ((ItemWrapper)values[0]).execute(myProject); + ((ItemWrapper)values[0]).execute(myProject, popupRef.get()); } else { for (Object value : values) { if (value instanceof BookmarkItem) { - ((ItemWrapper)value).execute(myProject); + ((ItemWrapper)value).execute(myProject, popupRef.get()); } } } @@ -196,6 +199,7 @@ public class MasterDetailPopupBuilder { setSouthComponent(footerPanel). setEastComponent(detailView). setItemChoosenCallback(runnable). + setCloseOnEnter(myCloseOnEnter). setMayBeParent(true). setMinSize(new Dimension(-1, 700)). setFilteringEnabled(new Function() { @@ -204,6 +208,8 @@ public class MasterDetailPopupBuilder { } }).createPopup(); + popupRef.set(popup); + myList.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_DELETE) { @@ -265,6 +271,11 @@ public class MasterDetailPopupBuilder { return this; } + public MasterDetailPopupBuilder setCloseOnEnter(boolean closeOnEnter) { + myCloseOnEnter = closeOnEnter; + return this; + } + public interface Delegate { String getTitle(); @@ -280,9 +291,7 @@ public class MasterDetailPopupBuilder { private ItemRenderer(Project project) { super(new BorderLayout()); myProject = project; - - setBackground(UIUtil.getPanelBackground()); - + setBackground(UIUtil.getListBackground()); final JLabel mnemonicLabel = new JLabel(); mnemonicLabel.setFont(Bookmark.MNEMONIC_FONT); @@ -313,6 +322,8 @@ public class MasterDetailPopupBuilder { if (value instanceof SplitterItem) { String label = ((SplitterItem)value).getText(); final TitledSeparator separator = new TitledSeparator(label); + separator.setBackground(UIUtil.getListBackground()); + separator.setForeground(UIUtil.getListForeground()); return separator; } myRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); diff --git a/platform/platform-api/src/com/intellij/openapi/ui/popup/PopupChooserBuilder.java b/platform/platform-api/src/com/intellij/openapi/ui/popup/PopupChooserBuilder.java index f82e36b483c3..1d7ddf517976 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/popup/PopupChooserBuilder.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/popup/PopupChooserBuilder.java @@ -81,6 +81,7 @@ public class PopupChooserBuilder { private boolean myMayBeParent; private int myAdAlignment = SwingUtilities.LEFT; private boolean myModalContext; + private boolean myCloseOnEnter = true; public PopupChooserBuilder(@NotNull JList list) { myChooserComponent = list; @@ -205,13 +206,28 @@ public class PopupChooserBuilder { @Override public void mouseReleased(MouseEvent e) { if (UIUtil.isActionClick(e, MouseEvent.MOUSE_RELEASED) && !UIUtil.isSelectionButtonDown(e) && !e.isConsumed()) { - closePopup(true, e, true); + if (myCloseOnEnter) { + closePopup(true, e, true); + } + else { + myItemChosenRunnable.run(); + } } } }); registerClosePopupKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), false); - registerClosePopupKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), true); + if (myCloseOnEnter) { + registerClosePopupKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), true); + } + else { + registerKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), new ActionListener() { + @Override + public void actionPerformed(ActionEvent event) { + myItemChosenRunnable.run(); + } + }); + } for (KeyStroke keystroke : myAdditionalKeystrokes) { registerClosePopupKeyboardAction(keystroke, true); } @@ -295,14 +311,18 @@ public class PopupChooserBuilder { } private void registerClosePopupKeyboardAction(final KeyStroke keyStroke, final boolean shouldPerformAction) { - myChooserComponent.registerKeyboardAction(new AbstractAction() { + registerPopupKeyboardAction(keyStroke, new AbstractAction() { public void actionPerformed(ActionEvent e) { if (!shouldPerformAction && myChooserComponent instanceof ListWithFilter) { if (((ListWithFilter)myChooserComponent).resetFilter()) return; } closePopup(shouldPerformAction, null, shouldPerformAction); } - }, keyStroke, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + }); + } + + private void registerPopupKeyboardAction(final KeyStroke keyStroke, AbstractAction action) { + myChooserComponent.registerKeyboardAction(action, keyStroke, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); } private void closePopup(boolean shouldPerformAction, MouseEvent e, boolean isOk) { @@ -419,6 +439,11 @@ public class PopupChooserBuilder { return this; } + public PopupChooserBuilder setCloseOnEnter(boolean closeOnEnter) { + myCloseOnEnter = closeOnEnter; + return this; + } + private class MyListWrapper extends JBScrollPane implements DataProvider { @SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"}) private final JList myList; diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties index f9f1f22f99d2..f881b56a2886 100644 --- a/platform/platform-resources-en/src/misc/registry.properties +++ b/platform/platform-resources-en/src/misc/registry.properties @@ -118,6 +118,7 @@ debugger.valueTooltipAutoShow.description=Auto show tooltip on mouse over debugger.mayBringFrameToFrontOnBreakpoint=true debugger.breakpoint.message.full.trace=false debugger.breakpoint.message.full.trace.description='Log message to console' breakpoint action will out full stacktrace for the thread that hit the breakpoint +debugger.breakpoint.use.breakpoints.popup=false filesystem.useNative=true diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index cd8a65c6998c..2d20bcfcaefb 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -628,8 +628,7 @@ - - + diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ViewBreakpointsAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ViewBreakpointsAction.java index a8d205efd602..14b21b5834ec 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ViewBreakpointsAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ViewBreakpointsAction.java @@ -25,8 +25,10 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.util.registry.Registry; import com.intellij.xdebugger.impl.breakpoints.XBreakpointUtil; import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointsConfigurationDialogFactory; +import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointsMasterDetailPopupFactory; public class ViewBreakpointsAction extends AnAction implements AnAction.TransparentUpdate { private Object myInitialBreakpoint; @@ -52,8 +54,14 @@ public class ViewBreakpointsAction extends AnAction implements AnAction.Transpar } } - DialogWrapper dialog = BreakpointsConfigurationDialogFactory.getInstance(project).createDialog(myInitialBreakpoint); - dialog.show(); + if (Registry.is("debugger.breakpoint.use.breakpoints.popup")) { + BreakpointsMasterDetailPopupFactory. + getInstance(project).createPopup(myInitialBreakpoint).showCenteredInCurrentWindow(project); + } + else { + DialogWrapper dialog = BreakpointsConfigurationDialogFactory.getInstance(project).createDialog(myInitialBreakpoint); + dialog.show(); + } myInitialBreakpoint = null; } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ViewBreakpointsActionNew.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ViewBreakpointsActionNew.java deleted file mode 100644 index 40d9a6123b7a..000000000000 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ViewBreakpointsActionNew.java +++ /dev/null @@ -1,68 +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.xdebugger.impl.actions; - -import com.intellij.idea.ActionsBundle; -import com.intellij.openapi.actionSystem.*; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.popup.JBPopup; -import com.intellij.xdebugger.impl.breakpoints.XBreakpointUtil; -import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointsMasterDetailPopupFactory; -import org.jetbrains.annotations.Nullable; - -public class ViewBreakpointsActionNew extends AnAction implements AnAction.TransparentUpdate { - @Nullable - private Object myInitialBreakpoint; - - public ViewBreakpointsActionNew() { - this(ActionsBundle.actionText(XDebuggerActions.VIEW_BREAKPOINTS), null); - } - - public ViewBreakpointsActionNew(String name, Object initialBreakpoint) { - super(name); - myInitialBreakpoint = initialBreakpoint; - } - - public void actionPerformed(AnActionEvent e) { - DataContext dataContext = e.getDataContext(); - Project project = PlatformDataKeys.PROJECT.getData(dataContext); - if (project == null) return; - - if (myInitialBreakpoint == null) { - Editor editor = PlatformDataKeys.EDITOR.getData(dataContext); - if (editor != null) { - myInitialBreakpoint = XBreakpointUtil.findSelectedBreakpoint(project, editor).second; - } - } - - BreakpointsMasterDetailPopupFactory. - getInstance(project).createPopup(myInitialBreakpoint).showCenteredInCurrentWindow(project); - - myInitialBreakpoint = null; - } - - public void update(AnActionEvent event) { - Presentation presentation = event.getPresentation(); - Project project = PlatformDataKeys.PROJECT.getData(event.getDataContext()); - if (project == null) { - presentation.setEnabled(false); - return; - } - presentation.setEnabled(true); - } - -} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java index 4e3f17b778fc..ee402cd19137 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java @@ -400,8 +400,7 @@ public class XBreakpointBase, P extends XBreakpointP public boolean equals(Object obj) { return obj instanceof XLineBreakpointImpl.BreakpointGutterIconRenderer && getBreakpoint() == ((XLineBreakpointImpl.BreakpointGutterIconRenderer)obj).getBreakpoint() - && Comparing.equal(getIcon(), ((XLineBreakpointImpl.BreakpointGutterIconRenderer)obj).getIcon()) - ; + && Comparing.equal(getIcon(), ((XLineBreakpointImpl.BreakpointGutterIconRenderer)obj).getIcon()); } @Override diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java index 2d0b8f6f7dd0..65fa9bb88458 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java @@ -19,6 +19,7 @@ import com.intellij.openapi.application.Result; import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.ui.ColoredListCellRenderer; import com.intellij.ui.popup.util.DetailView; import com.intellij.xdebugger.XSourcePosition; @@ -54,10 +55,11 @@ class XBreakpointItem implements BreakpointItem { } @Override - public void execute(Project project) { + public void execute(Project project, JBPopup popup) { final XSourcePosition position = myBreakpoint.getSourcePosition(); if (position != null) { position.createNavigatable(project).navigate(true); + popup.cancel(); } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java index 472e50fd6b0b..52a0262a12c7 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java @@ -28,6 +28,7 @@ import com.intellij.ui.components.JBList; import com.intellij.ui.popup.util.ItemWrapper; import com.intellij.ui.popup.util.MasterDetailPopupBuilder; import com.intellij.util.PlatformIcons; +import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; import com.intellij.xdebugger.impl.DebuggerSupport; import org.jetbrains.annotations.Nullable; @@ -73,7 +74,10 @@ public class BreakpointsMasterDetailPopupFactory { final BreakpointListModel model = createBreakpointsItemsList(selectionModel); final JBList list = new JBList(model); list.setSelectionModel(selectionModel); - list.getEmptyText().setText("No Bookmarks"); + + selectInitial(initialBreakpoint, model, list); + + list.getEmptyText().setText("No Breakpoints"); DefaultActionGroup actions = getActions(); @@ -94,7 +98,7 @@ public class BreakpointsMasterDetailPopupFactory { public boolean hasItemsWithMnemonic(Project project) { return false; } - }).createMasterDetailPopup(); + }).setCloseOnEnter(false).createMasterDetailPopup(); popup.addListener(new JBPopupListener() { @Override @@ -111,6 +115,18 @@ public class BreakpointsMasterDetailPopupFactory { return popup; } + private void selectInitial(Object initialBreakpoint, BreakpointListModel model, JBList list) { + for (int i = 0, l = model.size(); i < l; ++i) { + final ItemWrapper item = (ItemWrapper)model.get(i); + if (item instanceof BreakpointItem) { + if (((BreakpointItem)item).getBreakpoint() == initialBreakpoint) { + list.setSelectedIndex(i); + break; + } + } + } + } + private DefaultActionGroup getActions() { DefaultActionGroup actions = new DefaultActionGroup(); final DefaultActionGroup breakpointTypes = new DefaultActionGroup(); From 185bd7a87eec96310a88134234eb64af54a5b385 Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Tue, 15 May 2012 12:08:57 +0400 Subject: [PATCH 27/61] breakpoints ui. remove action on toolbar. fixed selection after removing breakpoint. --- .../ui/breakpoints/JavaBreakpointItem.java | 6 +- .../ui/popup/util/DetailViewImpl.java | 1 + .../popup/util/MasterDetailPopupBuilder.java | 72 +++++++++++-------- .../BreakpointsMasterDetailPopupFactory.java | 67 ++++++++++++----- 4 files changed, 97 insertions(+), 49 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java index a53489668fbb..96106874bf9c 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java @@ -46,7 +46,7 @@ class JavaBreakpointItem implements BreakpointItem { @Override public void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected) { renderer.setIcon(myBreakpoint.getIcon()); - renderer.append(myBreakpoint.getDisplayName()); + renderer.append(myBreakpoint.getShortName()); } @Override @@ -79,7 +79,9 @@ class JavaBreakpointItem implements BreakpointItem { public void updateDetailView(DetailView panel) { BreakpointPropertiesPanel breakpointPropertiesPanel = myBreakpointFactory .createBreakpointPropertiesPanel(myBreakpoint.getProject(), false); - breakpointPropertiesPanel.setSaveOnRemove(true); + if (breakpointPropertiesPanel != null) { + breakpointPropertiesPanel.setSaveOnRemove(true); + } if (breakpointPropertiesPanel != null) { breakpointPropertiesPanel.initFrom(myBreakpoint, true); diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java index 1b78efec4fd6..3bd83b6d0544 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java @@ -75,6 +75,7 @@ public class DetailViewImpl extends JPanel implements DetailView { remove(getEditor().getComponent()); EditorFactory.getInstance().releaseEditor(getEditor()); setEditor(null); + add(myNothingToShow, BorderLayout.CENTER); repaint(); } } diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java index f2e4fb075bf9..d965c830d51b 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java @@ -213,35 +213,7 @@ public class MasterDetailPopupBuilder { myList.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_DELETE) { - int index = myList.getSelectedIndex(); - if (index == -1 || index >= myList.getModel().getSize()) { - return; - } - Object[] values = myList.getSelectedValues(); - for (Object value : values) { - ItemWrapper item = (ItemWrapper)value; - - DefaultListModel model = myList.getModel() instanceof DefaultListModel - ? (DefaultListModel)myList.getModel() - : (DefaultListModel)((FilteringListModel)myList.getModel()).getOriginalModel(); - if (item.allowedToRemove()) { - model.removeElement(item); - - if (model.getSize() > 0) { - if (model.getSize() == index) { - myList.setSelectedIndex(model.getSize() - 1); - } - else if (model.getSize() > index) { - myList.setSelectedIndex(index); - } - } - else { - myList.clearSelection(); - } - item.removed(myProject); - } - - } + removeSelectedItems(MasterDetailPopupBuilder.this.myList, MasterDetailPopupBuilder.this.myProject); } else if (e.getKeyCode() == KeyEvent.VK_UP) { directionUp[0] = true; @@ -256,6 +228,48 @@ public class MasterDetailPopupBuilder { return popup; } + public static boolean allowedToRemoveSelectedItem(JBList list, Project project) { + Object[] values = list.getSelectedValues(); + for (Object value : values) { + ItemWrapper item = (ItemWrapper)value; + if (!item.allowedToRemove()) { + return false; + } + } + return values.length > 0; + } + + public static void removeSelectedItems(JBList list, Project project) { + int index = list.getSelectedIndex(); + if (index == -1 || index >= list.getModel().getSize()) { + return; + } + Object[] values = list.getSelectedValues(); + for (Object value : values) { + ItemWrapper item = (ItemWrapper)value; + + DefaultListModel model = list.getModel() instanceof DefaultListModel + ? (DefaultListModel)list.getModel() + : (DefaultListModel)((FilteringListModel)list.getModel()).getOriginalModel(); + if (item.allowedToRemove()) { + model.removeElement(item); + + if (model.getSize() > 0) { + if (model.getSize() == index) { + list.setSelectedIndex(model.getSize() - 1); + } + else if (model.getSize() > index) { + list.setSelectedIndex(index); + } + } + else { + list.clearSelection(); + } + item.removed(project); + } + } + } + public MasterDetailPopupBuilder setActionsGroup(ActionGroup actions) { myActions = actions; return this; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java index 52a0262a12c7..5096b0f6e60b 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java @@ -79,7 +79,7 @@ public class BreakpointsMasterDetailPopupFactory { list.getEmptyText().setText("No Breakpoints"); - DefaultActionGroup actions = getActions(); + DefaultActionGroup actions = getActions(list); final JBPopup popup = new MasterDetailPopupBuilder(myProject). setActionsGroup(actions). @@ -127,7 +127,7 @@ public class BreakpointsMasterDetailPopupFactory { } } - private DefaultActionGroup getActions() { + private DefaultActionGroup getActions(final JBList list) { DefaultActionGroup actions = new DefaultActionGroup(); final DefaultActionGroup breakpointTypes = new DefaultActionGroup(); for (BreakpointPanelProvider provider : myBreakpointPanelProviders) { @@ -142,6 +142,17 @@ public class BreakpointsMasterDetailPopupFactory { .showInFocusCenter(); } }); + actions.add(new AnAction("Remove Breakpoint", null, PlatformIcons.DELETE_ICON) { + @Override + public void update(AnActionEvent e) { + e.getPresentation().setEnabled(MasterDetailPopupBuilder.allowedToRemoveSelectedItem(list, myProject)); + } + + @Override + public void actionPerformed(AnActionEvent e) { + MasterDetailPopupBuilder.removeSelectedItems(list, myProject); + } + }); return actions; } @@ -183,26 +194,46 @@ public class BreakpointsMasterDetailPopupFactory { myBreakpointPanelProviders.get(i).removeListener(listener); } } - } - private class MyBreakpointsListener implements BreakpointPanelProvider.BreakpointsListener { - private final DefaultListModel myModel; - private DefaultListSelectionModel mySelectionModel; + private class MyBreakpointsListener implements BreakpointPanelProvider.BreakpointsListener { + private final DefaultListModel myModel; + private DefaultListSelectionModel mySelectionModel; - public MyBreakpointsListener(DefaultListModel model, DefaultListSelectionModel selectionModel) { - myModel = model; - mySelectionModel = selectionModel; - } + public MyBreakpointsListener(DefaultListModel model, DefaultListSelectionModel selectionModel) { + myModel = model; + mySelectionModel = selectionModel; + } - @Override - public void breakpointsChanged() { - final int index = mySelectionModel.getLeadSelectionIndex(); - myModel.removeAllElements(); - final ArrayList items = collectItems(); - for (ItemWrapper item : items) { - myModel.addElement(item); + @Override + public void breakpointsChanged() { + final ArrayList items = collectItems(); + if (!reallyChanged(items, myModel)) { + return; + } + final int index = mySelectionModel.getLeadSelectionIndex(); + myModel.removeAllElements(); + for (ItemWrapper item : items) { + myModel.addElement(item); + } + mySelectionModel.setLeadSelectionIndex(index); + } + + private boolean reallyChanged(List items, DefaultListModel model) { + if (items.size() != model.size()) return true; + for (int i = 0; i < model.size(); i++) { + final ItemWrapper item1 = items.get(i); + final ItemWrapper item2 = (ItemWrapper)model.get(i); + if (item1.getClass() != item2.getClass()) { + return true; + } + if (item1 instanceof BreakpointItem) { + if (((BreakpointItem)item1).getBreakpoint() != ((BreakpointItem)item2).getBreakpoint()) { + return true; + } + } + } + return false; } - mySelectionModel.setLeadSelectionIndex(index); } } } From 86f74e3068043d32f91552f7c70753eef657fdc7 Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Tue, 15 May 2012 12:24:22 +0400 Subject: [PATCH 28/61] breakpoints ui. cosmetics. some gaps --- .../src/com/intellij/ui/popup/util/DetailViewImpl.java | 2 +- platform/platform-api/src/com/intellij/ui/TitledSeparator.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java index 3bd83b6d0544..0ff966bc395f 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java @@ -142,7 +142,7 @@ public class DetailViewImpl extends JPanel implements DetailView { if (panel != null) { if (myDetailScrollPanel == null) { myDetailPanelWrapper = new JPanel(new GridLayout(1, 1)); - + myDetailPanelWrapper.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); myDetailPanelWrapper.add(panel); myDetailScrollPanel = diff --git a/platform/platform-api/src/com/intellij/ui/TitledSeparator.java b/platform/platform-api/src/com/intellij/ui/TitledSeparator.java index 010a55c960ff..6d759615473d 100644 --- a/platform/platform-api/src/com/intellij/ui/TitledSeparator.java +++ b/platform/platform-api/src/com/intellij/ui/TitledSeparator.java @@ -40,7 +40,7 @@ public class TitledSeparator extends JPanel { public TitledSeparator(String text) { setLayout(new GridBagLayout()); - add(myLabel, new GridBagConstraints(0, 0, 1, 1, 0, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + add(myLabel, new GridBagConstraints(0, 0, 1, 1, 0, 1, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 3, 0, 0), 0, 0)); add(mySeparator, new GridBagConstraints(1, 0, GridBagConstraints.REMAINDER, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(2, SEPARATOR_LEFT_INSET, 0, SEPARATOR_RIGHT_INSET), 0, 0)); From 0298f39d1861895cc59753e3c6f414e2ba283ace Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Tue, 15 May 2012 14:59:57 +0400 Subject: [PATCH 29/61] breakpoints ui. enable/disable action. --- .../ui/breakpoints/JavaBreakpointItem.java | 10 ++ .../ui/popup/util/DetailViewImpl.java | 5 +- .../popup/util/MasterDetailPopupBuilder.java | 2 + .../breakpoints/XBreakpointType.java | 7 +- .../breakpoints/XLineBreakpoint.java | 2 + .../breakpoints/XLineBreakpointType.java | 11 +- .../breakpoints/ui/BreakpointItem.java | 4 + .../impl/breakpoints/XBreakpointItem.java | 18 +++- .../impl/breakpoints/XBreakpointUtil.java | 4 + .../impl/breakpoints/XLineBreakpointImpl.java | 8 ++ .../BreakpointsMasterDetailPopupFactory.java | 100 +++++++++++++----- 11 files changed, 137 insertions(+), 34 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java index 96106874bf9c..4a16d4120bf5 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java @@ -115,4 +115,14 @@ class JavaBreakpointItem implements BreakpointItem { public Object getBreakpoint() { return myBreakpoint; } + + @Override + public boolean isEnabled() { + return myBreakpoint.ENABLED; + } + + @Override + public void setEnabled(boolean state) { + myBreakpoint.ENABLED = state; + } } diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java index 0ff966bc395f..1ea83d4a2972 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java @@ -45,12 +45,14 @@ public class DetailViewImpl extends JPanel implements DetailView { private JBScrollPane myDetailScrollPanel; private JPanel myDetailPanelWrapper; private JLabel myNothingToShow = new JLabel("Nothing to show"); + private JLabel myNothingToShowInEditor = new JLabel("Nothing to show"); public DetailViewImpl(Project project) { super(new BorderLayout()); myProject = project; setPreferredSize(new Dimension(600, 400)); myNothingToShow.setHorizontalAlignment(JLabel.CENTER); + myNothingToShowInEditor.setHorizontalAlignment(JLabel.CENTER); } @Override @@ -75,7 +77,7 @@ public class DetailViewImpl extends JPanel implements DetailView { remove(getEditor().getComponent()); EditorFactory.getInstance().releaseEditor(getEditor()); setEditor(null); - add(myNothingToShow, BorderLayout.CENTER); + add(myNothingToShowInEditor, BorderLayout.CENTER); repaint(); } } @@ -103,6 +105,7 @@ public class DetailViewImpl extends JPanel implements DetailView { if (document != null) { if (getEditor() == null || getEditor().getDocument() != document) { clearEditor(); + remove(myNothingToShowInEditor); setEditor(EditorFactory.getInstance().createViewer(document, project)); EditorHighlighter highlighter = EditorHighlighterFactory.getInstance() .createEditorHighlighter(file, EditorColorsManager.getInstance().getGlobalScheme(), project); diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java index d965c830d51b..084279a9a1be 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java @@ -332,6 +332,7 @@ public class MasterDetailPopupBuilder { add(myRenderer, BorderLayout.CENTER); } + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { if (value instanceof SplitterItem) { String label = ((SplitterItem)value).getText(); @@ -341,6 +342,7 @@ public class MasterDetailPopupBuilder { return separator; } myRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + myRenderer.revalidate(); return this; } } diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java index 1a24a22fa731..0961c416e82d 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java @@ -18,11 +18,8 @@ package com.intellij.xdebugger.breakpoints; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.project.Project; -import com.intellij.ui.ColoredListCellRenderer; -import com.intellij.ui.popup.util.DetailView; import com.intellij.xdebugger.XDebuggerUtil; import com.intellij.xdebugger.XSourcePosition; -import com.intellij.xdebugger.breakpoints.ui.BreakpointItem; import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel; import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroupingRule; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; @@ -191,6 +188,10 @@ public abstract class XBreakpointType, P extends XBreak return null; } + public String getShortText(B breakpoint) { + return getDisplayText(breakpoint); + } + public interface XBreakpointCreator

{ @NotNull XBreakpoint

createBreakpoint(@Nullable P properties); diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpoint.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpoint.java index 318360c98dfa..14d4b7aae28f 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpoint.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpoint.java @@ -35,4 +35,6 @@ public interface XLineBreakpoint

extends XBreak @NotNull XLineBreakpointType

getType(); + + String getShortFilePath(); } diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpointType.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpointType.java index 5ae43ab881c2..2a3582d49377 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpointType.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpointType.java @@ -71,7 +71,11 @@ public abstract class XLineBreakpointType

exten public abstract P createBreakpointProperties(@NotNull VirtualFile file, int line); public String getDisplayText(final XLineBreakpoint

breakpoint) { - return XDebuggerBundle.message("xbreakpoint.default.display.text", breakpoint.getLine() + 1, breakpoint.getPresentableFilePath()); + return fileLineDisplayText(breakpoint.getPresentableFilePath(), breakpoint.getLine()); + } + + private String fileLineDisplayText(String path, int line) { + return XDebuggerBundle.message("xbreakpoint.default.display.text", line + 1, path); } @NotNull @@ -87,6 +91,11 @@ public abstract class XLineBreakpointType

exten return null; } + @Override + public String getShortText(XLineBreakpoint

breakpoint) { + return fileLineDisplayText(breakpoint.getShortFilePath(), breakpoint.getLine()); + } + /** * Default line breakpoints aren't supported */ diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java index bd6ed506b1b9..d22376203b93 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/BreakpointItem.java @@ -26,4 +26,8 @@ import com.intellij.ui.popup.util.ItemWrapper; */ public interface BreakpointItem extends ItemWrapper { Object getBreakpoint(); + + boolean isEnabled(); + + void setEnabled(boolean state); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java index 65fa9bb88458..16e180dc5e29 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointItem.java @@ -45,8 +45,12 @@ class XBreakpointItem implements BreakpointItem { @Override public void setupRenderer(ColoredListCellRenderer renderer, Project project, boolean selected) { - renderer.setIcon(((XBreakpointBase)myBreakpoint).getIcon()); - renderer.append(XBreakpointUtil.getDisplayText(myBreakpoint)); + renderer.setIcon(getIcon()); + renderer.append(XBreakpointUtil.getShortText(myBreakpoint)); + } + + private Icon getIcon() { + return ((XBreakpointBase)myBreakpoint).getIcon(); } @Override @@ -114,4 +118,14 @@ class XBreakpointItem implements BreakpointItem { public Object getBreakpoint() { return myBreakpoint; } + + @Override + public boolean isEnabled() { + return myBreakpoint.isEnabled(); + } + + @Override + public void setEnabled(boolean state) { + myBreakpoint.setEnabled(state); + } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointUtil.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointUtil.java index 262ed8a6d942..b685d3dca09a 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointUtil.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointUtil.java @@ -36,6 +36,10 @@ public class XBreakpointUtil { private XBreakpointUtil() { } + public static > String getShortText(B breakpoint) { + return getType(breakpoint).getShortText(breakpoint); + } + public static > String getDisplayText(@NotNull B breakpoint) { return getType(breakpoint).getDisplayText(breakpoint); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java index 4e4158543d49..dfe161a81663 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java @@ -46,6 +46,7 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; import java.awt.dnd.DragSource; +import java.io.File; import java.util.List; /** @@ -123,6 +124,13 @@ public class XLineBreakpointImpl

extends XBreak return url != null ? url : ""; } + @Override + public String getShortFilePath() { + final String path = getPresentableFilePath(); + if (path.isEmpty()) return ""; + return new File(path).getName(); + } + @Nullable public RangeHighlighter getHighlighter() { return myHighlighter; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java index 5096b0f6e60b..dfe9a8b43955 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java @@ -17,7 +17,9 @@ package com.intellij.xdebugger.impl.breakpoints.ui; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CustomShortcutSet; import com.intellij.openapi.actionSystem.DefaultActionGroup; +import com.intellij.openapi.actionSystem.ex.CheckboxAction; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; @@ -50,6 +52,7 @@ public class BreakpointsMasterDetailPopupFactory { private final List myBreakpointPanelProviders; private Project myProject; + private BreakpointListModel myModel; public BreakpointsMasterDetailPopupFactory(Project project) { myProject = project; @@ -71,11 +74,11 @@ public class BreakpointsMasterDetailPopupFactory { public JBPopup createPopup(@Nullable Object initialBreakpoint) { final DefaultListSelectionModel selectionModel = new DefaultListSelectionModel(); - final BreakpointListModel model = createBreakpointsItemsList(selectionModel); - final JBList list = new JBList(model); + myModel = createBreakpointsItemsList(selectionModel); + final JBList list = new JBList(myModel); list.setSelectionModel(selectionModel); - selectInitial(initialBreakpoint, model, list); + selectInitial(initialBreakpoint, myModel, list); list.getEmptyText().setText("No Breakpoints"); @@ -108,7 +111,7 @@ public class BreakpointsMasterDetailPopupFactory { @Override public void onClosed(LightweightWindowEvent event) { - model.unsubscribe(); + myModel.unsubscribe(); } }); @@ -154,9 +157,48 @@ public class BreakpointsMasterDetailPopupFactory { } }); + actions.add(new CheckboxAction("Enabled"){ + { + registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0)), list); + } + @Override + public void update(AnActionEvent e) { + super.update(e); + e.getPresentation().setEnabled(list.getSelectedValue() instanceof BreakpointItem); + if (getCheckBox() != null) { + getCheckBox().setFocusable(false); + } + } + + @Override + public boolean isSelected(AnActionEvent e) { + return isSelectedBreakpointEnabled(list); + } + + @Override + public void setSelected(AnActionEvent e, boolean state) { + setSelectedBreakpointEnabled(list, state); + } + }); + return actions; } + private void setSelectedBreakpointEnabled(final JBList list, boolean state) { + final Object value = list.getSelectedValue(); + if (value instanceof BreakpointItem) { + ((BreakpointItem)value).setEnabled(state); + } + } + + private boolean isSelectedBreakpointEnabled(JBList list) { + final Object value = list.getSelectedValue(); + if (value instanceof BreakpointItem) { + return ((BreakpointItem)value).isEnabled(); + } + return false; + } + private BreakpointListModel createBreakpointsItemsList(DefaultListSelectionModel selectionModel) { final BreakpointListModel model = new BreakpointListModel(); final ArrayList items = collectItems(); @@ -168,7 +210,6 @@ public class BreakpointsMasterDetailPopupFactory { } - private ArrayList collectItems() { ArrayList items = new ArrayList(); for (BreakpointPanelProvider panelProvider : myBreakpointPanelProviders) { @@ -210,30 +251,35 @@ public class BreakpointsMasterDetailPopupFactory { if (!reallyChanged(items, myModel)) { return; } - final int index = mySelectionModel.getLeadSelectionIndex(); - myModel.removeAllElements(); - for (ItemWrapper item : items) { - myModel.addElement(item); - } - mySelectionModel.setLeadSelectionIndex(index); + rebuildModel(items, mySelectionModel, myModel); } - private boolean reallyChanged(List items, DefaultListModel model) { - if (items.size() != model.size()) return true; - for (int i = 0; i < model.size(); i++) { - final ItemWrapper item1 = items.get(i); - final ItemWrapper item2 = (ItemWrapper)model.get(i); - if (item1.getClass() != item2.getClass()) { - return true; - } - if (item1 instanceof BreakpointItem) { - if (((BreakpointItem)item1).getBreakpoint() != ((BreakpointItem)item2).getBreakpoint()) { - return true; - } - } - } - return false; - } } } + + private static void rebuildModel(ArrayList items, ListSelectionModel model, DefaultListModel model1) { + final int index = model.getLeadSelectionIndex(); + model1.removeAllElements(); + for (ItemWrapper item : items) { + model1.addElement(item); + } + model.setLeadSelectionIndex(index); + } + + private static boolean reallyChanged(List items, DefaultListModel model) { + if (items.size() != model.size()) return true; + for (int i = 0; i < model.size(); i++) { + final ItemWrapper item1 = items.get(i); + final ItemWrapper item2 = (ItemWrapper)model.get(i); + if (item1.getClass() != item2.getClass()) { + return true; + } + if (item1 instanceof BreakpointItem) { + if (((BreakpointItem)item1).getBreakpoint() != ((BreakpointItem)item2).getBreakpoint()) { + return true; + } + } + } + return false; + } } From f9e5f2af2b0b46a0b7804b28f62d765955b3767d Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Tue, 15 May 2012 17:51:17 +0400 Subject: [PATCH 30/61] breakpoints ui. show breakpoint types underneath of toolbar --- .../ui/popup/util/MasterDetailPopupBuilder.java | 14 ++++++++++---- .../ui/BreakpointsMasterDetailPopupFactory.java | 8 +++++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java index 084279a9a1be..b89274533ef5 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/util/MasterDetailPopupBuilder.java @@ -58,6 +58,12 @@ public class MasterDetailPopupBuilder { private Delegate myDelegate; private boolean myCloseOnEnter; + public ActionToolbar getActionToolbar() { + return myActionToolbar; + } + + private ActionToolbar myActionToolbar; + public MasterDetailPopupBuilder(Project project) { myProject = project; @@ -184,10 +190,10 @@ public class MasterDetailPopupBuilder { footerPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); footerPanel.add(pathLabel); - ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar("", myActions, true); - actionToolbar.setReservePlaceAutoPopupIcon(false); - actionToolbar.setMinimumButtonSize(new Dimension(20, 20)); - final JComponent toolBar = actionToolbar.getComponent(); + myActionToolbar = ActionManager.getInstance().createActionToolbar("", myActions, true); + myActionToolbar.setReservePlaceAutoPopupIcon(false); + myActionToolbar.setMinimumButtonSize(new Dimension(20, 20)); + final JComponent toolBar = myActionToolbar.getComponent(); toolBar.setOpaque(false); final JBPopup popup = new PopupChooserBuilder(myList). diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java index dfe9a8b43955..edc546a7446f 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointsMasterDetailPopupFactory.java @@ -53,6 +53,7 @@ public class BreakpointsMasterDetailPopupFactory { private final List myBreakpointPanelProviders; private Project myProject; private BreakpointListModel myModel; + private MasterDetailPopupBuilder myPopupBuilder; public BreakpointsMasterDetailPopupFactory(Project project) { myProject = project; @@ -84,7 +85,8 @@ public class BreakpointsMasterDetailPopupFactory { DefaultActionGroup actions = getActions(list); - final JBPopup popup = new MasterDetailPopupBuilder(myProject). + myPopupBuilder = new MasterDetailPopupBuilder(myProject); + final JBPopup popup = myPopupBuilder. setActionsGroup(actions). setList(list). setDelegate(new MasterDetailPopupBuilder.Delegate() { @@ -141,8 +143,8 @@ public class BreakpointsMasterDetailPopupFactory { public void actionPerformed(AnActionEvent e) { JBPopupFactory.getInstance() - .createActionGroupPopup("Choose type", breakpointTypes, e.getDataContext(), JBPopupFactory.ActionSelectionAid.NUMBERING, false) - .showInFocusCenter(); + .createActionGroupPopup(null, breakpointTypes, e.getDataContext(), JBPopupFactory.ActionSelectionAid.NUMBERING, false) + .showUnderneathOf(myPopupBuilder.getActionToolbar().getComponent()); } }); actions.add(new AnAction("Remove Breakpoint", null, PlatformIcons.DELETE_ICON) { From ac112dfc4948e831c54ca2e64b528657fe956382 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 15 May 2012 15:55:55 +0200 Subject: [PATCH 31/61] use per-module encoding settings --- .../CompilerEncodingConfiguration.java | 6 ++- .../jps/incremental/java/JavaBuilder.java | 46 +++++++++++++------ .../jps/incremental/groovy/GroovyBuilder.java | 4 +- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompilerEncodingConfiguration.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompilerEncodingConfiguration.java index 62bedef2151b..8a10c1a2f14e 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompilerEncodingConfiguration.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompilerEncodingConfiguration.java @@ -87,9 +87,11 @@ public class CompilerEncodingConfiguration { for (Module module : moduleChunk.getModules()) { final Set encodings = getModuleCharsetMap().get(module.getName()); final String encoding = ContainerUtil.getFirstItem(encodings, null); - if (encoding != null) return encoding; + if (encoding != null) { + return encoding; + } } - return null; + return moduleChunk.getProject().getProjectCharset(); } @NotNull diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index d7a5483a6608..6f1f2f4c4652 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -38,7 +38,8 @@ import org.jetbrains.jps.incremental.storage.BuildDataManager; import org.jetbrains.jps.incremental.storage.SourceToFormMapping; import org.jetbrains.jps.javac.*; -import javax.tools.*; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; import java.io.*; import java.net.MalformedURLException; import java.net.ServerSocket; @@ -584,7 +585,7 @@ public class JavaBuilder extends ModuleLevelBuilder { private static List getCompilationVMOptions(CompileContext context) { List cached = JAVAC_VM_OPTIONS.get(context); if (cached == null) { - loadJavacOptions(context); + loadCommonJavacOptions(context); cached = JAVAC_VM_OPTIONS.get(context); } return cached; @@ -593,10 +594,28 @@ public class JavaBuilder extends ModuleLevelBuilder { private static List getCompilationOptions(CompileContext context, ModuleChunk chunk) { List cached = JAVAC_OPTIONS.get(context); if (cached == null) { - loadJavacOptions(context); + loadCommonJavacOptions(context); cached = JAVAC_OPTIONS.get(context); } + final List options = new ArrayList(cached); + if (!isEncodingSet(options)) { + final CompilerEncodingConfiguration config = context.getProjectDescriptor().getEncodingConfiguration(); + final String encoding = config.getPreferredModuleChunkEncoding(chunk); + if (config.getAllModuleChunkEncodings(chunk).size() > 1) { + final StringBuilder msgBuilder = new StringBuilder(); + msgBuilder.append("Multiple encodings set for module chunk ").append(getChunkPresentableName(chunk)); + if (encoding != null) { + msgBuilder.append("\n\"").append(encoding).append("\" will be used by compiler"); + } + context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.INFO, msgBuilder.toString())); + } + if (encoding != null) { + options.add("-encoding"); + options.add(encoding); + } + } + final String langlevel = chunk.getModules().iterator().next().getLanguageLevel(); if (!StringUtil.isEmpty(langlevel)) { options.add("-source"); @@ -644,6 +663,16 @@ public class JavaBuilder extends ModuleLevelBuilder { return options; } + private static boolean isEncodingSet(List options) { + for (String option : options) { + if ("-encoding".equals(option)) { + return true; + } + } + return false; + } + + private static int getCompilerSdkVersion(CompileContext context) { final Integer cached = JAVA_COMPILER_VERSION_KEY.get(context); if (cached != null) { @@ -673,7 +702,7 @@ public class JavaBuilder extends ModuleLevelBuilder { return config.getProjectBytecodeTarget(); } - private static void loadJavacOptions(CompileContext context) { + private static void loadCommonJavacOptions(CompileContext context) { final List options = new ArrayList(); final List vmOptions = new ArrayList(); @@ -694,7 +723,6 @@ public class JavaBuilder extends ModuleLevelBuilder { } final String customArgs = javacOpts.get("ADDITIONAL_OPTIONS_STRING"); - boolean isEncodingSet = false; if (customArgs != null) { final StringTokenizer tokenizer = new StringTokenizer(customArgs, " \t\r\n"); while (tokenizer.hasMoreTokens()) { @@ -708,17 +736,9 @@ public class JavaBuilder extends ModuleLevelBuilder { else { options.add(token); } - if ("-encoding".equals(token)) { - isEncodingSet = true; - } } } - if (!isEncodingSet && !StringUtil.isEmpty(project.getProjectCharset())) { - options.add("-encoding"); - options.add(project.getProjectCharset()); - } - JAVAC_OPTIONS.set(context, options); JAVAC_VM_OPTIONS.set(context, vmOptions); } diff --git a/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java b/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java index f23b54077dd6..1cb782365946 100644 --- a/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java +++ b/plugins/groovy/rt/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java @@ -1,7 +1,6 @@ package org.jetbrains.jps.incremental.groovy; -import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.ArrayUtil; @@ -63,8 +62,7 @@ public class GroovyBuilder extends ModuleLevelBuilder { Map class2Src = buildClassToSourceMap(chunk, context, toCompilePaths, moduleOutput); - String ideCharset = chunk.getProject().getProjectCharset(); - String encoding = !Comparing.equal(CharsetToolkit.getDefaultSystemCharset().name(), ideCharset) ? ideCharset : null; + final String encoding = context.getProjectDescriptor().getEncodingConfiguration().getPreferredModuleChunkEncoding(chunk); List patchers = Collections.emptyList(); //todo patchers final File tempFile = GroovycOSProcessHandler.fillFileWithGroovycParameters( compilerOutput, toCompilePaths, FileUtil.toSystemDependentName(moduleOutput), class2Src, encoding, patchers From 94bdf490a2d81f8ef71d3029de1a214c5c82e3fc Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 15 May 2012 15:56:38 +0200 Subject: [PATCH 32/61] fix NPE --- .../jps/incremental/java/JavaBuilder.java | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index 6f1f2f4c4652..635a2edb3e9e 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -490,20 +490,22 @@ public class JavaBuilder extends ModuleLevelBuilder { } private static int convertToNumber(final String ver) { - final String prefix = "1."; - if (ver.startsWith(prefix)) { - final String versionNumberString; - final int dotIndex = ver.indexOf(".", prefix.length()); - if (dotIndex > 0) { - versionNumberString = ver.substring(prefix.length(), dotIndex); - } - else { - versionNumberString = ver.substring(prefix.length()); - } - try { - return Integer.parseInt(versionNumberString); - } - catch (NumberFormatException ignored) { + if (ver != null) { + final String prefix = "1."; + if (ver.startsWith(prefix)) { + final String versionNumberString; + final int dotIndex = ver.indexOf(".", prefix.length()); + if (dotIndex > 0) { + versionNumberString = ver.substring(prefix.length(), dotIndex); + } + else { + versionNumberString = ver.substring(prefix.length()); + } + try { + return Integer.parseInt(versionNumberString); + } + catch (NumberFormatException ignored) { + } } } return 0; From 8009a2f6e80b381f70f97b1831056d3a18d08c9e Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 15 May 2012 18:16:53 +0400 Subject: [PATCH 33/61] IDEA-84573 (Maven: configurable generate-sources behavior - use it as a source root or use intermediate folders) Fix problems found on review. --- .../maven/importing/MavenFoldersImporter.java | 39 +++++++++++-------- .../maven/project/MavenImportingSettings.java | 33 +++++++++++----- .../maven/importing/FoldersImportingTest.java | 36 +++++++++++++++++ 3 files changed, 81 insertions(+), 27 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java index 61d03c11270e..235e1d1f2f33 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java @@ -201,39 +201,44 @@ public class MavenFoldersImporter { } } - private void configGeneratedSourceFolder(@NotNull File dir, boolean isTestSources) { + private void configGeneratedSourceFolder(@NotNull File targetDir, boolean isTestSources) { switch (myImportingSettings.getGeneratedSourcesFolder()) { case GENERATED_SOURCE_FOLDER: - if (!myModel.hasRegisteredSourceSubfolder(dir)) { - myModel.addSourceFolder(dir.getPath(), isTestSources); - } + addAsSourceFolder(targetDir, isTestSources); break; case SUBFOLDER: - addAllSubDirsAsSources(dir, isTestSources); + addAllSubDirsAsSources(targetDir, isTestSources); break; case AUTODETECT: - Collection sourceRoots = JavaSourceRootDetectionUtil.suggestRoots(dir); - if (sourceRoots.size() == 1) { - JavaModuleSourceRoot root = sourceRoots.iterator().next(); - if (dir.equals(root.getDirectory())) { - if (!myModel.hasRegisteredSourceSubfolder(dir)) { - myModel.addSourceFolder(dir.getPath(), isTestSources); - } - break; + Collection sourceRoots = JavaSourceRootDetectionUtil.suggestRoots(targetDir); + + for (JavaModuleSourceRoot root : sourceRoots) { + if (targetDir.equals(root.getDirectory())) { + addAsSourceFolder(targetDir, isTestSources); + return; } + + addAsSourceFolder(root.getDirectory(), isTestSources); } - addAllSubDirsAsSources(dir, isTestSources); + + addAllSubDirsAsSources(targetDir, isTestSources); break; } } + private void addAsSourceFolder(@NotNull File dir, boolean isTestSources) { + if (!myModel.hasRegisteredSourceSubfolder(dir)) { + myModel.addSourceFolder(dir.getPath(), isTestSources); + } + } + private void addAllSubDirsAsSources(@NotNull File dir, boolean isTestSources) { for (File f : getChildren(dir)) { - if (!f.isDirectory()) continue; - if (myModel.hasRegisteredSourceSubfolder(f)) continue; - myModel.addSourceFolder(f.getPath(), isTestSources); + if (f.isDirectory()) { + addAsSourceFolder(f, isTestSources); + } } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenImportingSettings.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenImportingSettings.java index 0604282bafdb..dab37f367960 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenImportingSettings.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenImportingSettings.java @@ -52,7 +52,7 @@ public class MavenImportingSettings implements Cloneable { private List myListeners = ContainerUtil.createEmptyCOWList(); public enum GeneratedSourcesFolder { - AUTODETECT("Auto detect"), + AUTODETECT("Detect automatically"), GENERATED_SOURCE_FOLDER("target/generated-sources"), SUBFOLDER("subdirectories of \"target/generated-sources\""); @@ -187,16 +187,29 @@ public class MavenImportingSettings implements Cloneable { @Override public int hashCode() { - int result = dedicatedModuleDir.hashCode(); - result = 31 * result + (lookForNested ? 1 : 0); - result = 31 * result + (importAutomatically ? 1 : 0); - result = 31 * result + (createModulesForAggregators ? 1 : 0); - result = 31 * result + (createModuleGroups ? 1 : 0); - result = 31 * result + (keepSourceFolders ? 1 : 0); - result = 31 * result + (useMavenOutput ? 1 : 0); + int result = 0; + + if (lookForNested) result++; + result <<= 1; + if (importAutomatically) result++; + result <<= 1; + if (createModulesForAggregators) result++; + result <<= 1; + if (createModuleGroups) result++; + result <<= 1; + if (keepSourceFolders) result++; + result <<= 1; + if (useMavenOutput) result++; + result <<= 1; + if (downloadSourcesAutomatically) result++; + result <<= 1; + if (downloadDocsAutomatically) result++; + result <<= 1; + result = 31 * result + (updateFoldersOnImportPhase != null ? updateFoldersOnImportPhase.hashCode() : 0); - result = 31 * result + (downloadSourcesAutomatically ? 1 : 0); - result = 31 * result + (downloadDocsAutomatically ? 1 : 0); + result = 31 * result + dedicatedModuleDir.hashCode(); + result = 31 * result + generatedSourcesFolder.hashCode(); + return result; } diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/FoldersImportingTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/FoldersImportingTest.java index 4e343e5f6011..80dde852438b 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/FoldersImportingTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/FoldersImportingTest.java @@ -589,6 +589,42 @@ public class FoldersImportingTest extends MavenImportingTestCase { "target/generated-sources/com"); } + public void testAddingExistingGeneratedSources4() throws Exception { + createStdProjectFolders(); + + createProjectSubFile("target/generated-sources/A1/B1/com/A1.java", "package com; class A1 {}"); + createProjectSubFile("target/generated-sources/A1/B2/com/A2.java", "package com; class A2 {}"); + createProjectSubFile("target/generated-sources/A2/com/A3.java", "package com; class A3 {}"); + + importProject("test" + + "project" + + "1"); + + assertSources("project", + "src/main/java", + "src/main/resources", + "target/generated-sources/A1/B1", + "target/generated-sources/A1/B2", + "target/generated-sources/A2"); + } + + public void testAddingExistingGeneratedSources5() throws Exception { + createStdProjectFolders(); + + createProjectSubFile("target/generated-sources/A1/B1/com/A1.java", "package com; class A1 {}"); + createProjectSubFile("target/generated-sources/A2.java", "class A2 {}"); + + importProject("test" + + "project" + + "1"); + + assertSources("project", + "src/main/java", + "src/main/resources", + "target/generated-sources"); + } + + public void testAddingExistingGeneratedSourcesWithCustomTargetDir() throws Exception { createStdProjectFolders(); createProjectSubDirs("targetCustom/generated-sources/src", From 5bcfdf9699001579e3d2afc2744a9300814d0f9a Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Fri, 11 May 2012 21:09:42 +0400 Subject: [PATCH 34/61] Pre-refactoring cleanup. (Done mostly what inspections suggested) --- .../ui/layout/impl/JBRunnerTabs.java | 4 - .../src/com/intellij/ui/tabs/JBTabs.java | 41 +--- .../intellij/ui/tabs/JBTabsPresentation.java | 25 +-- .../intellij/ui/tabs/impl/ActionButton.java | 4 - .../intellij/ui/tabs/impl/ActionPanel.java | 4 +- .../com/intellij/ui/tabs/impl/DragHelper.java | 12 +- .../com/intellij/ui/tabs/impl/JBTabsImpl.java | 205 ++++-------------- .../intellij/ui/tabs/impl/LayoutPassInfo.java | 2 +- .../intellij/ui/tabs/impl/ShapeTransform.java | 29 +-- .../com/intellij/ui/tabs/impl/TabLabel.java | 32 ++- .../com/intellij/ui/tabs/impl/TabLayout.java | 1 - .../com/intellij/ui/tabs/impl/TabsBorder.java | 9 +- .../singleRow/ScrollableSingleRowLayout.java | 2 +- .../tabs/impl/singleRow/SingleRowLayout.java | 40 ++-- .../singleRow/SingleRowLayoutStrategy.java | 32 +-- .../impl/singleRow/SingleRowPassInfo.java | 15 +- .../ui/tabs/impl/table/TableLayout.java | 10 +- .../ui/tabs/impl/table/TablePassInfo.java | 6 +- .../intellij/ui/tabs/impl/table/TableRow.java | 6 +- 19 files changed, 123 insertions(+), 356 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java index 70beed4ea9a2..e7e923128667 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java @@ -53,10 +53,6 @@ public class @Override protected void paintLastGhost(Graphics2D g2d) {} - public boolean isGhostsAlwaysVisible() { - return false; - } - protected void doPaintInactive(Graphics2D g2d, boolean leftGhostExists, TabLabel label, diff --git a/platform/platform-api/src/com/intellij/ui/tabs/JBTabs.java b/platform/platform-api/src/com/intellij/ui/tabs/JBTabs.java index c263be580500..7e95d62fe9ad 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/JBTabs.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/JBTabs.java @@ -19,7 +19,6 @@ import com.intellij.openapi.actionSystem.ActionGroup; import com.intellij.openapi.actionSystem.DataProvider; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.ActiveRunnable; -import com.intellij.openapi.util.Getter; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.switcher.SwitchProvider; import org.jetbrains.annotations.NotNull; @@ -29,8 +28,6 @@ import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; -import java.util.Comparator; -import java.util.List; public interface JBTabs extends SwitchProvider { @@ -42,21 +39,10 @@ public interface JBTabs extends SwitchProvider { ActionCallback removeTab(@Nullable TabInfo info); - ActionCallback removeTab(@Nullable TabInfo info, @Nullable TabInfo forcedSelectionTranfer); - - ActionCallback removeTab(@Nullable TabInfo info, @Nullable TabInfo forcedSelectionTranfer, boolean transferFocus); - void removeAllTabs(); - @Nullable - ActionGroup getPopupGroup(); - - @Nullable - String getPopupPlace(); - JBTabs setPopupGroup(@NotNull ActionGroup popupGroup, @NotNull String place, final boolean addNavigationGroup); - JBTabs setPopupGroup(@NotNull Getter popupGroup, @NotNull String place, final boolean addNavigationGroup); - + ActionCallback select(@NotNull TabInfo info, boolean requestFocus); @Nullable @@ -65,9 +51,6 @@ public interface JBTabs extends SwitchProvider { @NotNull TabInfo getTabAt(int tabIndex); - @NotNull - List getTabs(); - int getTabCount(); @NotNull @@ -76,31 +59,19 @@ public interface JBTabs extends SwitchProvider { @Nullable DataProvider getDataProvider(); - JBTabs setDataProvider(@NotNull DataProvider dataProvider); - @Nullable TabInfo getTargetInfo(); @NotNull JBTabs addTabMouseListener(@NotNull MouseListener listener); - @NotNull - JBTabs removeTabMouseListener(@NotNull MouseListener listener); - JBTabs addListener(@NotNull TabsListener listener); - JBTabs removeListener(@NotNull TabsListener listener); - JBTabs setSelectionChangeHandler(SelectionChangeHandler handler); @NotNull JComponent getComponent(); - void updateTabActions(boolean validateNow); - - @Nullable - TabInfo findInfo(Component component); - @Nullable TabInfo findInfo(MouseEvent event); @@ -109,11 +80,7 @@ public interface JBTabs extends SwitchProvider { int getIndexOf(@Nullable final TabInfo tabInfo); - void sortTabs(Comparator comparator); - void requestFocus(); - - boolean isEditorTabs(); JBTabs setNavigationActionBinding(String prevActiobId, String nextActionId); JBTabs setNavigationActionsEnabled(boolean enabled); @@ -122,16 +89,10 @@ public interface JBTabs extends SwitchProvider { JBTabs setAdditionalSwitchProviderWhenOriginal(SwitchProvider delegate); - Image getComponentImage(TabInfo info); - void resetDropOver(TabInfo tabInfo); Image startDropOver(TabInfo tabInfo, RelativePoint point); void processDropOver(TabInfo over, RelativePoint point); - boolean isEmptyVisible(); - - int getInterTabSpaceLength(); - interface SelectionChangeHandler { ActionCallback execute(final TabInfo info, final boolean requestFocus, ActiveRunnable doChangeSelection); } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/JBTabsPresentation.java b/platform/platform-api/src/com/intellij/ui/tabs/JBTabsPresentation.java index 33fe1a0064a6..e354fb6d79f9 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/JBTabsPresentation.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/JBTabsPresentation.java @@ -30,14 +30,10 @@ public interface JBTabsPresentation { JBTabsPresentation setPaintBorder(int top, int left, int right, int bottom); JBTabsPresentation setTabSidePaintBorder(int size); - boolean isPaintFocus(); - JBTabsPresentation setPaintFocus(boolean paintFocus); JBTabsPresentation setStealthTabMode(boolean stealthTabMode); - boolean isStealthTabMode(); - JBTabsPresentation setSideComponentVertical(boolean vertical); JBTabsPresentation setSideComponentOnTabs(boolean onTabs); @@ -46,35 +42,18 @@ public interface JBTabsPresentation { boolean isSingleRow(); - boolean isSideComponentVertical(); - - boolean isSideComponentOnTabs(); - JBTabsPresentation setUiDecorator(@Nullable UiDecorator decorator); - boolean isRequestFocusOnLastFocusedComponent(); - JBTabsPresentation setRequestFocusOnLastFocusedComponent(boolean request); void setPaintBlocked(boolean blocked, final boolean takeSnapshot); - void setFocused(boolean focused); - JBTabsPresentation setInnerInsets(Insets innerInsets); - Insets getInnerInsets(); - JBTabsPresentation setGhostsAlwaysVisible(boolean visible); - boolean isGhostsAlwaysVisible(); - - @NotNull - JBTabsPresentation setAdjustBorders(boolean adjust); - JBTabsPresentation setFocusCycle(final boolean root); - boolean isToDrawBorderIfTabsHidden(); - @NotNull JBTabsPresentation setToDrawBorderIfTabsHidden(boolean draw); @@ -96,9 +75,7 @@ public interface JBTabsPresentation { JBTabsPosition getTabsPosition(); JBTabsPresentation setTabDraggingEnabled(boolean enabled); - - boolean isTabDraggingEnabled(); JBTabsPresentation setProvideSwitchTargets(boolean provide); -} \ No newline at end of file +} diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionButton.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionButton.java index 3dc1fe1f2b56..431132fffa12 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionButton.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionButton.java @@ -127,10 +127,6 @@ class ActionButton extends IconButton implements ActionListener { } } - public boolean isAutoHide() { - return myAutoHide; - } - public void toggleShowActions(boolean show) { if (myAutoHide) { myButton.setPainting(show); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java index 838a6a1e5095..2d5a66168223 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java @@ -37,15 +37,13 @@ public class ActionPanel extends NonOpaquePanel { private boolean myAutoHide; private boolean myActionsIsVisible = false; - private final int myGap = 2; - public ActionPanel(JBTabsImpl tabs, TabInfo tabInfo, Pass pass) { myTabs = tabs; ActionGroup group = tabInfo.getTabLabelActions() != null ? tabInfo.getTabLabelActions() : new DefaultActionGroup(); AnAction[] children = group.getChildren(null); final NonOpaquePanel wrapper = new NonOpaquePanel(new BorderLayout()); - wrapper.add(Box.createHorizontalStrut(myGap), BorderLayout.WEST); + wrapper.add(Box.createHorizontalStrut(2), BorderLayout.WEST); NonOpaquePanel inner = new NonOpaquePanel(); inner.setLayout(new BoxLayout(inner, BoxLayout.X_AXIS)); wrapper.add(inner, BorderLayout.CENTER); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java index 6e1186198afb..fda9ee1622d0 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java @@ -29,12 +29,12 @@ import java.awt.event.MouseEvent; class DragHelper extends MouseDragHelper { - JBTabsImpl myTabs; - TabInfo myDragSource; - Rectangle myDragOriginalRec; + private final JBTabsImpl myTabs; + private TabInfo myDragSource; + private Rectangle myDragOriginalRec; Rectangle myDragRec; - Dimension myHoldDelta; + private Dimension myHoldDelta; private TabInfo myDragOutSource; private TabLabel myPressedTabLabel; @@ -147,7 +147,7 @@ class DragHelper extends MouseDragHelper { if (targetLabel != null) { Rectangle saved = myDragRec; myDragRec = null; - myTabs.reallocate(myDragSource, targetLabel.getInfo(), true); + myTabs.reallocate(myDragSource, targetLabel.getInfo()); myDragOriginalRec = myTabs.myInfo2Label.get(myDragSource).getBounds(); myDragRec = saved; myTabs.moveDraggedTabLabel(); @@ -251,4 +251,4 @@ class DragHelper extends MouseDragHelper { public TabInfo getDragSource() { return myDragSource; } -} \ No newline at end of file +} diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java index aed4055b1853..f0623fa5895c 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java @@ -19,12 +19,12 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.GraphicsConfig; import com.intellij.openapi.ui.Queryable; import com.intellij.openapi.ui.ShadowAction; import com.intellij.openapi.util.*; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.wm.*; -import com.intellij.openapi.ui.GraphicsConfig; import com.intellij.ui.CaptionPanel; import com.intellij.ui.ColorUtil; import com.intellij.ui.Gray; @@ -65,12 +65,11 @@ import java.util.concurrent.CopyOnWriteArrayList; public class JBTabsImpl extends JComponent implements JBTabs, PropertyChangeListener, TimerListener, DataProvider, PopupMenuListener, Disposable, JBTabsPresentation, Queryable, QuickActionProvider { - public static DataKey NAVIGATION_ACTIONS_KEY = DataKey.create("JBTabs"); + public static final DataKey NAVIGATION_ACTIONS_KEY = DataKey.create("JBTabs"); - public static final String EDITOR_TABS = "main.editor.tabs"; public static final Color MAC_AQUA_BG_COLOR = Gray._200; - ActionManager myActionManager; + final ActionManager myActionManager; private final List myVisibleInfos = new ArrayList(); private final Map myHiddenInfos = new HashMap(); @@ -83,15 +82,15 @@ public class JBTabsImpl extends JComponent private final List myTabMouseListeners = new CopyOnWriteArrayList(); private final List myTabListeners = new CopyOnWriteArrayList(); - public boolean myFocused; + private boolean myFocused; private Getter myPopupGroup; private String myPopupPlace; TabInfo myPopupInfo; - DefaultActionGroup myNavigationActions; + final DefaultActionGroup myNavigationActions; - PopupMenuListener myPopupListener; + final PopupMenuListener myPopupListener; JPopupMenu myActivePopup; public boolean myHorizontalSide = true; @@ -130,7 +129,7 @@ public class JBTabsImpl extends JComponent private boolean myPaintBlocked; private BufferedImage myImage; private IdeFocusManager myFocusManager; - private boolean myAdjustBorders = true; + private final boolean myAdjustBorders = true; boolean myAddNavigationGroup = true; @@ -177,7 +176,7 @@ public class JBTabsImpl extends JComponent this(project, project); } - public JBTabsImpl(@NotNull Project project, @NotNull Disposable parent) { + private JBTabsImpl(@NotNull Project project, @NotNull Disposable parent) { this(project, ActionManager.getInstance(), IdeFocusManager.getInstance(project), parent); } @@ -331,8 +330,7 @@ public class JBTabsImpl extends JComponent return this; } - @Override - public Image getComponentImage(TabInfo info) { + public static Image getComponentImage(TabInfo info) { JComponent cmp = info.getComponent(); BufferedImage img; @@ -461,7 +459,7 @@ public class JBTabsImpl extends JComponent return myDropInfo != null && myDropInfo == info; } - public void setDropInfoIndex(int dropInfoIndex) { + protected void setDropInfoIndex(int dropInfoIndex) { myDropInfoIndex = dropInfoIndex; } @@ -474,8 +472,7 @@ public class JBTabsImpl extends JComponent public void mouseMoved(final MouseEvent e) { if (!myTabLabelActionsAutoHide) return; - final Point point = SwingUtilities.convertPoint(e.getComponent(), e.getX(), e.getY(), JBTabsImpl.this); - myLastOverPoint = point; + myLastOverPoint = SwingUtilities.convertPoint(e.getComponent(), e.getX(), e.getY(), JBTabsImpl.this); processMouseOver(); } @@ -590,6 +587,7 @@ public class JBTabsImpl extends JComponent } + @Nullable private JComponent getToFocus() { final TabInfo info = getSelectedInfo(); @@ -637,18 +635,6 @@ public class JBTabsImpl extends JComponent } } - private JBTabsImpl findTabs(Component c) { - Component eachParent = c; - while (eachParent != null) { - if (eachParent instanceof JBTabsImpl) { - return (JBTabsImpl)eachParent; - } - eachParent = eachParent.getParent(); - } - - return null; - } - @NotNull public TabInfo addTab(TabInfo info, int index) { @@ -669,10 +655,7 @@ public class JBTabsImpl extends JComponent myInfo2Label.put(info, label); if (!isDropTarget) { - if (index < 0) { - myVisibleInfos.add(info); - } - else if (index > myVisibleInfos.size() - 1) { + if (index < 0 || index > myVisibleInfos.size() - 1) { myVisibleInfos.add(info); } else { @@ -719,6 +702,7 @@ public class JBTabsImpl extends JComponent return addTab(info, -1); } + @Nullable public ActionGroup getPopupGroup() { return myPopupGroup != null ? myPopupGroup.get() : null; } @@ -847,7 +831,7 @@ public class JBTabsImpl extends JComponent } } - private void fireBeforeSelectionChanged(TabInfo oldInfo, TabInfo newInfo) { + private void fireBeforeSelectionChanged(@Nullable TabInfo oldInfo, TabInfo newInfo) { if (oldInfo != newInfo) { myOldSelection = oldInfo; try { @@ -861,7 +845,7 @@ public class JBTabsImpl extends JComponent } } - private void fireSelectionChanged(TabInfo oldInfo, TabInfo newInfo) { + private void fireSelectionChanged(@Nullable TabInfo oldInfo, TabInfo newInfo) { if (oldInfo != newInfo) { for (TabsListener eachListener : myTabListeners) { if (eachListener != null) { @@ -956,19 +940,6 @@ public class JBTabsImpl extends JComponent myDeferredToRemove.clear(); } - private void printRemoveInfo(final Component each) { - TabInfo removingInfo = null; - final List all = getTabs(); - for (TabInfo eachInfo : all) { - if (eachInfo.getComponent() == each) { - removingInfo = eachInfo; - break; - } - } - - //System.out.println(" - removing " + (removingInfo != null ? " component for " + removingInfo : each)); - } - public void propertyChange(final PropertyChangeEvent evt) { final TabInfo tabInfo = (TabInfo)evt.getSource(); if (TabInfo.ACTION_GROUP.equals(evt.getPropertyName())) { @@ -1322,7 +1293,7 @@ public class JBTabsImpl extends JComponent } } - public boolean isToDrawBorderIfTabsHidden() { + private boolean isToDrawBorderIfTabsHidden() { return myToDrawBorderIfTabsHidden; } @@ -1339,11 +1310,9 @@ public class JBTabsImpl extends JComponent public static class Toolbar extends JPanel { private final JBTabsImpl myTabs; - private final TabInfo myInfo; public Toolbar(JBTabsImpl tabs, TabInfo info) { myTabs = tabs; - myInfo = info; setLayout(new BorderLayout()); @@ -1489,7 +1458,7 @@ public class JBTabsImpl extends JComponent return this; } - public Insets getInnerInsets() { + private Insets getInnerInsets() { return myInnerInsets; } @@ -1542,15 +1511,15 @@ public class JBTabsImpl extends JComponent } - protected int getArcSize() { + private static int getArcSize() { return 4; } - protected int getEdgeArcSize() { + private static int getEdgeArcSize() { return 3; } - public int getGhostTabLength() { + public static int getGhostTabLength() { return 15; } @@ -1622,7 +1591,8 @@ public class JBTabsImpl extends JComponent config.restore(); } - protected Color getActiveTabColor(final Color c) { + @Nullable + protected Color getActiveTabColor(@Nullable final Color c) { final TabInfo info = getSelectedInfo(); if (info == null) { return c; @@ -1857,10 +1827,6 @@ public class JBTabsImpl extends JComponent g2d.drawLine(bottomX - path.deltaX(1), topY + path.deltaY(getArcSize()), bottomX - path.deltaX(1), bottomY - path.deltaY(1)); } - protected SingleRowLayout getSingleRowLayout() { - return mySingleRowLayout; - } - protected void paintLastGhost(Graphics2D g2d) { final ShapeTransform path = getEffectiveLayout().createShapeTransform(mySingleRowLayout.myLastSingRowLayout.lastGhost); @@ -1887,25 +1853,21 @@ public class JBTabsImpl extends JComponent g2d.drawLine(topX, topY + path.deltaY(1), bottomX - path.deltaX(getCurveArc()), topY + path.deltaY(1)); } - protected int getCurveArc() { + private static int getCurveArc() { return 2; } - protected Color getBoundsColor() { + private static Color getBoundsColor() { return Color.gray; } - protected Color getRightBlockColor() { + private static Color getRightBlockColor() { return Color.lightGray; } - protected Color getTopBlockColor() { + private static Color getTopBlockColor() { return Color.white; } - - protected boolean shouldPaintFocus() { - return myPaintFocus; - } private void paintNonSelectedTabs(final Graphics2D g2d, final boolean leftGhostExists, final boolean rightGhostExists) { TabInfo selected = getSelectedInfo(); @@ -1976,18 +1938,6 @@ public class JBTabsImpl extends JComponent protected LayoutPassInfo getLastLayoutPass() { return myLastLayoutPass; } - - protected TabLabel getInfoForLabel(TabInfo info) { - return myInfo2Label.get(info); - } - - protected TableLayout getTableLayout() { - return myTableLayout; - } - - protected DragHelper getDragHelper() { - return myDragHelper; - } @Override public Color getBackground() { @@ -2035,8 +1985,7 @@ public class JBTabsImpl extends JComponent boolean leftFromSelection = selected != null && tabIndex == myVisibleInfos.indexOf(selected) - 1; - Rectangle originalBounds = effectiveBounds; - final ShapeTransform shape = getEffectiveLayout().createShapeTransform(originalBounds); + final ShapeTransform shape = getEffectiveLayout().createShapeTransform(effectiveBounds); int leftX = firstShowing ? shape.getX() : shape.getX() - shape.deltaX(arc + 1); int topY = shape.getY() + shape.deltaY(selectionTabVShift); @@ -2115,7 +2064,7 @@ public class JBTabsImpl extends JComponent g2d.draw(shape.getShape()); } - public int getSelectionTabVShift() { + public static int getSelectionTabVShift() { return 2; } @@ -2189,7 +2138,7 @@ public class JBTabsImpl extends JComponent } - public boolean isStealthModeEffective() { + protected boolean isStealthModeEffective() { return myStealthTabMode && getTabCount() == 1 && (isSideComponentVertical() || !isSideComponentOnTabs()) && getTabsPosition() == JBTabsPosition.top; @@ -2358,16 +2307,8 @@ public class JBTabsImpl extends JComponent return this; } - public ActionCallback removeTab(final JComponent component) { - return removeTab(findInfo(component)); - } - public ActionCallback removeTab(final TabInfo info) { - return removeTab(info, null); - } - - public ActionCallback removeTab(final TabInfo info, @Nullable TabInfo forcedSelectionTransfer) { - return removeTab(info, forcedSelectionTransfer, true); + return removeTab(info, null, true); } public ActionCallback removeTab(final TabInfo info, @Nullable TabInfo forcedSelectionTransfer, boolean transferFocus) { @@ -2442,6 +2383,7 @@ public class JBTabsImpl extends JComponent myLastPaintedSelection = null; } + @Nullable public TabInfo findInfo(Component component) { for (TabInfo each : getTabs()) { if (each.getComponent() == component) return each; @@ -2450,20 +2392,11 @@ public class JBTabsImpl extends JComponent return null; } - public TabInfo findInfo(String text) { - if (text == null) return null; - - for (TabInfo each : getTabs()) { - if (text.equals(each.getText())) return each; - } - - return null; - } - public TabInfo findInfo(MouseEvent event) { return findInfo(event, false); } + @Nullable private TabInfo findInfo(final MouseEvent event, final boolean labelsOnly) { final Point point = SwingUtilities.convertPoint(event.getComponent(), event.getPoint(), this); return _findInfo(point, labelsOnly); @@ -2478,10 +2411,6 @@ public class JBTabsImpl extends JComponent return null; } - public TabInfo findTabLabelBy(final Point point) { - return _findInfo(point, true); - } - @Nullable private TabInfo _findInfo(final Point point, boolean labelsOnly) { Component component = findComponentAt(point); @@ -2509,8 +2438,8 @@ public class JBTabsImpl extends JComponent private static class Max { - Dimension myLabel = new Dimension(); - Dimension myToolbar = new Dimension(); + final Dimension myLabel = new Dimension(); + final Dimension myToolbar = new Dimension(); } private void updateContainer(boolean forced, final boolean layoutNow) { @@ -2539,7 +2468,7 @@ public class JBTabsImpl extends JComponent } } - mySingleRowLayout.scrollSelectionInView(myVisibleInfos); + mySingleRowLayout.scrollSelectionInView(); relayout(forced, layoutNow); } @@ -2569,14 +2498,6 @@ public class JBTabsImpl extends JComponent return myBorder; } - @NotNull - public JBTabs addTabMouseMotionListener(@NotNull MouseMotionListener listener) { - removeListeners(); - myTabMouseListeners.add(listener); - addListeners(); - return this; - } - @NotNull public JBTabs addTabMouseListener(@NotNull MouseListener listener) { removeListeners(); @@ -2594,14 +2515,6 @@ public class JBTabsImpl extends JComponent return false; } - @NotNull - public JBTabs removeTabMouseListener(@NotNull MouseListener listener) { - removeListeners(); - myTabMouseListeners.remove(listener); - addListeners(); - return this; - } - private void addListeners() { for (TabInfo eachInfo : myVisibleInfos) { final TabLabel label = myInfo2Label.get(eachInfo); @@ -2646,20 +2559,12 @@ public class JBTabsImpl extends JComponent return this; } - public JBTabs removeListener(@NotNull final TabsListener listener) { - myTabListeners.remove(listener); - return this; - } - @Override public JBTabs setSelectionChangeHandler(SelectionChangeHandler handler) { mySelectionChangeHandler = handler; return this; } - protected void onPopup(final TabInfo popupInfo) { - } - public void setFocused(final boolean focused) { if (myFocused == focused) return; @@ -2698,16 +2603,10 @@ public class JBTabsImpl extends JComponent return size == -1 ? 1 : size; } - public boolean isPaintFocus() { + private boolean isPaintFocus() { return myPaintFocus; } - @NotNull - public JBTabsPresentation setAdjustBorders(final boolean adjust) { - myAdjustBorders = adjust; - return this; - } - @NotNull public JBTabsPresentation setActiveTabFillIn(@Nullable final Color color) { if (!isChanged(myActiveTabFillIn, color)) return this; @@ -2732,7 +2631,7 @@ public class JBTabsImpl extends JComponent } @Nullable - public Color getActiveTabFillIn() { + protected Color getActiveTabFillIn() { return myActiveTabFillIn; } @@ -2915,7 +2814,6 @@ public class JBTabsImpl extends JComponent return !myHorizontalSide; } - @Override public boolean isSideComponentOnTabs() { return mySideComponentOnTabs; } @@ -2975,7 +2873,7 @@ public class JBTabsImpl extends JComponent relayout(true, false); } - public boolean isRequestFocusOnLastFocusedComponent() { + private boolean isRequestFocusOnLastFocusedComponent() { return myRequestFocusOnLastFocusedComponent; } @@ -3028,7 +2926,7 @@ public class JBTabsImpl extends JComponent } - public boolean isSelectionClick(final MouseEvent e, boolean canBeQuick) { + public static boolean isSelectionClick(final MouseEvent e, boolean canBeQuick) { if (e.getClickCount() == 1 || canBeQuick) { if (!e.isPopupTrigger()) { return e.getButton() == MouseEvent.BUTTON1 && !e.isControlDown() && !e.isAltDown() && !e.isMetaDown(); @@ -3120,25 +3018,16 @@ public class JBTabsImpl extends JComponent return this; } - void reallocate(TabInfo source, TabInfo target, boolean before) { + void reallocate(TabInfo source, TabInfo target) { if (source == target || source == null || target == null) return; final int targetIndex = myVisibleInfos.indexOf(target); - final int sourceIndex = myVisibleInfos.indexOf(source); - - boolean needsValidation = false; myVisibleInfos.remove(source); myVisibleInfos.add(targetIndex, source); - needsValidation = true; - //if (before && targetIndex < sourceIndex || !before && targetIndex > sourceIndex) { - //} - - if (needsValidation) { - invalidate(); - relayout(true, true); - } + invalidate(); + relayout(true, true); } boolean isHorizontalTabs() { @@ -3152,10 +3041,6 @@ public class JBTabsImpl extends JComponent } } - public boolean isUseBufferedPaint() { - return myUseBufferedPaint; - } - public void setUseBufferedPaint(boolean useBufferedPaint) { myUseBufferedPaint = useBufferedPaint; revalidate(); @@ -3280,13 +3165,11 @@ public class JBTabsImpl extends JComponent return myDropInfoIndex; } - @Override public boolean isEmptyVisible() { return myVisibleInfos.isEmpty(); } - @Override - public int getInterTabSpaceLength() { + public static int getInterTabSpaceLength() { return 1; } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/LayoutPassInfo.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/LayoutPassInfo.java index 7dd868299501..d9abba6bb983 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/LayoutPassInfo.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/LayoutPassInfo.java @@ -23,7 +23,7 @@ import java.util.List; public abstract class LayoutPassInfo { - public List myVisibleInfos; + public final List myVisibleInfos; protected LayoutPassInfo(List visibleInfos) { myVisibleInfos = visibleInfos; diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/ShapeTransform.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/ShapeTransform.java index 3c9c8c5e0557..b7f0777d47ba 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/ShapeTransform.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/ShapeTransform.java @@ -27,23 +27,18 @@ public abstract class ShapeTransform { private Rectangle myShapeRect; - protected int myXTransform; - protected int myYTransform; - private boolean mySwap; + private final int myXTransform; + private final int myYTransform; + private final boolean mySwap; - public ShapeTransform(Rectangle shapeRect, int xTransform, int yTransform, boolean swap) { + protected ShapeTransform(Rectangle shapeRect, int xTransform, int yTransform, boolean swap) { myShapeRect = shapeRect; myXTransform = xTransform; myYTransform = yTransform; mySwap = swap; } - public ShapeTransform(int XTranform, int YTranform) { - myXTransform = XTranform; - myYTransform = YTranform; - } - - public final Rectangle getShapeRect() { + protected final Rectangle getShapeRect() { return myShapeRect; } @@ -63,22 +58,10 @@ public abstract class ShapeTransform { return deltaY * myYTransform; } - public final T transformX1(T o1, T o2) { - return (mySwap ? myYTransform : myXTransform) == 1 ? o1: o2; - } - - public final T transformX2(T o1, T o2) { - return (mySwap ? myYTransform : myXTransform) == 1 ? o2: o1; - } - public final T transformY1(T o1, T o2) { return (mySwap ? myXTransform : myYTransform) == 1 ? o1: o2; } - public final T transformY2(T o1, T o2) { - return (mySwap ? myXTransform : myYTransform) == 1 ? o2: o1; - } - public abstract Insets transformInsets(Insets insets); public abstract Line2D.Float transformLine(int x1, int y1, int x2, int y2); @@ -136,7 +119,7 @@ public abstract class ShapeTransform { return reset(null); } - public final ShapeTransform reset(Rectangle shapeRec) { + protected final ShapeTransform reset(Rectangle shapeRec) { myPath = new GeneralPath(); if (shapeRec != null) { myShapeRect = shapeRec; diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java index ff7c60badee8..4fe4fd6dd449 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java @@ -65,7 +65,6 @@ public class TabLabel extends JPanel { private BufferedImage myInactiveStateImage; private Rectangle myLastPaintedInactiveImageBounds; - private boolean myStretchedByWidth; public TabLabel(JBTabsImpl tabs, final TabInfo info) { myTabs = tabs; @@ -87,7 +86,7 @@ public class TabLabel extends JPanel { addMouseListener(new MouseAdapter() { public void mousePressed(final MouseEvent e) { - if (myTabs.isSelectionClick(e, false) && myInfo.isEnabled()) { + if (JBTabsImpl.isSelectionClick(e, false) && myInfo.isEnabled()) { final TabInfo selectedInfo = myTabs.getSelectedInfo(); if (selectedInfo != myInfo) { myInfo.setPreviousSelection(selectedInfo); @@ -150,7 +149,7 @@ public class TabLabel extends JPanel { if (myTabs.getSelectedInfo() != myInfo) { myImage = null; doPaint(g); - } else if (!SystemInfo.isMac) { + } else if (!SystemInfo.isMac || SystemInfo.isJavaVersionAtLeast("1.7")) { myImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); final Graphics2D lg = myImage.createGraphics(); doPaint(lg); @@ -158,6 +157,16 @@ public class TabLabel extends JPanel { } } + @Override + public void setBounds(Rectangle r) { + super.setBounds(r); + } + + @Override + public void setBounds(int x, int y, int width, int height) { + super.setBounds(x, y, width, height); + } + public void paintImage(Graphics g) { final Rectangle b = getBounds(); if (myImage != null) { @@ -291,7 +300,6 @@ public class TabLabel extends JPanel { myTabs.myActivePopup.addPopupMenuListener(myTabs); myTabs.myActivePopup.show(e.getComponent(), e.getX(), e.getY()); - myTabs.onPopup(myTabs.myPopupInfo); } @@ -350,7 +358,7 @@ public class TabLabel extends JPanel { return hasIcons; } - private void setIcon(final Icon icon, int layer) { + private void setIcon(@Nullable final Icon icon, int layer) { LayeredIcon layeredIcon = getLayeredIcon(); layeredIcon.setIcon(icon, layer); if (hasIcons()) { @@ -366,14 +374,6 @@ public class TabLabel extends JPanel { return myIcon; } - public void setAttraction(boolean enabled) { - getLayeredIcon().setLayerEnabled(1, enabled); - } - - public boolean isAttractionEnabled() { - return getLayeredIcon().isLayerEnabled(1); - } - public TabInfo getInfo() { return myInfo; } @@ -418,10 +418,6 @@ public class TabLabel extends JPanel { myTabs.revalidateAndRepaint(false); } - @Override - protected void processMouseEvent(final MouseEvent e) { - super.processMouseEvent(e); - } private void removeOldActionPanel() { if (myActionPanel != null) { @@ -435,7 +431,7 @@ public class TabLabel extends JPanel { } - private void setAttractionIcon(Icon icon) { + private void setAttractionIcon(@Nullable Icon icon) { if (myIcon.getIcon(0) == null) { setIcon(null, 1); myOverlayedIcon = icon; diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLayout.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLayout.java index 5ced062c8543..321413c79f7c 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLayout.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLayout.java @@ -21,7 +21,6 @@ import org.jetbrains.annotations.NotNull; import java.awt.*; public abstract class TabLayout { - private Rectangle myHeaderRect; public ShapeTransform createShapeTransform(Dimension dimension) { return createShapeTransform(new Rectangle(0, 0, dimension.width, dimension.height)); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabsBorder.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabsBorder.java index 9cdfd6f61a9d..1d53f9a7b62f 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabsBorder.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabsBorder.java @@ -34,12 +34,13 @@ public class TabsBorder { public TabsBorder(JBTabsImpl tabs) { myTabs = tabs; - myBorderSize = new Insets(tabs.getBorder(-1), tabs.getBorder(-1), tabs.getBorder(-1), tabs.getBorder(-1)); - myTabBorderSize = tabs.getBorder(-1); + myBorderSize = new Insets(JBTabsImpl.getBorder(-1), JBTabsImpl.getBorder(-1), JBTabsImpl.getBorder(-1), JBTabsImpl.getBorder(-1)); + myTabBorderSize = JBTabsImpl.getBorder(-1); } public JBTabsPresentation setPaintBorder(int top, int left, int right, int bottom) { - final Insets newBorder = new Insets(myTabs.getBorder(top), myTabs.getBorder(left), myTabs.getBorder(bottom), myTabs.getBorder(right)); + final Insets newBorder = new Insets( + JBTabsImpl.getBorder(top), JBTabsImpl.getBorder(left), JBTabsImpl.getBorder(bottom), JBTabsImpl.getBorder(right)); if (newBorder.equals(myBorderSize)) return myTabs; myBorderSize = newBorder; @@ -52,7 +53,7 @@ public class TabsBorder { } public JBTabsPresentation setTabSidePaintBorder(int size) { - final int newSize = myTabs.getBorder(size); + final int newSize = JBTabsImpl.getBorder(size); if (myTabBorderSize == newSize) return myTabs; myTabBorderSize = newSize; diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/ScrollableSingleRowLayout.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/ScrollableSingleRowLayout.java index 2dd158059ec7..2f1bc02924e2 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/ScrollableSingleRowLayout.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/ScrollableSingleRowLayout.java @@ -65,7 +65,7 @@ public class ScrollableSingleRowLayout extends SingleRowLayout { } @Override - public void scrollSelectionInView(List visibleInfos) { + public void scrollSelectionInView() { myScrollSelectionInViewPending = true; } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java index c971bda0306a..8e8956e5bc65 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java @@ -29,15 +29,15 @@ import java.util.List; public class SingleRowLayout extends TabLayout { - JBTabsImpl myTabs; + final JBTabsImpl myTabs; public SingleRowPassInfo myLastSingRowLayout; - final SingleRowLayoutStrategy myTop; - final SingleRowLayoutStrategy myLeft; - final SingleRowLayoutStrategy myBottom; - final SingleRowLayoutStrategy myRight; + private final SingleRowLayoutStrategy myTop; + private final SingleRowLayoutStrategy myLeft; + private final SingleRowLayoutStrategy myBottom; + private final SingleRowLayoutStrategy myRight; - public MoreTabsIcon myMoreIcon = new MoreTabsIcon() { + public final MoreTabsIcon myMoreIcon = new MoreTabsIcon() { @Nullable protected Rectangle getIconRec() { return myLastSingRowLayout != null ? myLastSingRowLayout.moreRect : null; @@ -54,8 +54,8 @@ public class SingleRowLayout extends TabLayout { public JPopupMenu myMorePopup; - public GhostComponent myLeftGhost = new GhostComponent(RowDropPolicy.first, RowDropPolicy.first); - public GhostComponent myRightGhost = new GhostComponent(RowDropPolicy.last, RowDropPolicy.first); + public final GhostComponent myLeftGhost = new GhostComponent(RowDropPolicy.first, RowDropPolicy.first); + public final GhostComponent myRightGhost = new GhostComponent(RowDropPolicy.last, RowDropPolicy.first); private enum RowDropPolicy { first, last @@ -136,7 +136,7 @@ public class SingleRowLayout extends TabLayout { return 0; } - public void scrollSelectionInView(List visibleInfos) { + public void scrollSelectionInView() { } public LayoutPassInfo layoutSingleRow(List visibleInfos) { @@ -202,7 +202,7 @@ public class SingleRowLayout extends TabLayout { data.toFitLength = getStrategy().getToFitLength(data); if (myTabs.isGhostsAlwaysVisible()) { - data.toFitLength -= myTabs.getGhostTabLength() * 2 + (myTabs.getInterTabSpaceLength() * 2); + data.toFitLength -= JBTabsImpl.getGhostTabLength() * 2 + (JBTabsImpl.getInterTabSpaceLength() * 2); } } @@ -218,9 +218,9 @@ public class SingleRowLayout extends TabLayout { private void layoutLabelsAndGhosts(final SingleRowPassInfo data) { if (data.firstGhostVisible || myTabs.isGhostsAlwaysVisible()) { - data.firstGhost = getStrategy().getLayoutRect(data, data.position, myTabs.getGhostTabLength()); + data.firstGhost = getStrategy().getLayoutRect(data, data.position, JBTabsImpl.getGhostTabLength()); myTabs.layout(myLeftGhost, data.firstGhost); - data.position += getStrategy().getLengthIncrement(data.firstGhost.getSize()) + myTabs.getInterTabSpaceLength(); + data.position += getStrategy().getLengthIncrement(data.firstGhost.getSize()) + JBTabsImpl.getInterTabSpaceLength(); } int deltaToFit = 0; @@ -257,9 +257,9 @@ public class SingleRowLayout extends TabLayout { boolean continueLayout = applyTabLayout(data, label, length, deltaToFit); data.position = getStrategy().getMaxPosition(label.getBounds()); - data.position += myTabs.getInterTabSpaceLength(); + data.position += JBTabsImpl.getInterTabSpaceLength(); - totalLength = getStrategy().getMaxPosition(label.getBounds()) - positionStart + myTabs.getInterTabSpaceLength(); + totalLength = getStrategy().getMaxPosition(label.getBounds()) - positionStart + JBTabsImpl.getInterTabSpaceLength(); if (!continueLayout) { layoutStopped = true; } @@ -270,7 +270,7 @@ public class SingleRowLayout extends TabLayout { } if (data.lastGhostVisible || myTabs.isGhostsAlwaysVisible()) { - data.lastGhost = getStrategy().getLayoutRect(data, data.position, myTabs.getGhostTabLength()); + data.lastGhost = getStrategy().getLayoutRect(data, data.position, JBTabsImpl.getGhostTabLength()); myTabs.layout(myRightGhost, data.lastGhost); } } @@ -344,7 +344,7 @@ public class SingleRowLayout extends TabLayout { protected int getRequiredLength(TabInfo eachInfo) { return getStrategy().getLengthIncrement(myTabs.myInfo2Label.get(eachInfo).getPreferredSize()) - + (myTabs.isEditorTabs() ? myTabs.getInterTabSpaceLength() : 0); + + (myTabs.isEditorTabs() ? JBTabsImpl.getInterTabSpaceLength() : 0); } @@ -358,7 +358,7 @@ public class SingleRowLayout extends TabLayout { private GhostComponent(final RowDropPolicy before, final RowDropPolicy after) { addMouseListener(new MouseAdapter() { public void mousePressed(final MouseEvent e) { - if (myTabs.isSelectionClick(e, true) && myInfo != null) { + if (JBTabsImpl.isSelectionClick(e, true) && myInfo != null) { myRowDropPolicy = before; myTabs.select(myInfo, true).doWhenDone(new Runnable() { public void run() { @@ -395,13 +395,13 @@ public class SingleRowLayout extends TabLayout { if (!data.firstGhostVisible && isFirstSide) { data.firstGhostVisible = !myTabs.isEditorTabs(); if (!myTabs.isGhostsAlwaysVisible() && !myTabs.isEditorTabs()) { - data.toFitLength -= myTabs.getGhostTabLength(); + data.toFitLength -= JBTabsImpl.getGhostTabLength(); } } else if (!data.lastGhostVisible && !isFirstSide) { data.lastGhostVisible = !myTabs.isEditorTabs(); if (!myTabs.isGhostsAlwaysVisible() && !myTabs.isEditorTabs()) { - data.toFitLength -= myTabs.getGhostTabLength(); + data.toFitLength -= JBTabsImpl.getGhostTabLength(); } } } @@ -422,7 +422,7 @@ public class SingleRowLayout extends TabLayout { Rectangle firstBounds = first.getBounds(); Rectangle secondBounds = second.getBounds(); - boolean between = false; + final boolean between; boolean horizontal = getStrategy() instanceof SingleRowLayoutStrategy.Horizontal; if (horizontal) { diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayoutStrategy.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayoutStrategy.java index eef01235bbf2..b136b8e97ca5 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayoutStrategy.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayoutStrategy.java @@ -25,8 +25,8 @@ import java.awt.*; public abstract class SingleRowLayoutStrategy { private static final int MIN_TAB_WIDTH = 120; - SingleRowLayout myLayout; - JBTabsImpl myTabs; + final SingleRowLayout myLayout; + final JBTabsImpl myTabs; protected SingleRowLayoutStrategy(final SingleRowLayout layout) { myLayout = layout; @@ -59,8 +59,6 @@ public abstract class SingleRowLayoutStrategy { public abstract boolean isToCenterTextWhenStretched(); - public abstract Dimension getCompSizeDelta(SingleRowPassInfo data); - public abstract ShapeTransform createShapeTransform(Rectangle rectangle); public abstract boolean canBeStretched(); @@ -182,7 +180,7 @@ public abstract class SingleRowLayoutStrategy { else { x = data.position + (data.lastGhostVisible ? data.lastGhost.width : 0); } - return new Rectangle(x, data.insets.top + myTabs.getSelectionTabVShift(), + return new Rectangle(x, data.insets.top + JBTabsImpl.getSelectionTabVShift(), data.moreRectAxisSize - 1, myTabs.myHeaderFitSize.height - 1); } @@ -195,7 +193,7 @@ public abstract class SingleRowLayoutStrategy { final int vToolbarWidth = data.vToolbar != null ? data.vToolbar.getPreferredSize().width : 0; final int x = vToolbarWidth > 0 ? vToolbarWidth + 1 : 0; final int hToolbarHeight = !myTabs.isSideComponentOnTabs() && data.hToolbar != null ? data.hToolbar.getPreferredSize().height : 0; - final int y = data.compPosition + myTabs.myHeaderFitSize.height + (myTabs.isEditorTabs() ? 0 : 1) + + final int y = myTabs.myHeaderFitSize.height + (myTabs.isEditorTabs() ? 0 : 1) + (hToolbarHeight > 0 ? hToolbarHeight - 2 : 0); if (data.hToolbar != null) { @@ -218,11 +216,6 @@ public abstract class SingleRowLayoutStrategy { } } } - - public Dimension getCompSizeDelta(SingleRowPassInfo data) { - return new Dimension(); - } - } static class Bottom extends Horizontal { @@ -248,10 +241,6 @@ public abstract class SingleRowLayoutStrategy { data.moreRectAxisSize - 1, myTabs.myHeaderFitSize.height - 1); } - public Dimension getCompSizeDelta(SingleRowPassInfo data) { - return new Dimension(0, -(myTabs.myHeaderFitSize.height + 1)); - } - @Override public ShapeTransform createShapeTransform(Rectangle labelRec) { return new ShapeTransform.Bottom(labelRec); @@ -276,10 +265,6 @@ public abstract class SingleRowLayoutStrategy { return myLayout.myMoreIcon.myIcon.getIconHeight() + 4; } - public Dimension getCompSizeDelta(SingleRowPassInfo data) { - return new Dimension(); - } - @Override public boolean canBeStretched() { return false; @@ -351,7 +336,7 @@ public abstract class SingleRowLayoutStrategy { } public Rectangle getMoreRect(final SingleRowPassInfo data) { - return new Rectangle(data.insets.left + myTabs.getSelectionTabVShift(), + return new Rectangle(data.insets.left + JBTabsImpl.getSelectionTabVShift(), myTabs.getHeight() - data.insets.bottom - data.moreRectAxisSize - 1, myTabs.myHeaderFitSize.width - 1, data.moreRectAxisSize - 1); @@ -391,11 +376,6 @@ public abstract class SingleRowLayoutStrategy { myTabs.myHeaderFitSize.width - 1, data.moreRectAxisSize - 1); } - - @Override - public Dimension getCompSizeDelta(SingleRowPassInfo data) { - return new Dimension(-myTabs.myHeaderFitSize.width, 0); - } } -} \ No newline at end of file +} diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowPassInfo.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowPassInfo.java index 62c1b09172cb..25370ed9869d 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowPassInfo.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowPassInfo.java @@ -26,20 +26,18 @@ import java.util.List; public class SingleRowPassInfo extends LayoutPassInfo { final Dimension layoutSize; - int contentCount; + final int contentCount; int position; int requiredLength; int toFitLength; public final List toLayout; public final List toDrop; - int moreRectAxisSize; + final int moreRectAxisSize; public Rectangle moreRect; public JComponent hToolbar; public JComponent vToolbar; - public int compPosition; - public Rectangle firstGhost; public boolean firstGhostVisible; @@ -48,17 +46,16 @@ public class SingleRowPassInfo extends LayoutPassInfo { public Insets insets; - private final JBTabsImpl myTabs; public JComponent comp; public Rectangle tabRectangle; - int scrollOffset; + final int scrollOffset; public SingleRowPassInfo(SingleRowLayout layout, List visibleInfos) { super(visibleInfos); - myTabs = layout.myTabs; - layoutSize = layout.myTabs.getSize(); - contentCount = myTabs.getTabCount(); + JBTabsImpl tabs = layout.myTabs; + layoutSize = tabs.getSize(); + contentCount = tabs.getTabCount(); toLayout = new ArrayList(); toDrop = new ArrayList(); moreRectAxisSize = layout.getStrategy().getMoreRectAxisSize(); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java index f2cdf9b374ef..1326531e2465 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java @@ -56,8 +56,8 @@ public class TableLayout extends TabLayout { eachX = data.toFitRec.x; } myTabs.layout(eachLabel, eachX, 0, size.width, 1); - eachX += size.width + myTabs.getInterTabSpaceLength(); - data.requiredWidth += size.width + myTabs.getInterTabSpaceLength(); + eachX += size.width + JBTabsImpl.getInterTabSpaceLength(); + data.requiredWidth += size.width + JBTabsImpl.getInterTabSpaceLength(); } int selectedRow = -1; @@ -84,7 +84,7 @@ public class TableLayout extends TabLayout { if (myTabs.getSelectedInfo() == eachInfo) { selectedRow = eachRow; } - eachX += size.width + myTabs.getInterTabSpaceLength(); + eachX += size.width + JBTabsImpl.getInterTabSpaceLength(); } else { eachTableRow = new TableRow(data); @@ -161,9 +161,9 @@ public class TableLayout extends TabLayout { label.setAlignmentToCenter(deltaToFit > 0); boolean lastCell = i == eachRow.myColumns.size() - 1; - eachX += width + (lastCell ? 0 : myTabs.getInterTabSpaceLength()); + eachX += width + (lastCell ? 0 : JBTabsImpl.getInterTabSpaceLength()); } - eachY += myTabs.myHeaderFitSize.height - 1 + myTabs.getInterTabSpaceLength() - (row < data.table.size() - 1 ? tabUnderlineFix : 0); + eachY += myTabs.myHeaderFitSize.height - 1 + JBTabsImpl.getInterTabSpaceLength() - (row < data.table.size() - 1 ? tabUnderlineFix : 0); row++; } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TablePassInfo.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TablePassInfo.java index d29ced04e289..33623bbd7278 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TablePassInfo.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TablePassInfo.java @@ -27,15 +27,15 @@ import java.util.List; import java.util.Map; public class TablePassInfo extends LayoutPassInfo { - List table = new ArrayList(); + final List table = new ArrayList(); public Rectangle toFitRec; - Map myInfo2Row = new HashMap(); + final Map myInfo2Row = new HashMap(); int requiredWidth; int requiredRows; int rowToFitMaxX; - JBTabsImpl myTabs; + final JBTabsImpl myTabs; TablePassInfo(final JBTabsImpl tabs, List visibleInfos) { super(visibleInfos); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableRow.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableRow.java index 5cbab8c37389..7c40ed1cf204 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableRow.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableRow.java @@ -17,13 +17,13 @@ package com.intellij.ui.tabs.impl.table; import com.intellij.ui.tabs.TabInfo; -import java.util.List; import java.util.ArrayList; +import java.util.List; class TableRow { - TablePassInfo myData; - List myColumns = new ArrayList(); + private final TablePassInfo myData; + final List myColumns = new ArrayList(); int width; public TableRow(final TablePassInfo data) { From 72f42620c1cef187f0c803920320ec8bae558d9d Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Sat, 12 May 2012 16:04:15 +0400 Subject: [PATCH 35/61] unused state --- .../com/intellij/ui/tabs/impl/DragHelper.java | 2 +- .../com/intellij/ui/tabs/impl/JBTabsImpl.java | 134 ++++++++---------- .../com/intellij/ui/tabs/impl/TabsBorder.java | 2 +- 3 files changed, 64 insertions(+), 74 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java index fda9ee1622d0..41b4fa0b798a 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java @@ -238,7 +238,7 @@ class DragHelper extends MouseDragHelper { if (!willDragOutStart) { myTabs.fireTabsMoved(); } - myTabs.relayout(true, false); + myTabs.relayout(false); myTabs.revalidate(); } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java index f0623fa5895c..c8ec1ea8d08f 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java @@ -111,8 +111,6 @@ public class JBTabsImpl extends JComponent private LayoutPassInfo myLastLayoutPass; private TabInfo myLastPaintedSelection; - public boolean myForcedRelayout; - private UiDecorator myUiDecorator; static final UiDecorator ourDefaultDecorator = new DefaultDecorator(); @@ -387,7 +385,7 @@ public class JBTabsImpl extends JComponent } if (needsUpdate) { - relayout(true, false); + relayout(false); } } @@ -675,7 +673,7 @@ public class JBTabsImpl extends JComponent adjust(info); - updateAll(false, false); + updateAll(false); if (info.isHidden()) { updateHiding(); @@ -728,9 +726,9 @@ public class JBTabsImpl extends JComponent return this; } - private void updateAll(final boolean forcedRelayout, final boolean now) { + private void updateAll(final boolean now) { mySelectedInfo = getSelectedInfo(); - updateContainer(forcedRelayout, now); + updateContainer(now); removeDeferred(); updateListeners(); updateTabActions(false); @@ -801,7 +799,7 @@ public class JBTabsImpl extends JComponent fireBeforeSelectionChanged(oldInfo, newInfo); - updateContainer(false, true); + updateContainer(true); fireSelectionChanged(oldInfo, newInfo); @@ -944,10 +942,10 @@ public class JBTabsImpl extends JComponent final TabInfo tabInfo = (TabInfo)evt.getSource(); if (TabInfo.ACTION_GROUP.equals(evt.getPropertyName())) { updateSideComponent(tabInfo); - relayout(false, false); + relayout(false); } else if (TabInfo.COMPONENT.equals(evt.getPropertyName())) { - relayout(true, false); + relayout(false); } else if (TabInfo.TEXT.equals(evt.getPropertyName())) { updateText(tabInfo); @@ -964,11 +962,11 @@ public class JBTabsImpl extends JComponent } else if (TabInfo.TAB_ACTION_GROUP.equals(evt.getPropertyName())) { updateTabActions(tabInfo); - relayout(false, false); + relayout(false); } else if (TabInfo.HIDDEN.equals(evt.getPropertyName())) { updateHiding(); - relayout(false, false); + relayout(false); } else if (TabInfo.ENABLED.equals(evt.getPropertyName())) { updateEnabling(); @@ -1021,7 +1019,7 @@ public class JBTabsImpl extends JComponent if (mySelectedInfo != null && myHiddenInfos.containsKey(mySelectedInfo)) { mySelectedInfo = getToSelectOnRemoveOf(mySelectedInfo); } - updateAll(true, false); + updateAll(false); } } @@ -1345,51 +1343,46 @@ public class JBTabsImpl extends JComponent public void doLayout() { - try { - myHeaderFitSize = computeHeaderFitSize(); + myHeaderFitSize = computeHeaderFitSize(); - final Collection labels = myInfo2Label.values(); - for (TabLabel each : labels) { - each.setTabActionsAutoHide(myTabLabelActionsAutoHide); - } - - - List visible = new ArrayList(); - visible.addAll(myVisibleInfos); - - if (myDropInfo != null && !visible.contains(myDropInfo) && myShowDropLocation) { - if (getDropInfoIndex() >= 0 && getDropInfoIndex() < visible.size()) { - visible.add(getDropInfoIndex(), myDropInfo); - } else { - visible.add(myDropInfo); - } - } - - if (isSingleRow()) { - myLastLayoutPass = mySingleRowLayout.layoutSingleRow(visible); - myTableLayout.myLastTableLayout = null; - } - else { - myLastLayoutPass = myTableLayout.layoutTable(visible); - mySingleRowLayout.myLastSingRowLayout = null; - } - - if (isStealthModeEffective() && !isHideTabs()) { - final TabLabel label = getSelectedLabel(); - final Rectangle bounds = label.getBounds(); - final Insets insets = getLayoutInsets(); - layout(label, insets.left, bounds.y, getWidth() - insets.right - insets.left, bounds.height); - } - - - moveDraggedTabLabel(); - - myTabActionsAutoHideListener.processMouseOver(); + final Collection labels = myInfo2Label.values(); + for (TabLabel each : labels) { + each.setTabActionsAutoHide(myTabLabelActionsAutoHide); } - finally { - myForcedRelayout = false; + + + List visible = new ArrayList(); + visible.addAll(myVisibleInfos); + + if (myDropInfo != null && !visible.contains(myDropInfo) && myShowDropLocation) { + if (getDropInfoIndex() >= 0 && getDropInfoIndex() < visible.size()) { + visible.add(getDropInfoIndex(), myDropInfo); + } else { + visible.add(myDropInfo); + } } + if (isSingleRow()) { + myLastLayoutPass = mySingleRowLayout.layoutSingleRow(visible); + myTableLayout.myLastTableLayout = null; + } + else { + myLastLayoutPass = myTableLayout.layoutTable(visible); + mySingleRowLayout.myLastSingRowLayout = null; + } + + if (isStealthModeEffective() && !isHideTabs()) { + final TabLabel label = getSelectedLabel(); + final Rectangle bounds = label.getBounds(); + final Insets insets = getLayoutInsets(); + layout(label, insets.left, bounds.y, getWidth() - insets.right - insets.left, bounds.height); + } + + + moveDraggedTabLabel(); + + myTabActionsAutoHideListener.processMouseOver(); + applyResetComponents(); } @@ -2377,7 +2370,7 @@ public class JBTabsImpl extends JComponent myInfo2Toolbar.remove(info); resetTabsCache(); - updateAll(false, false); + updateAll(false); // avoid leaks myLastPaintedSelection = null; @@ -2442,7 +2435,7 @@ public class JBTabsImpl extends JComponent final Dimension myToolbar = new Dimension(); } - private void updateContainer(boolean forced, final boolean layoutNow) { + private void updateContainer(final boolean layoutNow) { for (TabInfo each : myVisibleInfos) { final JComponent eachComponent = each.getComponent(); if (getSelectedInfo() == each && getSelectedInfo() != null) { @@ -2469,7 +2462,7 @@ public class JBTabsImpl extends JComponent } mySingleRowLayout.scrollSelectionInView(); - relayout(forced, layoutNow); + relayout(layoutNow); } protected void addImpl(final Component comp, final Object constraints, final int index) { @@ -2487,10 +2480,7 @@ public class JBTabsImpl extends JComponent return c.getRootPane() != null; } - void relayout(boolean forced, final boolean layoutNow) { - if (!myForcedRelayout) { - myForcedRelayout = forced; - } + void relayout(final boolean layoutNow) { revalidateAndRepaint(layoutNow); } @@ -2588,7 +2578,7 @@ public class JBTabsImpl extends JComponent myHideTabs = hideTabs; - relayout(true, false); + relayout(false); } public JBTabsPresentation setPaintBorder(int top, int left, int right, int bottom) { @@ -2755,7 +2745,7 @@ public class JBTabsImpl extends JComponent public JBTabsPresentation setStealthTabMode(final boolean stealthTabMode) { myStealthTabMode = stealthTabMode; - relayout(true, false); + relayout(false); return this; } @@ -2772,7 +2762,7 @@ public class JBTabsImpl extends JComponent } - relayout(true, false); + relayout(false); return this; } @@ -2781,7 +2771,7 @@ public class JBTabsImpl extends JComponent public JBTabsPresentation setSideComponentOnTabs(boolean onTabs) { mySideComponentOnTabs = onTabs; - relayout(true, false); + relayout(false); return this; } @@ -2789,7 +2779,7 @@ public class JBTabsImpl extends JComponent public JBTabsPresentation setSingleRow(boolean singleRow) { myLayout = singleRow ? mySingleRowLayout : myTableLayout; - relayout(true, false); + relayout(false); return this; } @@ -2797,7 +2787,7 @@ public class JBTabsImpl extends JComponent public JBTabsPresentation setGhostsAlwaysVisible(final boolean visible) { myGhostsAlwaysVisible = visible; - relayout(true, false); + relayout(false); return this; } @@ -2858,7 +2848,7 @@ public class JBTabsImpl extends JComponent adjust(each); } - relayout(true, false); + relayout(false); } private void adjust(final TabInfo each) { @@ -2870,7 +2860,7 @@ public class JBTabsImpl extends JComponent public void sortTabs(Comparator comparator) { Collections.sort(myVisibleInfos, comparator); - relayout(true, false); + relayout(false); } private boolean isRequestFocusOnLastFocusedComponent() { @@ -2992,7 +2982,7 @@ public class JBTabsImpl extends JComponent @NotNull public JBTabsPresentation setTabsPosition(final JBTabsPosition position) { myPosition = position; - relayout(true, false); + relayout(false); return this; } @@ -3027,7 +3017,7 @@ public class JBTabsImpl extends JComponent myVisibleInfos.add(targetIndex, source); invalidate(); - relayout(true, true); + relayout(true); } boolean isHorizontalTabs() { @@ -3147,7 +3137,7 @@ public class JBTabsImpl extends JComponent label.paintOffscreen(g); g.dispose(); - relayout(true, false); + relayout(false); return img; } @@ -3157,7 +3147,7 @@ public class JBTabsImpl extends JComponent int index = myLayout.getDropIndexFor(point.getPoint(this)); if (index != getDropInfoIndex()) { setDropInfoIndex(index); - relayout(true, false); + relayout(false); } } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabsBorder.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabsBorder.java index 1d53f9a7b62f..45cdc869bed2 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabsBorder.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabsBorder.java @@ -47,7 +47,7 @@ public class TabsBorder { myEffectiveBorder = null; - myTabs.relayout(true, false); + myTabs.relayout(false); return myTabs; } From 937cf22ce129d9a2dce2c33a79b8d2cf356775b1 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Sat, 12 May 2012 16:28:43 +0400 Subject: [PATCH 36/61] revert --- .../com/intellij/ui/tabs/impl/DragHelper.java | 2 +- .../com/intellij/ui/tabs/impl/JBTabsImpl.java | 132 ++++++++++-------- .../com/intellij/ui/tabs/impl/TabsBorder.java | 2 +- 3 files changed, 73 insertions(+), 63 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java index 41b4fa0b798a..fda9ee1622d0 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java @@ -238,7 +238,7 @@ class DragHelper extends MouseDragHelper { if (!willDragOutStart) { myTabs.fireTabsMoved(); } - myTabs.relayout(false); + myTabs.relayout(true, false); myTabs.revalidate(); } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java index c8ec1ea8d08f..f0623fa5895c 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java @@ -111,6 +111,8 @@ public class JBTabsImpl extends JComponent private LayoutPassInfo myLastLayoutPass; private TabInfo myLastPaintedSelection; + public boolean myForcedRelayout; + private UiDecorator myUiDecorator; static final UiDecorator ourDefaultDecorator = new DefaultDecorator(); @@ -385,7 +387,7 @@ public class JBTabsImpl extends JComponent } if (needsUpdate) { - relayout(false); + relayout(true, false); } } @@ -673,7 +675,7 @@ public class JBTabsImpl extends JComponent adjust(info); - updateAll(false); + updateAll(false, false); if (info.isHidden()) { updateHiding(); @@ -726,9 +728,9 @@ public class JBTabsImpl extends JComponent return this; } - private void updateAll(final boolean now) { + private void updateAll(final boolean forcedRelayout, final boolean now) { mySelectedInfo = getSelectedInfo(); - updateContainer(now); + updateContainer(forcedRelayout, now); removeDeferred(); updateListeners(); updateTabActions(false); @@ -799,7 +801,7 @@ public class JBTabsImpl extends JComponent fireBeforeSelectionChanged(oldInfo, newInfo); - updateContainer(true); + updateContainer(false, true); fireSelectionChanged(oldInfo, newInfo); @@ -942,10 +944,10 @@ public class JBTabsImpl extends JComponent final TabInfo tabInfo = (TabInfo)evt.getSource(); if (TabInfo.ACTION_GROUP.equals(evt.getPropertyName())) { updateSideComponent(tabInfo); - relayout(false); + relayout(false, false); } else if (TabInfo.COMPONENT.equals(evt.getPropertyName())) { - relayout(false); + relayout(true, false); } else if (TabInfo.TEXT.equals(evt.getPropertyName())) { updateText(tabInfo); @@ -962,11 +964,11 @@ public class JBTabsImpl extends JComponent } else if (TabInfo.TAB_ACTION_GROUP.equals(evt.getPropertyName())) { updateTabActions(tabInfo); - relayout(false); + relayout(false, false); } else if (TabInfo.HIDDEN.equals(evt.getPropertyName())) { updateHiding(); - relayout(false); + relayout(false, false); } else if (TabInfo.ENABLED.equals(evt.getPropertyName())) { updateEnabling(); @@ -1019,7 +1021,7 @@ public class JBTabsImpl extends JComponent if (mySelectedInfo != null && myHiddenInfos.containsKey(mySelectedInfo)) { mySelectedInfo = getToSelectOnRemoveOf(mySelectedInfo); } - updateAll(false); + updateAll(true, false); } } @@ -1343,45 +1345,50 @@ public class JBTabsImpl extends JComponent public void doLayout() { - myHeaderFitSize = computeHeaderFitSize(); + try { + myHeaderFitSize = computeHeaderFitSize(); - final Collection labels = myInfo2Label.values(); - for (TabLabel each : labels) { - each.setTabActionsAutoHide(myTabLabelActionsAutoHide); - } - - - List visible = new ArrayList(); - visible.addAll(myVisibleInfos); - - if (myDropInfo != null && !visible.contains(myDropInfo) && myShowDropLocation) { - if (getDropInfoIndex() >= 0 && getDropInfoIndex() < visible.size()) { - visible.add(getDropInfoIndex(), myDropInfo); - } else { - visible.add(myDropInfo); + final Collection labels = myInfo2Label.values(); + for (TabLabel each : labels) { + each.setTabActionsAutoHide(myTabLabelActionsAutoHide); } + + + List visible = new ArrayList(); + visible.addAll(myVisibleInfos); + + if (myDropInfo != null && !visible.contains(myDropInfo) && myShowDropLocation) { + if (getDropInfoIndex() >= 0 && getDropInfoIndex() < visible.size()) { + visible.add(getDropInfoIndex(), myDropInfo); + } else { + visible.add(myDropInfo); + } + } + + if (isSingleRow()) { + myLastLayoutPass = mySingleRowLayout.layoutSingleRow(visible); + myTableLayout.myLastTableLayout = null; + } + else { + myLastLayoutPass = myTableLayout.layoutTable(visible); + mySingleRowLayout.myLastSingRowLayout = null; + } + + if (isStealthModeEffective() && !isHideTabs()) { + final TabLabel label = getSelectedLabel(); + final Rectangle bounds = label.getBounds(); + final Insets insets = getLayoutInsets(); + layout(label, insets.left, bounds.y, getWidth() - insets.right - insets.left, bounds.height); + } + + + moveDraggedTabLabel(); + + myTabActionsAutoHideListener.processMouseOver(); } - - if (isSingleRow()) { - myLastLayoutPass = mySingleRowLayout.layoutSingleRow(visible); - myTableLayout.myLastTableLayout = null; + finally { + myForcedRelayout = false; } - else { - myLastLayoutPass = myTableLayout.layoutTable(visible); - mySingleRowLayout.myLastSingRowLayout = null; - } - - if (isStealthModeEffective() && !isHideTabs()) { - final TabLabel label = getSelectedLabel(); - final Rectangle bounds = label.getBounds(); - final Insets insets = getLayoutInsets(); - layout(label, insets.left, bounds.y, getWidth() - insets.right - insets.left, bounds.height); - } - - - moveDraggedTabLabel(); - - myTabActionsAutoHideListener.processMouseOver(); applyResetComponents(); } @@ -2370,7 +2377,7 @@ public class JBTabsImpl extends JComponent myInfo2Toolbar.remove(info); resetTabsCache(); - updateAll(false); + updateAll(false, false); // avoid leaks myLastPaintedSelection = null; @@ -2435,7 +2442,7 @@ public class JBTabsImpl extends JComponent final Dimension myToolbar = new Dimension(); } - private void updateContainer(final boolean layoutNow) { + private void updateContainer(boolean forced, final boolean layoutNow) { for (TabInfo each : myVisibleInfos) { final JComponent eachComponent = each.getComponent(); if (getSelectedInfo() == each && getSelectedInfo() != null) { @@ -2462,7 +2469,7 @@ public class JBTabsImpl extends JComponent } mySingleRowLayout.scrollSelectionInView(); - relayout(layoutNow); + relayout(forced, layoutNow); } protected void addImpl(final Component comp, final Object constraints, final int index) { @@ -2480,7 +2487,10 @@ public class JBTabsImpl extends JComponent return c.getRootPane() != null; } - void relayout(final boolean layoutNow) { + void relayout(boolean forced, final boolean layoutNow) { + if (!myForcedRelayout) { + myForcedRelayout = forced; + } revalidateAndRepaint(layoutNow); } @@ -2578,7 +2588,7 @@ public class JBTabsImpl extends JComponent myHideTabs = hideTabs; - relayout(false); + relayout(true, false); } public JBTabsPresentation setPaintBorder(int top, int left, int right, int bottom) { @@ -2745,7 +2755,7 @@ public class JBTabsImpl extends JComponent public JBTabsPresentation setStealthTabMode(final boolean stealthTabMode) { myStealthTabMode = stealthTabMode; - relayout(false); + relayout(true, false); return this; } @@ -2762,7 +2772,7 @@ public class JBTabsImpl extends JComponent } - relayout(false); + relayout(true, false); return this; } @@ -2771,7 +2781,7 @@ public class JBTabsImpl extends JComponent public JBTabsPresentation setSideComponentOnTabs(boolean onTabs) { mySideComponentOnTabs = onTabs; - relayout(false); + relayout(true, false); return this; } @@ -2779,7 +2789,7 @@ public class JBTabsImpl extends JComponent public JBTabsPresentation setSingleRow(boolean singleRow) { myLayout = singleRow ? mySingleRowLayout : myTableLayout; - relayout(false); + relayout(true, false); return this; } @@ -2787,7 +2797,7 @@ public class JBTabsImpl extends JComponent public JBTabsPresentation setGhostsAlwaysVisible(final boolean visible) { myGhostsAlwaysVisible = visible; - relayout(false); + relayout(true, false); return this; } @@ -2848,7 +2858,7 @@ public class JBTabsImpl extends JComponent adjust(each); } - relayout(false); + relayout(true, false); } private void adjust(final TabInfo each) { @@ -2860,7 +2870,7 @@ public class JBTabsImpl extends JComponent public void sortTabs(Comparator comparator) { Collections.sort(myVisibleInfos, comparator); - relayout(false); + relayout(true, false); } private boolean isRequestFocusOnLastFocusedComponent() { @@ -2982,7 +2992,7 @@ public class JBTabsImpl extends JComponent @NotNull public JBTabsPresentation setTabsPosition(final JBTabsPosition position) { myPosition = position; - relayout(false); + relayout(true, false); return this; } @@ -3017,7 +3027,7 @@ public class JBTabsImpl extends JComponent myVisibleInfos.add(targetIndex, source); invalidate(); - relayout(true); + relayout(true, true); } boolean isHorizontalTabs() { @@ -3137,7 +3147,7 @@ public class JBTabsImpl extends JComponent label.paintOffscreen(g); g.dispose(); - relayout(false); + relayout(true, false); return img; } @@ -3147,7 +3157,7 @@ public class JBTabsImpl extends JComponent int index = myLayout.getDropIndexFor(point.getPoint(this)); if (index != getDropInfoIndex()) { setDropInfoIndex(index); - relayout(false); + relayout(true, false); } } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabsBorder.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabsBorder.java index 45cdc869bed2..1d53f9a7b62f 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabsBorder.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabsBorder.java @@ -47,7 +47,7 @@ public class TabsBorder { myEffectiveBorder = null; - myTabs.relayout(false); + myTabs.relayout(true, false); return myTabs; } From 2e1a6abb064e3fe97b019e733c0cde2faf6266bf Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Tue, 15 May 2012 19:22:30 +0400 Subject: [PATCH 37/61] In JBTabsImpl.paintChildren() course, selected tab child is paint separately, with JComponent's paintChildren unaware of this, and not setting ANCESTOR_USING_BUFFER flag. Thus, label component is drawn to the buffer without being aware of it. This causes coordinate mapping problems. The workaround is to make sure none of the components, that TabLabel consists of uses double buffering. --- .../ui/components/panels/NonOpaquePanel.java | 1 + .../com/intellij/ui/tabs/impl/TabLabel.java | 30 +++++++------------ .../src/com/intellij/util/ui/Centerizer.java | 3 +- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/components/panels/NonOpaquePanel.java b/platform/platform-api/src/com/intellij/ui/components/panels/NonOpaquePanel.java index a0f0f82019ef..442f94595cd1 100644 --- a/platform/platform-api/src/com/intellij/ui/components/panels/NonOpaquePanel.java +++ b/platform/platform-api/src/com/intellij/ui/components/panels/NonOpaquePanel.java @@ -53,6 +53,7 @@ public class NonOpaquePanel extends Wrapper { @Override public void setOpaque(boolean isOpaque) { super.setOpaque(isOpaque); + setDoubleBuffered(false); if (!isOpaque && UIUtil.isUnderNimbusLookAndFeel()) { if (UIUtil.isUnderNimbusLookAndFeel()) { diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java index 4fe4fd6dd449..0c512c632510 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java @@ -58,15 +58,15 @@ public class TabLabel extends JPanel { protected ActionPanel myActionPanel; private boolean myCentered; - private final Wrapper myLabelPlaceholder = new Wrapper(); + private final Wrapper myLabelPlaceholder = new Wrapper(false); private final JBTabsImpl myTabs; - private BufferedImage myImage; - private BufferedImage myInactiveStateImage; private Rectangle myLastPaintedInactiveImageBounds; public TabLabel(JBTabsImpl tabs, final TabInfo info) { + super(false); + myTabs = tabs; myInfo = info; myLabel.setOpaque(false); @@ -147,13 +147,7 @@ public class TabLabel extends JPanel { if (myTabs.isDropTarget(myInfo)) return; if (myTabs.getSelectedInfo() != myInfo) { - myImage = null; doPaint(g); - } else if (!SystemInfo.isMac || SystemInfo.isJavaVersionAtLeast("1.7")) { - myImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); - final Graphics2D lg = myImage.createGraphics(); - doPaint(lg); - lg.dispose(); } } @@ -169,17 +163,13 @@ public class TabLabel extends JPanel { public void paintImage(Graphics g) { final Rectangle b = getBounds(); - if (myImage != null) { - g.drawImage(myImage, b.x, b.y, getWidth(), getHeight(), null); - } else { - final Graphics lG = g.create(b.x, b.y, b.width, b.height); - try { - lG.setColor(Color.red); - doPaint(lG); - } - finally { - lG.dispose(); - } + final Graphics lG = g.create(b.x, b.y, b.width, b.height); + try { + lG.setColor(Color.red); + doPaint(lG); + } + finally { + lG.dispose(); } } diff --git a/platform/util/src/com/intellij/util/ui/Centerizer.java b/platform/util/src/com/intellij/util/ui/Centerizer.java index 9b747d9df2cb..4f42ca3352de 100644 --- a/platform/util/src/com/intellij/util/ui/Centerizer.java +++ b/platform/util/src/com/intellij/util/ui/Centerizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import java.awt.*; public class Centerizer extends JPanel { public Centerizer(@NotNull JComponent comp) { + super(false); setOpaque(false); setBorder(null); From ab87ff04f6d3bdfaf316dc5c67332d0071193848 Mon Sep 17 00:00:00 2001 From: Dmitry Boulytchev Date: Tue, 15 May 2012 20:06:52 +0400 Subject: [PATCH 38/61] Cleaning up after storage dump implementation (compile server). --- .../jps/incremental/IncProjectBuilder.java | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java index dc99c6ca0217..0d84546cf4f3 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java @@ -221,31 +221,6 @@ public class IncProjectBuilder { context.processMessage(new ProgressMessage("Running 'after' tasks")); runTasks(context, myBuilderRegistry.getAfterTasks()); - final JavaBuilderLogger logger = context.getLoggingManager().getJavaBuilderLogger(); - - if (logger.isEnabled()) { - final File flag = new File(Utils.getSystemRoot() + File.separator + "dumpSnapshot"); - - if (flag.exists()) { - final Mappings mappings = myProjectDescriptor.dataManager.getMappings(); - final String fileName = - Utils.getSystemRoot() + File.separator + "snapshot-" + new SimpleDateFormat("dd-MM-yy(hh:mm:ss)").format(new Date()) + ".log"; - - try { - final PrintStream stream = new PrintStream(fileName); - - stream.println("Mappings:"); - mappings.toStream(stream); - stream.println("End Of Mappings"); - - stream.close(); - } - catch (FileNotFoundException e) { - e.printStackTrace(); - } - } - } - context.processMessage(new ProgressMessage("Finished, saving caches...")); } From f7404ed3ba1ddd2d61efef5144ebb1db78b632c8 Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Tue, 15 May 2012 20:49:49 +0400 Subject: [PATCH 39/61] RelativeLayout --- .../layout/RelativeLayoutOperation.java | 80 +++++---- .../RelativeLayoutResizeOperation.java | 160 +++++++++++++++++- .../layout/actions/ResizeOperation.java | 33 +--- .../layout/relative/AutoResizeSnapPoint.java | 105 ++++++++++++ .../layout/relative/BaselineSnapPoint.java | 2 +- .../layout/relative/ComponentSnapPoint.java | 2 +- .../layout/relative/ContainerSnapPoint.java | 6 +- .../relative/ResizeComponentSnapPoint.java | 62 +++++++ .../relative/ResizeContainerSnapPoint.java | 73 ++++++++ .../layout/relative/WrapSizeSnapPoint.java | 76 +++++++++ .../designer/model/RadViewComponent.java | 57 ++++++- 11 files changed, 572 insertions(+), 84 deletions(-) create mode 100644 plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/AutoResizeSnapPoint.java create mode 100644 plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ResizeComponentSnapPoint.java create mode 100644 plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ResizeContainerSnapPoint.java create mode 100644 plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/WrapSizeSnapPoint.java diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/RelativeLayoutOperation.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/RelativeLayoutOperation.java index 24e70befb986..4ec20a0066bf 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/RelativeLayoutOperation.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/RelativeLayoutOperation.java @@ -134,42 +134,46 @@ public class RelativeLayoutOperation extends AbstractEditOperation { mySnapFeedback.repaint(); myBoundsFeedback.setLocation(myBounds.x, myBounds.y); - configureTextFeedback(); + configureTextFeedback(myHorizontalTextFeedback, myVerticalTextFeedback, myHorizontalPoint, myVerticalPoint, myContainerBounds); } - private void configureTextFeedback() { - myHorizontalTextFeedback.clear(); - myVerticalTextFeedback.clear(); + public static void configureTextFeedback(TextFeedback horizontalTextFeedback, + TextFeedback verticalTextFeedback, + SnapPoint horizontalPoint, + SnapPoint verticalPoint, + Rectangle containerBounds) { + horizontalTextFeedback.clear(); + verticalTextFeedback.clear(); - myHorizontalTextFeedback.setVisible(myHorizontalPoint != null); - if (myHorizontalPoint != null) { - myHorizontalPoint.addTextInfo(myHorizontalTextFeedback); + horizontalTextFeedback.setVisible(horizontalPoint != null); + if (horizontalPoint != null) { + horizontalPoint.addTextInfo(horizontalTextFeedback); - if (myVerticalPoint == null) { - myHorizontalTextFeedback.centerTop(myContainerBounds); + if (verticalPoint == null) { + horizontalTextFeedback.centerTop(containerBounds); } } - myVerticalTextFeedback.setVisible(myVerticalPoint != null); - if (myVerticalPoint != null) { - myVerticalPoint.addTextInfo(myVerticalTextFeedback); + verticalTextFeedback.setVisible(verticalPoint != null); + if (verticalPoint != null) { + verticalPoint.addTextInfo(verticalTextFeedback); - if (myHorizontalPoint == null) { - myVerticalTextFeedback.centerTop(myContainerBounds); + if (horizontalPoint == null) { + verticalTextFeedback.centerTop(containerBounds); } } - if (myHorizontalPoint != null && myVerticalPoint != null) { - Dimension size1 = myHorizontalTextFeedback.getPreferredSize(); - Dimension size2 = myVerticalTextFeedback.getPreferredSize(); + if (horizontalPoint != null && verticalPoint != null) { + Dimension size1 = horizontalTextFeedback.getPreferredSize(); + Dimension size2 = verticalTextFeedback.getPreferredSize(); int width = Math.max(size1.width, size2.width); int height = size1.height + size2.height; - int x = myContainerBounds.x + myContainerBounds.width / 2 - width / 2; - int y = myContainerBounds.y - height - 10; + int x = containerBounds.x + containerBounds.width / 2 - width / 2; + int y = containerBounds.y - height - 10; - myHorizontalTextFeedback.setBounds(x, y, width, size1.height); - myVerticalTextFeedback.setBounds(x, y + size1.height, width, size2.height); + horizontalTextFeedback.setBounds(x, y, width, size1.height); + verticalTextFeedback.setBounds(x, y + size1.height, width, size2.height); } } @@ -191,24 +195,10 @@ public class RelativeLayoutOperation extends AbstractEditOperation { } private void createPoints() { - List children = new ArrayList(myContainer.getChildren()); - children.removeAll(myComponents); - - Map relativeInfos = myContainer.getClientProperty(RelativeInfo.KEY); - for (RadComponent editComponent : myComponents) { - for (Iterator I = children.iterator(); I.hasNext(); ) { - RadComponent child = I.next(); - RelativeInfo info = relativeInfos.get(child); - if (info.contains(editComponent)) { - I.remove(); - } - } - } - myHorizontalPoints = new ArrayList(); myVerticalPoints = new ArrayList(); - for (RadComponent component : children) { + for (RadComponent component : getSnapComponents(myContainer, myComponents)) { myHorizontalPoints.add(new ComponentSnapPoint((RadViewComponent)component, true)); myVerticalPoints.add(new ComponentSnapPoint((RadViewComponent)component, false)); myVerticalPoints.add(new BaselineSnapPoint((RadViewComponent)component)); @@ -223,6 +213,24 @@ public class RelativeLayoutOperation extends AbstractEditOperation { myVerticalPoints.add(new AutoSnapPoint(container, false)); } + public static List getSnapComponents(RadComponent container, List components) { + List children = new ArrayList(container.getChildren()); + children.removeAll(components); + + Map relativeInfos = container.getClientProperty(RelativeInfo.KEY); + for (RadComponent editComponent : components) { + for (Iterator I = children.iterator(); I.hasNext(); ) { + RadComponent child = I.next(); + RelativeInfo info = relativeInfos.get(child); + if (info.contains(editComponent)) { + I.remove(); + } + } + } + + return children; + } + @Override public void execute() throws Exception { if (myContext.isCreate() || myContext.isPaste() || myContext.isAdd()) { diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/RelativeLayoutResizeOperation.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/RelativeLayoutResizeOperation.java index 9f04adfd53c4..5df6f63217b3 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/RelativeLayoutResizeOperation.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/RelativeLayoutResizeOperation.java @@ -15,10 +15,11 @@ */ package com.intellij.android.designer.designSurface.layout.actions; -import com.intellij.android.designer.designSurface.layout.relative.SnapPoint; -import com.intellij.android.designer.designSurface.layout.relative.SnapPointFeedbackHost; +import com.intellij.android.designer.designSurface.layout.RelativeLayoutOperation; +import com.intellij.android.designer.designSurface.layout.relative.*; import com.intellij.android.designer.model.RadViewComponent; import com.intellij.designer.designSurface.EditOperation; +import com.intellij.designer.designSurface.FeedbackLayer; import com.intellij.designer.designSurface.OperationContext; import com.intellij.designer.designSurface.feedbacks.RectangleFeedback; import com.intellij.designer.designSurface.feedbacks.TextFeedback; @@ -26,8 +27,12 @@ import com.intellij.designer.designSurface.selection.DirectionResizePoint; import com.intellij.designer.designSurface.selection.ResizeSelectionDecorator; import com.intellij.designer.model.RadComponent; import com.intellij.designer.utils.Position; +import com.intellij.openapi.util.Pair; +import com.intellij.ui.IdeBorderFactory; import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -37,15 +42,18 @@ public class RelativeLayoutResizeOperation implements EditOperation { public static final String TYPE = "relative_resize"; private final OperationContext myContext; + private List myComponents; private RadViewComponent myComponent; + private RadViewComponent myContainer; - private RectangleFeedback myFeedback; + private RectangleFeedback myBoundsFeedback; + private RectangleFeedback myWrapFeedback; private SnapPointFeedbackHost mySnapFeedback; private TextFeedback myHorizontalTextFeedback; private TextFeedback myVerticalTextFeedback; private Rectangle myContainerBounds; - private Rectangle myBounds; + private Dimension myWrapSize; private List myHorizontalPoints; private List myVerticalPoints; @@ -59,7 +67,9 @@ public class RelativeLayoutResizeOperation implements EditOperation { @Override public void setComponent(RadComponent component) { + myComponents = Arrays.asList(component); myComponent = (RadViewComponent)component; + myContainer = (RadViewComponent)myComponent.getParent(); } @Override @@ -67,17 +77,148 @@ public class RelativeLayoutResizeOperation implements EditOperation { } private void createFeedback() { + if (mySnapFeedback == null) { + myContainer.setClientProperty(SnapPointFeedbackHost.KEY, Boolean.TRUE); + + FeedbackLayer layer = myContext.getArea().getFeedbackLayer(); + + myHorizontalTextFeedback = new TextFeedback(); + myHorizontalTextFeedback.setBorder(IdeBorderFactory.createEmptyBorder(0, 3, 2, 0)); + layer.add(myHorizontalTextFeedback); + + myVerticalTextFeedback = new TextFeedback(); + myVerticalTextFeedback.setBorder(IdeBorderFactory.createEmptyBorder(0, 3, 2, 0)); + layer.add(myVerticalTextFeedback); + + myBoundsFeedback = new RectangleFeedback(Color.blue, 2); + layer.add(myBoundsFeedback); + + int direction = myContext.getResizeDirection(); + if (direction == Position.EAST || direction == Position.SOUTH || direction == Position.SOUTH_EAST) { + Rectangle bounds = myComponent.getBounds(myContext.getArea().getFeedbackLayer()); + String width = myComponent.getTag().getAttributeValue("android:layout_width"); + String height = myComponent.getTag().getAttributeValue("android:layout_height"); + + Pair widthInfo = ResizeOperation.getDefaultSize(width, bounds.width); + Pair heightInfo = ResizeOperation.getDefaultSize(height, bounds.height); + + myWrapSize = new Dimension(widthInfo.first, heightInfo.first); + myComponent.calculateWrapSize(myWrapSize, bounds); + + Rectangle wrapBounds; + if (direction == Position.EAST) { + wrapBounds = new Rectangle(bounds.x, bounds.y, myWrapSize.width, bounds.height); + } + else if (direction == Position.SOUTH) { + wrapBounds = new Rectangle(bounds.x, bounds.y, bounds.width, myWrapSize.height); + } + else { + wrapBounds = new Rectangle(bounds.getLocation(), myWrapSize); + } + + myWrapFeedback = new RectangleFeedback(Color.green, 1); + myWrapFeedback.setBounds(wrapBounds); + layer.add(myWrapFeedback); + } + + myContainerBounds = myContainer.getBounds(layer); + + mySnapFeedback = new SnapPointFeedbackHost(); + mySnapFeedback.setBounds(myContainerBounds); + + createPoints(); + + layer.add(mySnapFeedback); + + layer.repaint(); + } } @Override public void showFeedback() { createFeedback(); - // TODO: Auto-generated method stub + + Rectangle bounds = myContext.getTransformedRectangle(myComponent.getBounds(myContext.getArea().getFeedbackLayer())); + bounds.width = Math.max(bounds.width, 0); + bounds.height = Math.max(bounds.height, 0); + + mySnapFeedback.clearAll(); + myHorizontalPoint = null; + myVerticalPoint = null; + + for (SnapPoint point : myHorizontalPoints) { + if (point.processBounds(myComponents, bounds, mySnapFeedback)) { + myHorizontalPoint = point; + break; + } + } + for (SnapPoint point : myVerticalPoints) { + if (point.processBounds(myComponents, bounds, mySnapFeedback)) { + myVerticalPoint = point; + break; + } + } + + mySnapFeedback.repaint(); + myBoundsFeedback.setBounds(bounds); + RelativeLayoutOperation.configureTextFeedback(myHorizontalTextFeedback, + myVerticalTextFeedback, + myHorizontalPoint, + myVerticalPoint, + myContainerBounds); } @Override public void eraseFeedback() { - // TODO: Auto-generated method stub + if (mySnapFeedback != null) { + myContainer.extractClientProperty(SnapPointFeedbackHost.KEY); + FeedbackLayer layer = myContext.getArea().getFeedbackLayer(); + layer.remove(myHorizontalTextFeedback); + layer.remove(myVerticalTextFeedback); + layer.remove(myBoundsFeedback); + + if (myWrapFeedback != null) { + layer.remove(myWrapFeedback); + } + + layer.remove(mySnapFeedback); + layer.repaint(); + myHorizontalTextFeedback = null; + myVerticalTextFeedback = null; + myBoundsFeedback = null; + myWrapFeedback = null; + mySnapFeedback = null; + } + } + + private void createPoints() { + myHorizontalPoints = new ArrayList(); + myVerticalPoints = new ArrayList(); + + List snapComponents = RelativeLayoutOperation.getSnapComponents(myContainer, myComponents); + snapComponents.removeAll(myContext.getComponents()); + + int direction = myContext.getResizeDirection(); + if ((direction & Position.NORTH_SOUTH) != 0) { + createPoints(myVerticalPoints, snapComponents, false, direction); + } + if ((direction & Position.EAST_WEST) != 0) { + createPoints(myHorizontalPoints, snapComponents, true, direction); + } + } + + private void createPoints(List points, List snapComponents, boolean horizontal, int direction) { + for (RadComponent component : snapComponents) { + points.add(new ResizeComponentSnapPoint((RadViewComponent)component, horizontal)); + } + + points.add(new ResizeContainerSnapPoint(myContainer, horizontal)); + + if (direction == Position.EAST || direction == Position.SOUTH || direction == Position.SOUTH_EAST) { + points.add(new WrapSizeSnapPoint(myComponent, horizontal, myWrapSize)); + } + + points.add(new AutoResizeSnapPoint(myContainer, horizontal, direction)); } @Override @@ -87,7 +228,12 @@ public class RelativeLayoutResizeOperation implements EditOperation { @Override public void execute() throws Exception { - // TODO: Auto-generated method stub + if (myHorizontalPoint != null) { + myHorizontalPoint.execute(myComponents); + } + if (myVerticalPoint != null) { + myVerticalPoint.execute(myComponents); + } } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/ResizeOperation.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/ResizeOperation.java index 34e2d1fa8125..c10c21fae8b6 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/ResizeOperation.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/actions/ResizeOperation.java @@ -43,7 +43,6 @@ public class ResizeOperation implements EditOperation { public final static Color blue = new Color(0, 50, 255); private static final int SNAP_DELTA = 4; - private static final int WRAP_CONTENT = 0 << 30; private final OperationContext myContext; private RadViewComponent myComponent; @@ -70,7 +69,6 @@ public class ResizeOperation implements EditOperation { myComponent = (RadViewComponent)component; Rectangle bounds = myComponent.getBounds(myContext.getArea().getFeedbackLayer()); - String width = myComponent.getTag().getAttributeValue("android:layout_width"); String height = myComponent.getTag().getAttributeValue("android:layout_height"); @@ -78,7 +76,7 @@ public class ResizeOperation implements EditOperation { Pair heightInfo = getDefaultSize(height, bounds.height); myWrapSize = new Dimension(widthInfo.first, heightInfo.first); - calculateWrapSize(bounds); + myComponent.calculateWrapSize(myWrapSize, bounds); myFillSize = new Dimension(widthInfo.second, heightInfo.second); calculateFillParentSize(bounds); @@ -86,33 +84,6 @@ public class ResizeOperation implements EditOperation { createStaticFeedback(bounds, width, height); } - private void calculateWrapSize(Rectangle bounds) { - if (myWrapSize.width == -1 || myWrapSize.height == -1) { - try { - Object viewObject = myComponent.getViewInfo().getViewObject(); - Class viewClass = viewObject.getClass(); - - viewClass.getMethod("forceLayout").invoke(viewObject); - viewClass.getMethod("measure", int.class, int.class).invoke(viewObject, WRAP_CONTENT, WRAP_CONTENT); - - if (myWrapSize.width == -1) { - myWrapSize.width = (Integer)viewClass.getMethod("getMeasuredWidth").invoke(viewObject); - } - if (myWrapSize.height == -1) { - myWrapSize.height = (Integer)viewClass.getMethod("getMeasuredHeight").invoke(viewObject); - } - } - catch (Throwable e) { - if (myWrapSize.width == -1) { - myWrapSize.width = bounds.width; - } - if (myWrapSize.height == -1) { - myWrapSize.height = bounds.height; - } - } - } - } - private void calculateFillParentSize(Rectangle bounds) { if (myFillSize.width == -1 || myFillSize.height == -1) { Rectangle parentBounds = myComponent.getParent().getBounds(myContext.getArea().getFeedbackLayer()); @@ -132,7 +103,7 @@ public class ResizeOperation implements EditOperation { } } - private static Pair getDefaultSize(String value, int size) { + public static Pair getDefaultSize(String value, int size) { int wrap = -1; int fill = -1; diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/AutoResizeSnapPoint.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/AutoResizeSnapPoint.java new file mode 100644 index 000000000000..2563f11eb425 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/AutoResizeSnapPoint.java @@ -0,0 +1,105 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.android.designer.designSurface.layout.relative; + +import com.intellij.android.designer.model.ModelParser; +import com.intellij.android.designer.model.RadViewComponent; +import com.intellij.designer.designSurface.feedbacks.TextFeedback; +import com.intellij.designer.model.RadComponent; +import com.intellij.designer.utils.Position; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.psi.xml.XmlTag; + +import java.awt.*; +import java.util.List; + +/** + * @author Alexander Lobas + */ +public class AutoResizeSnapPoint extends SnapPoint { + private final int myDirection; + private int myMargin; + private int mySize; + + public AutoResizeSnapPoint(RadViewComponent container, boolean horizontal, int direction) { + super(container, horizontal); + myDirection = direction; + } + + @Override + public void addTextInfo(TextFeedback feedback) { + if (myMargin > 0) { + feedback.append("alignParent" + (myHorizontal ? "Left " : "Top "), SnapPointFeedbackHost.SNAP_ATTRIBUTES); + feedback.append(", margin" + (myHorizontal ? "Left " : "Top ") + Integer.toString(myMargin)); + feedback.dimension("dp"); + feedback.append(", "); + } + + if ((myDirection & Position.EAST_WEST) != 0) { + feedback.append("layout:width "); + } + else { + feedback.append("layout:height "); + } + + feedback.append(Integer.toString(mySize)); + feedback.dimension("dp"); + } + + @Override + public boolean processBounds(List components, Rectangle bounds, SnapPointFeedbackHost feedback) { + super.processBounds(components, bounds, feedback); + + if (myHorizontal) { + mySize = bounds.width; + + if ((myDirection & Position.WEST) != 0) { + myMargin = bounds.x - myBounds.x; + feedback.addVerticalLine(myBounds.x, myBounds.y, myBounds.height); + feedback.addHorizontalArrow(myBounds.x, bounds.y + bounds.height / 2, myMargin); + } + } + else { + mySize = bounds.height; + + if ((myDirection & Position.NORTH) != 0) { + myMargin = bounds.y - myBounds.y; + feedback.addHorizontalLine(myBounds.x, myBounds.y, myBounds.width); + feedback.addVerticalArrow(bounds.x + bounds.width / 2, myBounds.y, myMargin); + } + } + + return true; + } + + @Override + public void execute(final List components) throws Exception { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + XmlTag tag = ((RadViewComponent)components.get(0)).getTag(); + if (myMargin > 0) { + tag.setAttribute("android:layout_alignParent" + (myHorizontal ? "Left" : "Top"), "true"); + tag.setAttribute("android:layout_margin" + (myHorizontal ? "Left" : "Top"), Integer.toString(myMargin) + "dp"); + } + else { + ModelParser.deleteAttribute(tag, "android:layout_alignParent" + (myHorizontal ? "Right" : "Bottom")); + } + tag.setAttribute("android:layout_" + (myHorizontal ? "width" : "height"), Integer.toString(mySize) + "dp"); + } + }); + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/BaselineSnapPoint.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/BaselineSnapPoint.java index e391ca5a84e7..a01db1391486 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/BaselineSnapPoint.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/BaselineSnapPoint.java @@ -32,7 +32,7 @@ public class BaselineSnapPoint extends SnapPoint { public BaselineSnapPoint(RadViewComponent component) { super(component, false); - myBaseline = ((RadViewComponent)component).getBaseline(); + myBaseline = component.getBaseline(); } @Override diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ComponentSnapPoint.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ComponentSnapPoint.java index 68c64c285354..438548f31839 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ComponentSnapPoint.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ComponentSnapPoint.java @@ -28,7 +28,7 @@ import java.util.List; * @author Alexander Lobas */ public class ComponentSnapPoint extends SnapPoint { - private Side myBeginSide; + protected Side myBeginSide; private Side myEndSide; public ComponentSnapPoint(RadViewComponent component, boolean horizontal) { diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ContainerSnapPoint.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ContainerSnapPoint.java index ca48d771434e..64075d082afc 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ContainerSnapPoint.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ContainerSnapPoint.java @@ -29,7 +29,7 @@ import java.util.List; * @author Alexander Lobas */ public class ContainerSnapPoint extends SnapPoint { - private Side mySide; + protected Side mySide; public ContainerSnapPoint(RadViewComponent container, boolean horizontal) { super(container, horizontal); @@ -139,7 +139,7 @@ public class ContainerSnapPoint extends SnapPoint { return false; } - private boolean processHorizontalCenter(Rectangle targetBounds, SnapPointFeedbackHost feedback) { + protected boolean processHorizontalCenter(Rectangle targetBounds, SnapPointFeedbackHost feedback) { int centerX = myBounds.x + myBounds.width / 2; int startX = centerX - SNAP_SIZE; @@ -156,7 +156,7 @@ public class ContainerSnapPoint extends SnapPoint { return false; } - private boolean processVerticalCenter(Rectangle targetBounds, SnapPointFeedbackHost feedback) { + protected boolean processVerticalCenter(Rectangle targetBounds, SnapPointFeedbackHost feedback) { int centerY = myBounds.y + myBounds.height / 2; int startY = centerY - SNAP_SIZE; diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ResizeComponentSnapPoint.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ResizeComponentSnapPoint.java new file mode 100644 index 000000000000..a8a239c52444 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ResizeComponentSnapPoint.java @@ -0,0 +1,62 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.android.designer.designSurface.layout.relative; + +import com.intellij.android.designer.model.ModelParser; +import com.intellij.android.designer.model.RadViewComponent; +import com.intellij.designer.model.RadComponent; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.psi.xml.XmlTag; + +import java.util.List; + +/** + * @author Alexander Lobas + */ +public class ResizeComponentSnapPoint extends ComponentSnapPoint { + public ResizeComponentSnapPoint(RadViewComponent component, boolean horizontal) { + super(component, horizontal); + } + + @Override + public void execute(final List components) throws Exception { + super.execute(components); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + XmlTag tag = ((RadViewComponent)components.get(0)).getTag(); + + if (myBeginSide == Side.top) { + ModelParser.deleteAttribute(tag, "android:layout_alignParentTop"); + ModelParser.deleteAttribute(tag, "android:layout_marginTop"); + } + else if (myBeginSide == Side.bottom) { + ModelParser.deleteAttribute(tag, "android:layout_alignParentBottom"); + ModelParser.deleteAttribute(tag, "android:layout_marginBottom"); + } + else if (myBeginSide == Side.left) { + ModelParser.deleteAttribute(tag, "android:layout_alignParentLeft"); + ModelParser.deleteAttribute(tag, "android:layout_marginLeft"); + } + else if (myBeginSide == Side.right) { + ModelParser.deleteAttribute(tag, "android:layout_alignParentRight"); + ModelParser.deleteAttribute(tag, "android:layout_marginRight"); + } + } + }); + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ResizeContainerSnapPoint.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ResizeContainerSnapPoint.java new file mode 100644 index 000000000000..5c6ea51cfb9e --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/ResizeContainerSnapPoint.java @@ -0,0 +1,73 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.android.designer.designSurface.layout.relative; + +import com.intellij.android.designer.model.ModelParser; +import com.intellij.android.designer.model.RadViewComponent; +import com.intellij.designer.model.RadComponent; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.psi.xml.XmlTag; + +import java.awt.*; +import java.util.List; + +/** + * @author Alexander Lobas + */ +public class ResizeContainerSnapPoint extends ContainerSnapPoint { + public ResizeContainerSnapPoint(RadViewComponent container, boolean horizontal) { + super(container, horizontal); + } + + @Override + protected boolean processHorizontalCenter(Rectangle targetBounds, SnapPointFeedbackHost feedback) { + return false; + } + + @Override + protected boolean processVerticalCenter(Rectangle targetBounds, SnapPointFeedbackHost feedback) { + return false; + } + + @Override + public void execute(final List components) throws Exception { + super.execute(components); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + XmlTag tag = ((RadViewComponent)components.get(0)).getTag(); + + if (mySide == Side.top) { + ModelParser.deleteAttribute(tag, "android:layout_alignTop"); + ModelParser.deleteAttribute(tag, "android:layout_below"); + } + else if (mySide == Side.left) { + ModelParser.deleteAttribute(tag, "android:layout_alignBottom"); + ModelParser.deleteAttribute(tag, "android:layout_above"); + } + else if (mySide == Side.bottom) { + ModelParser.deleteAttribute(tag, "android:layout_alignLeft"); + ModelParser.deleteAttribute(tag, "android:layout_toRightOf"); + } + else if (mySide == Side.right) { + ModelParser.deleteAttribute(tag, "android:layout_alignRight"); + ModelParser.deleteAttribute(tag, "android:layout_toLeftOf"); + } + } + }); + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/WrapSizeSnapPoint.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/WrapSizeSnapPoint.java new file mode 100644 index 000000000000..3a7891d30a43 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/layout/relative/WrapSizeSnapPoint.java @@ -0,0 +1,76 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.android.designer.designSurface.layout.relative; + +import com.intellij.android.designer.model.ModelParser; +import com.intellij.android.designer.model.RadViewComponent; +import com.intellij.designer.designSurface.feedbacks.TextFeedback; +import com.intellij.designer.model.RadComponent; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.psi.xml.XmlTag; + +import java.awt.*; +import java.util.List; + +/** + * @author Alexander Lobas + */ +public class WrapSizeSnapPoint extends SnapPoint { + private final Dimension myWrapSize; + + public WrapSizeSnapPoint(RadViewComponent component, boolean horizontal, Dimension wrapSize) { + super(component, horizontal); + myWrapSize = wrapSize; + } + + @Override + public void addTextInfo(TextFeedback feedback) { + feedback.append("layout:" + (myHorizontal ? "width " : "height ")); + feedback.snap("wrap_content"); + } + + @Override + public boolean processBounds(List components, Rectangle bounds, SnapPointFeedbackHost feedback) { + super.processBounds(components, bounds, feedback); + + if (myHorizontal) { + if (Math.abs(bounds.width - myWrapSize.width) < SNAP_SIZE) { + bounds.width = myWrapSize.width; + return true; + } + } + else { + if (Math.abs(bounds.height - myWrapSize.height) < SNAP_SIZE) { + bounds.height = myWrapSize.height; + return true; + } + } + + return false; + } + + @Override + public void execute(final List components) throws Exception { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + XmlTag tag = ((RadViewComponent)components.get(0)).getTag(); + ModelParser.deleteAttribute(tag, "android:layout_alignParent" + (myHorizontal ? "Right" : "Bottom")); + tag.setAttribute("android:layout_" + (myHorizontal ? "width" : "height"), "wrap_content"); + } + }); + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadViewComponent.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewComponent.java index 2fa5a8ea9f06..b7dbce9d9545 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/RadViewComponent.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadViewComponent.java @@ -41,11 +41,6 @@ public class RadViewComponent extends RadVisualComponent { private XmlTag myTag; private List myProperties; - @Override - public List getChildren() { - return myChildren; - } - public XmlTag getTag() { return myTag; } @@ -75,6 +70,12 @@ public class RadViewComponent extends RadVisualComponent { myMargins = null; } + ////////////////////////////////////////////////////////////////////////////////////////// + // + // + // + ////////////////////////////////////////////////////////////////////////////////////////// + public String ensureId() { String id = getId(); if (id == null) { @@ -94,6 +95,12 @@ public class RadViewComponent extends RadVisualComponent { return "@id/" + idValue.substring(idValue.indexOf('/') + 1); } + ////////////////////////////////////////////////////////////////////////////////////////// + // + // + // + ////////////////////////////////////////////////////////////////////////////////////////// + public int getBaseline() { try { Object viewObject = myViewInfo.getViewObject(); @@ -128,6 +135,46 @@ public class RadViewComponent extends RadVisualComponent { return value == Integer.MIN_VALUE ? 0 : value; } + private static final int WRAP_CONTENT = 0 << 30; + + public void calculateWrapSize(Dimension wrapSize, Rectangle bounds) { + if (wrapSize.width == -1 || wrapSize.height == -1) { + try { + Object viewObject = myViewInfo.getViewObject(); + Class viewClass = viewObject.getClass(); + + viewClass.getMethod("forceLayout").invoke(viewObject); + viewClass.getMethod("measure", int.class, int.class).invoke(viewObject, WRAP_CONTENT, WRAP_CONTENT); + + if (wrapSize.width == -1) { + wrapSize.width = (Integer)viewClass.getMethod("getMeasuredWidth").invoke(viewObject); + } + if (wrapSize.height == -1) { + wrapSize.height = (Integer)viewClass.getMethod("getMeasuredHeight").invoke(viewObject); + } + } + catch (Throwable e) { + if (wrapSize.width == -1) { + wrapSize.width = bounds.width; + } + if (wrapSize.height == -1) { + wrapSize.height = bounds.height; + } + } + } + } + + ////////////////////////////////////////////////////////////////////////////////////////// + // + // + // + ////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public List getChildren() { + return myChildren; + } + @Override public void delete() throws Exception { IdManager.get(this).removeComponent(this, true); From d1c25ca05e0ffb8324126ad70fc9b65f28a9fea1 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 15 May 2012 18:38:51 +0200 Subject: [PATCH 40/61] load facet types synchronously --- jps/model/src/org/jetbrains/jps/idea/FacetLoader.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jps/model/src/org/jetbrains/jps/idea/FacetLoader.groovy b/jps/model/src/org/jetbrains/jps/idea/FacetLoader.groovy index 697e3ac7e1bc..897f5fd9c47e 100644 --- a/jps/model/src/org/jetbrains/jps/idea/FacetLoader.groovy +++ b/jps/model/src/org/jetbrains/jps/idea/FacetLoader.groovy @@ -30,7 +30,7 @@ class FacetLoader { } } - private static FacetTypeService findFacetType(String typeId) { + private static synchronized FacetTypeService findFacetType(String typeId) { if (facetTypes == null) { facetTypes = [:] facetTypeLoader.each {FacetTypeService type -> From 1c49b9ee5cd3af8cf0699cc6a51155a3100a3a93 Mon Sep 17 00:00:00 2001 From: Vassiliy Kudryashov Date: Tue, 15 May 2012 22:39:28 +0400 Subject: [PATCH 41/61] TomcatSupportProviderTest fix --- .../impl/run/BuildArtifactsBeforeRunTaskProvider.java | 8 ++++++++ .../src/com/intellij/execution/RunManagerEx.java | 2 ++ .../src/com/intellij/execution/impl/RunManagerImpl.java | 9 ++++----- .../src/com/intellij/mock/MockRunManager.java | 4 ++++ 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/run/BuildArtifactsBeforeRunTaskProvider.java b/java/compiler/impl/src/com/intellij/packaging/impl/run/BuildArtifactsBeforeRunTaskProvider.java index c7bab6b06867..bfd25ce8f0b0 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/run/BuildArtifactsBeforeRunTaskProvider.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/run/BuildArtifactsBeforeRunTaskProvider.java @@ -228,6 +228,14 @@ public class BuildArtifactsBeforeRunTaskProvider extends BeforeRunTaskProvider buildArtifactsTasks = runManager.getBeforeRunTasks(configuration, ID); + if (buildArtifactsTasks.isEmpty()) { //Add new task if absent + BuildArtifactsBeforeRunTask task = new BuildArtifactsBeforeRunTask(project); + buildArtifactsTasks.add(task); + List tasks = runManager.getBeforeRunTasks(configuration); + tasks.add(task); + runManager.setBeforeRunTasks(configuration, tasks, false); + } + for (BuildArtifactsBeforeRunTask task : buildArtifactsTasks) { task.setEnabled(true); task.addArtifact(artifact); diff --git a/platform/lang-impl/src/com/intellij/execution/RunManagerEx.java b/platform/lang-impl/src/com/intellij/execution/RunManagerEx.java index 13a16c6fd8f2..d1ffbf31d23d 100644 --- a/platform/lang-impl/src/com/intellij/execution/RunManagerEx.java +++ b/platform/lang-impl/src/com/intellij/execution/RunManagerEx.java @@ -65,6 +65,8 @@ public abstract class RunManagerEx extends RunManager { @NotNull public abstract List getBeforeRunTasks(RunConfiguration settings); + public abstract void setBeforeRunTasks(RunConfiguration runConfiguration, List tasks, boolean addEnabledTemplateTasksIfAbsent); + @NotNull public abstract List getBeforeRunTasks(RunConfiguration settings, Key taskProviderID); diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java index cc09148e22af..2b9637df0b3e 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java @@ -256,7 +256,6 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, checkRecentsLimit(); mySharedConfigurations.put(newId, shared); - getTemplateBeforeRunTask(configuration); setBeforeRunTasks(configuration, tasks, addEnabledTemplateTasksIfAbsent); if (existingSettings == settings) { @@ -830,10 +829,10 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, if (tasks != null) { return getCopies(tasks); } - return getTemplateBeforeRunTask(settings); + return getTemplateBeforeRunTasks(settings); } - private List getTemplateBeforeRunTask(RunConfiguration settings) { + private List getTemplateBeforeRunTasks(RunConfiguration settings) { final RunnerAndConfigurationSettings template = getConfigurationTemplate(settings.getFactory()); final List templateTasks = myConfigurationToBeforeTasksMap.get(template.getConfiguration()); if (templateTasks != null) { @@ -879,7 +878,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, public final void setBeforeRunTasks(final RunConfiguration runConfiguration, @NotNull List tasks, boolean addEnabledTemplateTasksIfAbsent) { List result = new ArrayList(tasks); if (addEnabledTemplateTasksIfAbsent) { - List templates = getTemplateBeforeRunTask(runConfiguration); + List templates = getTemplateBeforeRunTasks(runConfiguration); Set> idsToSet = new HashSet>(); for (BeforeRunTask task : tasks) { idsToSet.add(task.getProviderId()); @@ -902,7 +901,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, } public void addConfiguration(final RunnerAndConfigurationSettings settings, final boolean isShared) { - addConfiguration(settings, isShared, new ArrayList(), false); + addConfiguration(settings, isShared, getTemplateBeforeRunTasks(settings.getConfiguration()), false); } public static RunManagerImpl getInstanceImpl(final Project project) { diff --git a/platform/testFramework/src/com/intellij/mock/MockRunManager.java b/platform/testFramework/src/com/intellij/mock/MockRunManager.java index 8cb22fd675be..481ef662723b 100644 --- a/platform/testFramework/src/com/intellij/mock/MockRunManager.java +++ b/platform/testFramework/src/com/intellij/mock/MockRunManager.java @@ -129,6 +129,10 @@ public class MockRunManager extends RunManagerEx { return Collections.emptyList(); } + @Override + public void setBeforeRunTasks(RunConfiguration runConfiguration, List tasks, boolean addEnabledTemplateTasksIfAbsent) { + } + @Override public RunnerAndConfigurationSettings findConfigurationByName(@NotNull String name) { return null; From a922bfab53a83c0610512dedf76b7ebd1cd8f80c Mon Sep 17 00:00:00 2001 From: Evgeny Zakrevsky Date: Tue, 15 May 2012 22:54:01 +0400 Subject: [PATCH 42/61] IDEA-77932 Create Patch dialog resizes several time on opening --- .../options/InitialConfigurationDialog.java | 2 +- .../integration/ui/views/RevisionsList.java | 2 +- .../openapi/ui/SimpleToolWindowPanel.java | 7 +- .../src/com/intellij/ui/TitledSeparator.java | 20 +- .../ui/AbstractTitledSeparatorWithIcon.java | 6 +- .../ui/HideableDetailsUnderSeparator.java | 5 +- .../com/intellij/ui/HideableTitledPanel.java | 131 +++++++++++++ .../ui/SplitterWithSecondHideable.java | 143 +++++++------- .../src/com/intellij/openapi/ui/Splitter.java | 48 +++-- .../util/src/com/intellij/util/ui/UIUtil.java | 29 +-- .../patch/CreatePatchConfigurationPanel.java | 179 ++++-------------- .../changes/ui/CommitChangeListDialog.java | 2 +- 12 files changed, 289 insertions(+), 285 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/ui/HideableTitledPanel.java diff --git a/platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.java b/platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.java index 27625060354f..e00ecc273227 100644 --- a/platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.java +++ b/platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.java @@ -165,7 +165,7 @@ public class InitialConfigurationDialog extends DialogWrapper { private void createUIComponents() { myColorPreviewPanel = new AbstractTitledSeparatorWithIcon(IconLoader.getIcon("/general/comboArrowRight.png"), IconLoader.getIcon("/general/comboArrowDown.png"), - "Click to preview", true, false) { + "Click to preview") { private int myAddedWidth; diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/RevisionsList.java b/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/RevisionsList.java index 21ea7b38aa09..17df7d096bbc 100644 --- a/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/RevisionsList.java +++ b/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/RevisionsList.java @@ -394,7 +394,7 @@ public class RevisionsList { @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { Graphics2D g2d = (Graphics2D)g.create(); - g2d.setColor(UIUtil.getBorderSeparatorColor()); + g2d.setColor(UIUtil.getBorderColor()); g2d.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, new float[]{1}, 1)); g2d.drawLine(x, y, x + width, y); if (isLast) { diff --git a/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java b/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java index 8198230777a4..8ac88742c368 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java @@ -18,7 +18,6 @@ package com.intellij.openapi.ui; import com.intellij.openapi.actionSystem.ActionToolbar; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.DataProvider; -import com.intellij.openapi.actionSystem.Separator; import com.intellij.openapi.util.Ref; import com.intellij.ui.switcher.QuickActionProvider; import com.intellij.util.ui.AwtVisitor; @@ -28,8 +27,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.awt.event.*; -import java.util.*; +import java.awt.event.ContainerAdapter; +import java.awt.event.ContainerEvent; import java.util.List; public class SimpleToolWindowPanel extends JPanel implements QuickActionProvider, DataProvider { @@ -145,7 +144,7 @@ public class SimpleToolWindowPanel extends JPanel implements QuickActionProvider super.paintComponent(g); if (myToolbar != null && myToolbar.getParent() == this && myContent != null && myContent.getParent() == this) { - g.setColor(UIUtil.getBorderSeparatorColor()); + g.setColor(UIUtil.getBorderColor()); if (myVertical) { final int y = (int)myToolbar.getBounds().getMaxY(); g.drawLine(0, y, getWidth(), y); diff --git a/platform/platform-api/src/com/intellij/ui/TitledSeparator.java b/platform/platform-api/src/com/intellij/ui/TitledSeparator.java index 6d759615473d..7773ee761c7a 100644 --- a/platform/platform-api/src/com/intellij/ui/TitledSeparator.java +++ b/platform/platform-api/src/com/intellij/ui/TitledSeparator.java @@ -54,7 +54,7 @@ public class TitledSeparator extends JPanel { public void updateUI() { super.updateUI(); if (myLabel != null) { - myLabel.setFont(UIUtil.getBorderFont(UIUtil.FontSize.SMALL, false)); + myLabel.setFont(UIUtil.getTitledBorderFont()); } } @@ -81,22 +81,4 @@ public class TitledSeparator extends JPanel { public JSeparator getSeparator() { return mySeparator; } - - @Deprecated - public boolean isBoldFont() { - return false; - } - - @Deprecated - public boolean isSmallFont() { - return true; - } - - @Deprecated - public void setBoldFont(boolean boldFont) { - } - - @Deprecated - public void setSmallFont(boolean smallFont) { - } } diff --git a/platform/platform-impl/src/com/intellij/ui/AbstractTitledSeparatorWithIcon.java b/platform/platform-impl/src/com/intellij/ui/AbstractTitledSeparatorWithIcon.java index 5a061dfef07a..44ef8f368d44 100644 --- a/platform/platform-impl/src/com/intellij/ui/AbstractTitledSeparatorWithIcon.java +++ b/platform/platform-impl/src/com/intellij/ui/AbstractTitledSeparatorWithIcon.java @@ -42,9 +42,7 @@ public abstract class AbstractTitledSeparatorWithIcon extends JPanel { public AbstractTitledSeparatorWithIcon(@NotNull final Icon icon, @NotNull final Icon iconOpen, - @NotNull final String text, - final boolean smallFont, - final boolean boldFont) { + @NotNull final String text) { myIcon = icon; myIconOpen = iconOpen; setLayout(new GridBagLayout()); @@ -59,7 +57,7 @@ public abstract class AbstractTitledSeparatorWithIcon extends JPanel { new Insets(3, 0, 0, 0), 0, 0); add(mySeparator, gb); setBorder(IdeBorderFactory.createEmptyBorder(3, 0, 5, 5)); - myLabel.setFont(UIUtil.getBorderFont(smallFont ? UIUtil.FontSize.SMALL : UIUtil.FontSize.NORMAL, boldFont)); + myLabel.setFont(UIUtil.getTitledBorderFont()); myLabel.setForeground(UIUtil.getTitledBorderTitleColor()); originalText = text; myLabel.setText(UIUtil.replaceMnemonicAmpersand(originalText)); diff --git a/platform/platform-impl/src/com/intellij/ui/HideableDetailsUnderSeparator.java b/platform/platform-impl/src/com/intellij/ui/HideableDetailsUnderSeparator.java index fb3d91012efe..1e9af99d3528 100644 --- a/platform/platform-impl/src/com/intellij/ui/HideableDetailsUnderSeparator.java +++ b/platform/platform-impl/src/com/intellij/ui/HideableDetailsUnderSeparator.java @@ -29,9 +29,8 @@ import java.awt.*; public abstract class HideableDetailsUnderSeparator extends AbstractTitledSeparatorWithIcon { public HideableDetailsUnderSeparator(@NotNull Icon icon, @NotNull Icon iconOpen, - @NotNull String text, - boolean smallFont, boolean boldFont) { - super(icon, iconOpen, text, smallFont, boldFont); + @NotNull String text) { + super(icon, iconOpen, text); } public void on() { diff --git a/platform/platform-impl/src/com/intellij/ui/HideableTitledPanel.java b/platform/platform-impl/src/com/intellij/ui/HideableTitledPanel.java new file mode 100644 index 000000000000..783c47ca8aec --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ui/HideableTitledPanel.java @@ -0,0 +1,131 @@ +package com.intellij.ui; + +import com.intellij.openapi.util.IconLoader; +import com.intellij.util.ui.UIUtil; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/** + * @author evgeny zakrevsky + */ +public class HideableTitledPanel extends JPanel { + Icon OFF_ICON = IconLoader.getIcon("/general/comboArrow.png"); + Icon ON_ICON = IconLoader.getIcon("/general/comboUpPassive.png"); + private TitledSeparatorWithMnemonic myTitledSeparator; + private boolean myOn; + private final JComponent myContent; + private Dimension myPreviousContentSize; + + public HideableTitledPanel(String title, JComponent content, boolean on) { + super(new BorderLayout()); + myContent = content; + add(myContent, BorderLayout.CENTER); + myTitledSeparator = new TitledSeparatorWithMnemonic(title, null); + add(myTitledSeparator, BorderLayout.NORTH); + myTitledSeparator.getLabel().setIcon(OFF_ICON); + + myTitledSeparator.getLabel().addMouseListener(new MouseAdapter() { + @Override + public void mouseReleased(MouseEvent e) { + if (myOn) { + off(); + } + else { + on(); + } + } + + @Override + public void mouseEntered(MouseEvent e) { + setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + + @Override + public void mouseExited(MouseEvent e) { + setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + }); + + UIUtil.setActionNameAndMnemonic(title, new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + if (myOn) { + off(); + } + else { + on(); + } + } + }); + + setOn(on); + } + + public void setOn(boolean on) { + myOn = on; + if (myOn) { + on(); + } + else { + off(); + } + } + + protected void on() { + myOn = true; + myTitledSeparator.getLabel().setIcon(ON_ICON); + myContent.setVisible(true); + adjustWindow(); + invalidate(); + repaint(); + } + + private void adjustWindow() { + final Window window = SwingUtilities.getWindowAncestor(this); + if (window == null) return; + final Dimension size = window.getSize(); + final Dimension contentSize = myPreviousContentSize != null && myPreviousContentSize.width > 0 && myPreviousContentSize.height > 0 + ? myPreviousContentSize + : myContent.getPreferredSize(); + final Dimension newSize; + if (myOn) { + newSize = new Dimension(Math.max(size.width, myContent.getSize().width), size.height + contentSize.height); + } + else { + newSize = new Dimension(size.width, size.height - contentSize.height); + } + if (!newSize.equals(size)) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + if (window.isShowing()) { + window.setSize(newSize); + } + } + }); + } + } + + protected void off() { + myOn = false; + myTitledSeparator.getLabel().setIcon(OFF_ICON); + myContent.setVisible(false); + myPreviousContentSize = myContent.getSize(); + adjustWindow(); + invalidate(); + repaint(); + } + + public void setTitle(String title) { + myTitledSeparator.setText(title); + } + + @Override + public void setEnabled(boolean enabled) { + myTitledSeparator.myLabel.setForeground(enabled ? UIUtil.getActiveTextColor() : UIUtil.getInactiveTextColor()); + myContent.setEnabled(enabled); + } +} diff --git a/platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java b/platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java index 2b86c4af99a6..8e80795c01c6 100644 --- a/platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java +++ b/platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java @@ -47,7 +47,7 @@ public abstract class SplitterWithSecondHideable { public SplitterWithSecondHideable(final boolean vertical, final String separatorText, final JComponent firstComponent, - final OnOffListener listener, final boolean boldFont) { + final OnOffListener listener) { myVertical = vertical; myListener = listener; myFictivePanel = new JPanel(new BorderLayout()); @@ -56,12 +56,13 @@ public abstract class SplitterWithSecondHideable { if (vertical) { icon = IconLoader.getIcon("/general/comboArrow.png"); openIcon = IconLoader.getIcon("/general/comboUpPassive.png"); - } else { + } + else { icon = IconLoader.getIcon("/general/comboArrowRight.png"); openIcon = IconLoader.getIcon("/general/comboArrowRightPassive.png"); } - myTitledSeparator = new AbstractTitledSeparatorWithIcon(icon, openIcon, separatorText, true, true) { + myTitledSeparator = new AbstractTitledSeparatorWithIcon(icon, openIcon, separatorText) { @Override protected RefreshablePanel createPanel() { return createDetails(); @@ -89,7 +90,7 @@ public abstract class SplitterWithSecondHideable { final int firstSize = vertical ? mySplitter.getFirstComponent().getHeight() : mySplitter.getFirstComponent().getWidth(); // !! order is important! first fix mySplitter.fixFirst(); - myListener.on((int) ((1 - proportion) * firstSize / proportion)); + myListener.on((int)((1 - proportion) * firstSize / proportion)); //mySplitter.setProportion(proportion); mySplitter.setSecondComponent(myDetailsComponent.getPanel()); mySplitter.revalidate(); @@ -111,66 +112,67 @@ public abstract class SplitterWithSecondHideable { } }; mySplitter = new PseudoSplitter(vertical) { - { - myTitledSeparator.mySeparator.addMouseListener(new MouseAdapter() { - @Override - public void mouseEntered(MouseEvent e) { - myTitledSeparator.mySeparator - .setCursor(myTitledSeparator.myOn ? new Cursor(Cursor.S_RESIZE_CURSOR) : new Cursor(Cursor.DEFAULT_CURSOR)); - ((MyDivider) mySuperDivider).processMouseEvent(e); - } + { + myTitledSeparator.mySeparator.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + myTitledSeparator.mySeparator + .setCursor(myTitledSeparator.myOn ? new Cursor(Cursor.S_RESIZE_CURSOR) : new Cursor(Cursor.DEFAULT_CURSOR)); + ((MyDivider)mySuperDivider).processMouseEvent(e); + } - @Override - public void mouseExited(MouseEvent e) { - myTitledSeparator.mySeparator.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); - ((MyDivider) mySuperDivider).processMouseEvent(e); - } + @Override + public void mouseExited(MouseEvent e) { + myTitledSeparator.mySeparator.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + ((MyDivider)mySuperDivider).processMouseEvent(e); + } - @Override - public void mouseClicked(MouseEvent e) { - ((MyDivider) mySuperDivider).processMouseEvent(e); - } + @Override + public void mouseClicked(MouseEvent e) { + ((MyDivider)mySuperDivider).processMouseEvent(e); + } - @Override - public void mousePressed(MouseEvent e) { - ((MyDivider) mySuperDivider).processMouseEvent(e); - } + @Override + public void mousePressed(MouseEvent e) { + ((MyDivider)mySuperDivider).processMouseEvent(e); + } - @Override - public void mouseReleased(MouseEvent e) { - ((MyDivider) mySuperDivider).processMouseEvent(e); - } + @Override + public void mouseReleased(MouseEvent e) { + ((MyDivider)mySuperDivider).processMouseEvent(e); + } - @Override - public void mouseWheelMoved(MouseWheelEvent e) { - ((MyDivider) mySuperDivider).processMouseEvent(e); - } + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + ((MyDivider)mySuperDivider).processMouseEvent(e); + } - @Override - public void mouseDragged(MouseEvent e) { - ((MyDivider) mySuperDivider).processMouseEvent(e); - } + @Override + public void mouseDragged(MouseEvent e) { + ((MyDivider)mySuperDivider).processMouseEvent(e); + } - @Override - public void mouseMoved(MouseEvent e) { - ((MyDivider) mySuperDivider).processMouseEvent(e); - } - }); + @Override + public void mouseMoved(MouseEvent e) { + ((MyDivider)mySuperDivider).processMouseEvent(e); + } + }); - myTitledSeparator.mySeparator.addMouseMotionListener(new MouseMotionListener() { - @Override - public void mouseDragged(MouseEvent e) { - ((MyDivider) mySuperDivider).processMouseMotionEvent(e); - } + myTitledSeparator.mySeparator.addMouseMotionListener(new MouseMotionListener() { + @Override + public void mouseDragged(MouseEvent e) { + ((MyDivider)mySuperDivider).processMouseMotionEvent(e); + } - @Override - public void mouseMoved(MouseEvent e) { - ((MyDivider) mySuperDivider).processMouseMotionEvent(e); - } - }); - } - @Override - protected Divider createDivider() { + @Override + public void mouseMoved(MouseEvent e) { + ((MyDivider)mySuperDivider).processMouseMotionEvent(e); + } + }); + } + + @Override + protected Divider createDivider() { mySuperDivider = new MyDivider(); mySuperDivider.add(myTitledSeparator, new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, @@ -178,22 +180,22 @@ public abstract class SplitterWithSecondHideable { return mySuperDivider; } - @Override - public int getDividerWidth() { + @Override + public int getDividerWidth() { return vertical ? myTitledSeparator.getHeight() : myTitledSeparator.getWidth(); } - class MyDivider extends Divider { - @Override - public void processMouseMotionEvent(MouseEvent e) { - super.processMouseMotionEvent(e); - } - - @Override - public void processMouseEvent(MouseEvent e) { - super.processMouseEvent(e); - } + class MyDivider extends Divider { + @Override + public void processMouseMotionEvent(MouseEvent e) { + super.processMouseMotionEvent(e); } + + @Override + public void processMouseEvent(MouseEvent e) { + super.processMouseEvent(e); + } + } }; mySplitter.setDoubleBuffered(true); mySplitter.setFirstComponent(firstComponent); @@ -201,7 +203,7 @@ public abstract class SplitterWithSecondHideable { //mySplitter.setShowDividerIcon(false); mySplitter.setProportion(1.0f); } - + public void setText(final String value) { myTitledSeparator.setText(value); } @@ -215,6 +217,7 @@ public abstract class SplitterWithSecondHideable { } protected abstract RefreshablePanel createDetails(); + protected abstract float getSplitterInitialProportion(); public float getUsedProportion() { @@ -224,11 +227,11 @@ public abstract class SplitterWithSecondHideable { public void initOn() { myTitledSeparator.initOn(); } - + public void on() { myTitledSeparator.on(); } - + public void off() { myTitledSeparator.off(); } diff --git a/platform/util/src/com/intellij/openapi/ui/Splitter.java b/platform/util/src/com/intellij/openapi/ui/Splitter.java index 8e4b183ed269..a3b37c807ab5 100644 --- a/platform/util/src/com/intellij/openapi/ui/Splitter.java +++ b/platform/util/src/com/intellij/openapi/ui/Splitter.java @@ -244,8 +244,10 @@ public class Splitter extends JPanel { if (isHonorMinimumSize()) { - final double firstMinSize = getOrientation() ? myFirstComponent.getMinimumSize().getHeight() : myFirstComponent.getMinimumSize().getWidth(); - final double secondMinSize = getOrientation() ? mySecondComponent.getMinimumSize().getHeight() : mySecondComponent.getMinimumSize().getWidth(); + final double firstMinSize = + getOrientation() ? myFirstComponent.getMinimumSize().getHeight() : myFirstComponent.getMinimumSize().getWidth(); + final double secondMinSize = + getOrientation() ? mySecondComponent.getMinimumSize().getHeight() : mySecondComponent.getMinimumSize().getWidth(); if (firstComponentSize + secondComponentSize < firstMinSize + secondMinSize) { double proportion = firstMinSize / (firstMinSize + secondMinSize); @@ -269,19 +271,19 @@ public class Splitter extends JPanel { firstComponentSize = Math.floor(firstComponentSize); secondComponentSize = Math.floor(secondComponentSize); - + if (getOrientation()) { // fix flooring - secondComponentSize += (int) (height - firstComponentSize - secondComponentSize - dividerWidth); - + secondComponentSize += (int)(height - firstComponentSize - secondComponentSize - dividerWidth); + firstRect.setBounds(0, 0, (int)width, (int)firstComponentSize); dividerRect.setBounds(0, (int)firstComponentSize, (int)width, (int)dividerWidth); secondRect.setBounds(0, (int)(firstComponentSize + dividerWidth), (int)width, (int)secondComponentSize); } else { // fix flooring - secondComponentSize += (int) (width - firstComponentSize - secondComponentSize - dividerWidth); - + secondComponentSize += (int)(width - firstComponentSize - secondComponentSize - dividerWidth); + firstRect.setBounds(0, 0, (int)firstComponentSize, (int)height); dividerRect.setBounds((int)firstComponentSize, 0, (int)dividerWidth, (int)height); secondRect.setBounds((int)(firstComponentSize + dividerWidth), 0, (int)secondComponentSize, (int)height); @@ -485,16 +487,15 @@ public class Splitter extends JPanel { } Icon glueIcon = IconLoader.getIcon(isVerticalSplit ? "/general/splitGlueV.png" : "/general/splitGlueH.png"); - int leftInsetIcon = 1; - int leftInsetArrow = 0; - int glueFill = isVerticalSplit ? GridBagConstraints.VERTICAL : GridBagConstraints.HORIZONTAL; - add(new JLabel(glueIcon), new GridBagConstraints(0, 0, 1, 1, 0, 0, - GridBagConstraints.CENTER, GridBagConstraints.EAST, - new Insets(0, leftInsetIcon, 0, 0), 0, 0)); + add(new JLabel(glueIcon), new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE, + new Insets(0, 0, 0, 0), 0, 0)); if (myShowDividerControls && false) { + int glueFill = isVerticalSplit ? GridBagConstraints.VERTICAL : GridBagConstraints.HORIZONTAL; int xMask = isVerticalSplit ? 1 : 0; int yMask = isVerticalSplit ? 0 : 1; + int leftInsetArrow = 0; + int leftInsetIcon = 1; JLabel splitDownlabel = new JLabel(IconLoader.getIcon(isVerticalSplit ? "/general/splitDown.png" : "/general/splitRight.png")); splitDownlabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); @@ -509,7 +510,8 @@ public class Splitter extends JPanel { GridBagConstraints.NONE, new Insets(0, leftInsetArrow, 0, 0), 0, 0)); // add(new JLabel(glueIcon), - new GridBagConstraints(2 * xMask, 2 * yMask, 1, 1, 0, 0, GridBagConstraints.CENTER, glueFill, new Insets(0, leftInsetIcon, 0, 0), 0, 0)); + new GridBagConstraints(2 * xMask, 2 * yMask, 1, 1, 0, 0, GridBagConstraints.CENTER, glueFill, + new Insets(0, leftInsetIcon, 0, 0), 0, 0)); JLabel splitCenterlabel = new JLabel(IconLoader.getIcon(isVerticalSplit ? "/general/splitCenterV.png" : "/general/splitCenterH.png")); splitCenterlabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); @@ -522,7 +524,8 @@ public class Splitter extends JPanel { add(splitCenterlabel, new GridBagConstraints(3 * xMask, 3 * yMask, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, leftInsetArrow, 0, 0), 0, 0)); add(new JLabel(glueIcon), - new GridBagConstraints(4 * xMask, 4 * yMask, 1, 1, 0, 0, GridBagConstraints.CENTER, glueFill, new Insets(0, leftInsetIcon, 0, 0), 0, 0)); + new GridBagConstraints(4 * xMask, 4 * yMask, 1, 1, 0, 0, GridBagConstraints.CENTER, glueFill, + new Insets(0, leftInsetIcon, 0, 0), 0, 0)); // JLabel splitUpLabel = new JLabel(IconLoader.getIcon(isVerticalSplit ? "/general/splitUp.png" : "/general/splitLeft.png")); splitUpLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); @@ -539,7 +542,7 @@ public class Splitter extends JPanel { isVerticalSplit ? GridBagConstraints.WEST : GridBagConstraints.SOUTH, glueFill, new Insets(0, leftInsetIcon, 0, 0), 0, 0)); } - + revalidate(); repaint(); } @@ -552,13 +555,17 @@ public class Splitter extends JPanel { float proportion; if (getOrientation()) { if (getHeight() > 0) { - proportion = Math.min(1.0f, Math.max(.0f, Math.min(Math.max(getMinProportion(myFirstComponent), (float)myPoint.y / (float)Splitter.this.getHeight()), 1 - getMinProportion(mySecondComponent)))); + proportion = Math.min(1.0f, Math.max(.0f, Math + .min(Math.max(getMinProportion(myFirstComponent), (float)myPoint.y / (float)Splitter.this.getHeight()), + 1 - getMinProportion(mySecondComponent)))); setProportion(proportion); } } else { if (getWidth() > 0) { - proportion = Math.min(1.0f, Math.max(.0f, Math.min(Math.max(getMinProportion(myFirstComponent), (float)myPoint.x / (float)Splitter.this.getWidth()), 1 - getMinProportion(mySecondComponent)))); + proportion = Math.min(1.0f, Math.max(.0f, Math + .min(Math.max(getMinProportion(myFirstComponent), (float)myPoint.x / (float)Splitter.this.getWidth()), + 1 - getMinProportion(mySecondComponent)))); setProportion(proportion); } } @@ -595,9 +602,10 @@ public class Splitter extends JPanel { public void setResizeEnabled(boolean resizeEnabled) { myResizeEnabled = resizeEnabled; - if (! myResizeEnabled) { + if (!myResizeEnabled) { setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } else { + } + else { setCursor(getOrientation() ? Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR) : Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR)); diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 0a19f1839d11..89aa02faf0be 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -20,7 +20,10 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.ui.*; +import com.intellij.ui.ColorUtil; +import com.intellij.ui.Gray; +import com.intellij.ui.PanelWithAnchor; +import com.intellij.ui.SideBorder; import com.intellij.util.ArrayUtil; import com.intellij.util.PairFunction; import com.intellij.util.Processor; @@ -40,15 +43,12 @@ import javax.swing.border.EmptyBorder; import javax.swing.border.LineBorder; import javax.swing.plaf.ComboBoxUI; import javax.swing.plaf.ProgressBarUI; -import javax.swing.plaf.UIResource; import javax.swing.plaf.basic.BasicComboBoxUI; -import javax.swing.plaf.basic.BasicTreeUI; import javax.swing.plaf.basic.ComboPopup; import javax.swing.text.DefaultEditorKit; import javax.swing.text.JTextComponent; import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.StyleSheet; -import javax.swing.tree.TreePath; import java.awt.*; import java.awt.event.*; import java.awt.font.FontRenderContext; @@ -1562,26 +1562,9 @@ public class UIUtil { return BORDER_COLOR; } - public static Color getTitledBorderLineColor() { - return BORDER_COLOR; - } - public static Font getTitledBorderFont() { - return getLabelFont(); - } - - public static Font getBorderFont(@NotNull FontSize size, boolean isBold) { - Font defFont = getTitledBorderFont(); - if (size == FontSize.SMALL) { - defFont = defFont.deriveFont(Math.max(defFont.getSize() - 2f, 11f)); - } - if (size == FontSize.MINI) { - defFont = defFont.deriveFont(Math.max(defFont.getSize() - 4f, 9f)); - } - //if (isBold) { - // defFont = defFont.deriveFont(Font.BOLD); - //} - return defFont; + Font defFont = getLabelFont(); + return defFont.deriveFont(Math.max(defFont.getSize() - 2f, 11f)); } public static Color getTitledBorderTitleColor() { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchConfigurationPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchConfigurationPanel.java index ff9008bb46f5..801082dc1f82 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchConfigurationPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchConfigurationPanel.java @@ -34,15 +34,14 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.VcsBundle; import com.intellij.openapi.vcs.VcsConfiguration; import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.changes.RefreshablePanel; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileWrapper; import com.intellij.openapi.vfs.encoding.EncodingManager; -import com.intellij.ui.SplitterWithSecondHideable; +import com.intellij.ui.HideableTitledPanel; import com.intellij.util.Consumer; -import com.intellij.util.OnOffListener; +import com.intellij.util.ui.FormBuilder; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -58,7 +57,7 @@ public class CreatePatchConfigurationPanel { private static final String SYSTEM_DEFAULT = IdeBundle.message("encoding.name.system.default"); public static final String ALL = "(All)"; - private JPanel myPanel; + private JPanel myMainPanel; private TextFieldWithBrowseButton myFileNameField; private JCheckBox myReversePatchCheckbox; private JComboBox myEncoding; @@ -70,17 +69,18 @@ public class CreatePatchConfigurationPanel { private List myChanges; private Collection myIncludedChanges; private SelectFilesToAddTextsToPatchPanel mySelectFilesToAddTextsToPatchPanel; - private SplitterWithSecondHideable mySplitterWithSecondHideable; + private HideableTitledPanel myHideableTitledPanel; + private JPanel myPanelWithSelectedFiles; public CreatePatchConfigurationPanel(final Project project) { myProject = project; - initUi(); + initMainPanel(); myFileNameField.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { final FileSaverDialog dialog = FileChooserFactory.getInstance().createSaveFileDialog( - new FileSaverDescriptor("Save patch to", ""), myPanel); + new FileSaverDescriptor("Save patch to", ""), myMainPanel); final String path = FileUtil.toSystemIndependentName(myFileNameField.getText().trim()); final int idx = path.lastIndexOf("/"); VirtualFile baseDir = idx == -1 ? project.getBaseDir() : @@ -121,27 +121,6 @@ public class CreatePatchConfigurationPanel { }); myErrorLabel.setForeground(Color.RED); checkName(); - /*new AdjustComponentWhenShown() { - @Override - protected boolean init() { - if (myPanel.isVisible()) { - IdeFocusManager.findInstanceByComponent(myPanel).requestFocus(myFileNameField.getTextField(), true); - if (myIncludeBaseRevisionTextCheckBox.isVisible()) { - // a hack =( - final JDialog dialog = getParentDialog(); - final Dimension dialogSize = dialog.getSize(); - dialog.setSize(dialogSize.width, dialogSize.height + 1); - if (dialogSize.width < 500) { - dialog.setSize(500, dialogSize.height - 1); - } else { - dialog.setSize(dialogSize.width, dialogSize.height - 1); - } - dialog.repaint(); - } - } - return false; - } - }.install(myPanel);*/ initEncodingCombo(); } @@ -165,110 +144,31 @@ public class CreatePatchConfigurationPanel { if (SYSTEM_DEFAULT.equals(selectedItem)) { return EncodingManager.getInstance().getDefaultCharset(); } - return (Charset) selectedItem; + return (Charset)selectedItem; } - private void initUi() { - myPanel = new JPanel(new GridBagLayout()); - myPanel.setMinimumSize(new Dimension(400, -1)); - final GridBagConstraints gb = new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, - new Insets(1, 1, 1, 1), 0, 0); - gb.anchor = GridBagConstraints.WEST; - final JLabel createPatchLabel = new JLabel(VcsBundle.message("create.patch.file.path")); - myPanel.add(createPatchLabel, gb); - gb.anchor = GridBagConstraints.NORTHWEST; + private void initMainPanel() { myFileNameField = new TextFieldWithBrowseButton(); - ++ gb.gridx; - gb.fill = GridBagConstraints.HORIZONTAL; - gb.weightx = 1; - myPanel.add(myFileNameField, gb); - - /*gb.fill = GridBagConstraints.NONE; - gb.weightx = 0;*/ - gb.gridx = 0; - ++ gb.gridy; - gb.gridwidth = 2; myReversePatchCheckbox = new JCheckBox(VcsBundle.message("create.patch.reverse.patch.checkbox")); - ++ gb.gridy; - myPanel.add(myReversePatchCheckbox, gb); - ++ gb.gridy; - gb.gridwidth = 2; - - gb.anchor = GridBagConstraints.WEST; - myPanel.add(new JLabel("Encoding:"), gb); - ++ gb.gridx; - gb.anchor = GridBagConstraints.NORTHWEST; myEncoding = new JComboBox(); - myPanel.add(myEncoding, gb); - ++ gb.gridy; - - gb.gridx = 0; myIncludeBaseRevisionTextCheckBox = new JCheckBox("Include base revision text(s) into patch file"); - myPanel.add(myIncludeBaseRevisionTextCheckBox, gb); - ++ gb.gridy; - myErrorLabel = new JLabel(); - myPanel.add(myErrorLabel, gb); + + myMainPanel = FormBuilder.createFormBuilder() + .addLabeledComponent(VcsBundle.message("create.patch.file.path"), myFileNameField) + .addComponent(myReversePatchCheckbox) + .addLabeledComponent("Encoding:", myEncoding) + .addComponent(myIncludeBaseRevisionTextCheckBox) + .addComponent(myErrorLabel) + .getPanel(); } - private void initSplitter(Runnable inclusionListener) { + private void initPanelWithSelectedFiles(Runnable inclusionListener) { mySelectFilesToAddTextsToPatchPanel = new SelectFilesToAddTextsToPatchPanel(myProject, myChanges, myIncludedChanges, inclusionListener); - final Dimension preferredSize = myPanel.getPreferredSize(); - final JPanel wrapper = new JPanel(new BorderLayout()) { - @Override - public Dimension getPreferredSize() { - return preferredSize; - } - - @Override - public Dimension getMaximumSize() { - return preferredSize; - } - - @Override - public Dimension getMinimumSize() { - return preferredSize; - } - }; - wrapper.add(myPanel, BorderLayout.NORTH); - mySplitterWithSecondHideable = new SplitterWithSecondHideable(true, ALL, wrapper, new OnOffListener() { - @Override - public void on(Integer integer) { - VcsConfiguration.getInstance(myProject).CREATE_PATCH_EXPAND_DETAILS_DEFAULT = true; - final JDialog dialog = getParentDialog(); - final Dimension dialogSize = dialog.getSize(); - int width = dialogSize.width < 550 ? 550 : dialogSize.width; - dialog.setSize(width, dialogSize.height + integer); - dialog.repaint(); - } - - @Override - public void off(Integer integer) { - VcsConfiguration.getInstance(myProject).CREATE_PATCH_EXPAND_DETAILS_DEFAULT = false; - final JDialog dialog = getParentDialog(); - final Dimension dialogSize = dialog.getSize(); - dialog.setSize(dialogSize.width, dialogSize.height - integer); - dialog.repaint(); - } - }, false) { - @Override - protected RefreshablePanel createDetails() { - return mySelectFilesToAddTextsToPatchPanel; - } - - @Override - protected float getSplitterInitialProportion() { - return 0.3f; - } - }; - } - - private JDialog getParentDialog() { - Container parent = myPanel.getParent(); - while (! (parent instanceof JDialog)) { - parent = parent.getParent(); - } - return (JDialog)parent; + myHideableTitledPanel = new HideableTitledPanel("", mySelectFilesToAddTextsToPatchPanel.getPanel(), false); + myPanelWithSelectedFiles = new JPanel(new BorderLayout()); + myPanelWithSelectedFiles.add(myMainPanel, BorderLayout.NORTH); + myPanelWithSelectedFiles.add(myHideableTitledPanel, BorderLayout.CENTER); } public void showTextStoreOption(final boolean dvcsIsUsed) { @@ -276,29 +176,29 @@ public class CreatePatchConfigurationPanel { if (myChanges.size() > 0) { myIncludeBaseRevisionTextCheckBox.setVisible(true); - final VcsConfiguration configuration = VcsConfiguration.getInstance(myProject); - - boolean turnOn = dvcsIsUsed || configuration.INCLUDE_TEXT_INTO_PATCH; - myIncludeBaseRevisionTextCheckBox.setSelected(turnOn); - myIncludeBaseRevisionTextCheckBox.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - mySelectFilesToAddTextsToPatchPanel.setEnabled(myIncludeBaseRevisionTextCheckBox.isSelected()); - mySplitterWithSecondHideable.setEnabledColor(myIncludeBaseRevisionTextCheckBox.isSelected()); - } - }); final Runnable inclusionListener = new Runnable() { @Override public void run() { if (mySelectFilesToAddTextsToPatchPanel != null) { myIncludedChanges = mySelectFilesToAddTextsToPatchPanel.getIncludedChanges(); - mySplitterWithSecondHideable.setText("Selected: " + (myIncludedChanges.size() == myChanges.size() ? - "All" : ("" + myIncludedChanges.size() + " of " + myChanges.size()))); + myHideableTitledPanel.setTitle("Selected: " + (myIncludedChanges.size() == myChanges.size() ? + "All" : (myIncludedChanges.size() + " of " + myChanges.size()))); } } }; - initSplitter(inclusionListener); + initPanelWithSelectedFiles(inclusionListener); inclusionListener.run(); + + final VcsConfiguration configuration = VcsConfiguration.getInstance(myProject); + boolean turnOn = dvcsIsUsed || configuration.INCLUDE_TEXT_INTO_PATCH; + myIncludeBaseRevisionTextCheckBox.setSelected(turnOn); + myIncludeBaseRevisionTextCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + myHideableTitledPanel.setEnabled(myIncludeBaseRevisionTextCheckBox.isSelected()); + } + }); + myHideableTitledPanel.setEnabled(myIncludeBaseRevisionTextCheckBox.isSelected()); } } @@ -306,7 +206,8 @@ public class CreatePatchConfigurationPanel { final PatchNameChecker patchNameChecker = new PatchNameChecker(myFileNameField.getText()); if (patchNameChecker.nameOk()) { myErrorLabel.setText(""); - } else { + } + else { myErrorLabel.setText(patchNameChecker.getError()); } if (myOkEnabledListener != null) { @@ -315,7 +216,7 @@ public class CreatePatchConfigurationPanel { } public void onOk() { - if (myIncludeBaseRevisionTextCheckBox.isVisible() && ! myDvcsIsUsed) { + if (myIncludeBaseRevisionTextCheckBox.isVisible() && !myDvcsIsUsed) { final VcsConfiguration vcsConfiguration = VcsConfiguration.getInstance(myProject); vcsConfiguration.INCLUDE_TEXT_INTO_PATCH = myIncludeBaseRevisionTextCheckBox.isSelected(); } @@ -330,7 +231,7 @@ public class CreatePatchConfigurationPanel { } public JComponent getPanel() { - return ! myIncludeBaseRevisionTextCheckBox.isVisible() || myChanges.isEmpty() ? myPanel : mySplitterWithSecondHideable.getComponent(); + return !myIncludeBaseRevisionTextCheckBox.isVisible() || myChanges.isEmpty() ? myMainPanel : myPanelWithSelectedFiles; } public void installOkEnabledListener(final Consumer runnable) { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java index 70779b8b6882..900ed610ff03 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java @@ -994,7 +994,7 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj setSize(dialogSize.width, dialogSize.height - integer); repaint(); } - }, true) { + }) { @Override protected RefreshablePanel createDetails() { initDetails(); From d1af9e587842494f0741610dafe0485296fde4a7 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 15 May 2012 20:58:42 +0200 Subject: [PATCH 43/61] create breakpoint for every codeIndex returned for a given line. (IDEA-80556, IDEA-81110) --- .../ui/breakpoints/LineBreakpoint.java | 27 ++++++------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java index e7e14ece92ee..e3586870ec1e 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java @@ -131,28 +131,17 @@ public class LineBreakpoint extends BreakpointWithHighlighter { } try { List locs = debugProcess.getPositionManager().locationsOfLine(classType, getSourcePosition()); - if (locs.size() > 0) { - Location minLocation = null; - for (final Location loc : locs) { - if (minLocation == null) { - minLocation = loc; + if (!locs.isEmpty()) { + for (Location loc : locs) { + if (LOG.isDebugEnabled()) { + LOG.debug("Found location [codeIndex=" + loc.codeIndex() +"] for reference type " + classType.name() + " at line " + getLineIndex() + "; isObsolete: " + (debugProcess.getVirtualMachineProxy().versionHigher("1.4") && loc.method().isObsolete())); } - else if (loc.codeIndex() < minLocation.codeIndex()) { - minLocation = loc; + BreakpointRequest request = debugProcess.getRequestsManager().createBreakpointRequest(LineBreakpoint.this, loc); + debugProcess.getRequestsManager().enableRequest(request); + if (LOG.isDebugEnabled()) { + LOG.debug("Created breakpoint request for reference type " + classType.name() + " at line " + getLineIndex() + "; codeIndex=" + loc.codeIndex()); } } - - assert minLocation != null; - - if (LOG.isDebugEnabled()) { - LOG.debug("Found location for reference type " + classType.name() + " at line " + getLineIndex() + "; isObsolete: " + (debugProcess.getVirtualMachineProxy().versionHigher("1.4") && minLocation - .method().isObsolete())); - } - BreakpointRequest request = debugProcess.getRequestsManager().createBreakpointRequest(LineBreakpoint.this, minLocation); - debugProcess.getRequestsManager().enableRequest(request); - if (LOG.isDebugEnabled()) { - LOG.debug("Created breakpoint request for reference type " + classType.name() + " at line " + getLineIndex()); - } } else { // there's no executable code in this class From b4e5b91d299e237e118eec1dc1d4a484e18a5f91 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 15 May 2012 21:59:26 +0200 Subject: [PATCH 44/61] fix NPEs --- .../com/intellij/debugger/engine/DebugProcessImpl.java | 10 ++++++---- .../com/intellij/debugger/ui/PositionHighlighter.java | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java index aeda55d6c3f6..1136db3dd846 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java @@ -447,10 +447,12 @@ public abstract class DebugProcessImpl implements DebugProcess { try { if (thread != null && thread.frameCount() > 0) { StackFrameProxyImpl stackFrame = thread.frame(0); - Location location = stackFrame.location(); - ReferenceType referenceType = location.declaringType(); - if (referenceType != null) { - return referenceType.name(); + if (stackFrame != null) { + Location location = stackFrame.location(); + ReferenceType referenceType = location.declaringType(); + if (referenceType != null) { + return referenceType.name(); + } } } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java b/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java index e2f7af092f12..57be8b16bf3b 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java @@ -301,7 +301,7 @@ public class PositionHighlighter { try { StackFrameProxyImpl frameProxy = myContext.getFrameProxy(); final ThreadReferenceProxyImpl thread = getSuspendContext().getThread(); - isExecutionPoint = thread != null && frameProxy.equals(thread.frame(0)); + isExecutionPoint = thread != null && frameProxy != null && frameProxy.equals(thread.frame(0)); } catch(Throwable th) { LOG.debug(th); From 96a8926d70d06b87c02b7613486c2a50782a8d3f Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 15 May 2012 22:04:56 +0200 Subject: [PATCH 45/61] fix NPE --- .../intellij/debugger/actions/JavaMarkObjectActionHandler.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/JavaMarkObjectActionHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/JavaMarkObjectActionHandler.java index 53db32ecfb51..dcd0454c16aa 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/JavaMarkObjectActionHandler.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/JavaMarkObjectActionHandler.java @@ -33,6 +33,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.util.containers.HashMap; @@ -148,7 +149,7 @@ public class JavaMarkObjectActionHandler extends MarkObjectActionHandler { if (node instanceof DebuggerTreeNodeImpl) { final DebuggerTreeNodeImpl _node = (DebuggerTreeNodeImpl)node; final NodeDescriptorImpl descriptor = _node.getDescriptor(); - if (descriptor instanceof ValueDescriptor && value.equals(((ValueDescriptor)descriptor).getValue())) { + if (descriptor instanceof ValueDescriptor && Comparing.equal(value, ((ValueDescriptor)descriptor).getValue())) { _node.labelChanged(); } } From 78ba93f48ca2d0ba7f14a804238b1f0ddcf53825 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 15 May 2012 22:44:57 +0200 Subject: [PATCH 46/61] ParameterList: avoid undefined macros in macro map (IDEA-86118 GWT plugin run configuration. ${PROJECT_DIR} macros in VM options. Leads crash if trying to run/debug) --- .../com/intellij/execution/configurations/ParametersList.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/platform/platform-api/src/com/intellij/execution/configurations/ParametersList.java b/platform/platform-api/src/com/intellij/execution/configurations/ParametersList.java index 06cccde080c3..56c4f6959997 100644 --- a/platform/platform-api/src/com/intellij/execution/configurations/ParametersList.java +++ b/platform/platform-api/src/com/intellij/execution/configurations/ParametersList.java @@ -334,8 +334,7 @@ public class ParametersList implements Cloneable { final Application application = ApplicationManager.getApplication(); if (application != null) { final PathMacros pathMacros = PathMacros.getInstance(); - final Set names = pathMacros.getAllMacroNames(); - for (String name : names) { + for (String name : pathMacros.getUserMacroNames()) { myMacroMap.put("${" + name + "}", pathMacros.getValue(name)); } final Map env = EnvironmentUtil.getEnviromentProperties(); From 9d8ae0a8feb951f799df29fc9f10ba07f4b0b255 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 15 May 2012 22:47:19 +0200 Subject: [PATCH 47/61] additional null check --- .../intellij/execution/configurations/ParametersList.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/execution/configurations/ParametersList.java b/platform/platform-api/src/com/intellij/execution/configurations/ParametersList.java index 56c4f6959997..762ba6c55400 100644 --- a/platform/platform-api/src/com/intellij/execution/configurations/ParametersList.java +++ b/platform/platform-api/src/com/intellij/execution/configurations/ParametersList.java @@ -335,7 +335,10 @@ public class ParametersList implements Cloneable { if (application != null) { final PathMacros pathMacros = PathMacros.getInstance(); for (String name : pathMacros.getUserMacroNames()) { - myMacroMap.put("${" + name + "}", pathMacros.getValue(name)); + final String value = pathMacros.getValue(name); + if (value != null) { + myMacroMap.put("${" + name + "}", value); + } } final Map env = EnvironmentUtil.getEnviromentProperties(); for (String name : env.keySet()) { From f6d42f51495839fbd90e87e5f2358b760d810b12 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 16 May 2012 00:40:58 +0400 Subject: [PATCH 48/61] Fix nested highlighting support in a test framework --- .../ExpectedHighlightingData.java | 155 ++++++++++-------- .../ExpectedHighlightingDataTest.java | 125 ++++++++++++++ 2 files changed, 213 insertions(+), 67 deletions(-) create mode 100644 platform/testFramework/testSrc/com/intellij/testFramework/ExpectedHighlightingDataTest.java diff --git a/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java b/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java index 44024054e76d..880746145197 100644 --- a/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java +++ b/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +36,7 @@ import com.intellij.openapi.editor.markup.GutterIconRenderer; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; @@ -44,15 +45,19 @@ import com.intellij.psi.PsiFile; import com.intellij.rt.execution.junit.FileComparisonFailure; import com.intellij.util.ConstantFunction; import com.intellij.util.Function; +import com.intellij.util.NullableFunction; +import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashMap; import gnu.trove.THashSet; import junit.framework.Assert; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.awt.*; import java.lang.reflect.Field; import java.util.*; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -72,17 +77,17 @@ public class ExpectedHighlightingData { @NonNls private static final String ANY_TEXT = "*"; private final String myText; - private static class ExpectedHighlightingSet { + public static class ExpectedHighlightingSet { + private final HighlightSeverity severity; private final boolean endOfLine; - final boolean enabled; - final Set infos; - final HighlightSeverity severity; + private final boolean enabled; + private final Set infos; public ExpectedHighlightingSet(@NotNull HighlightSeverity severity, boolean endOfLine, boolean enabled) { + this.severity = severity; this.endOfLine = endOfLine; this.enabled = enabled; infos = new THashSet(); - this.severity = severity; } } @SuppressWarnings("WeakerAccess") @@ -114,10 +119,10 @@ public class ExpectedHighlightingData { myDocument = document; myFile = file; myText = document.getText(); - highlightingTypes = new LinkedHashMap(); + highlightingTypes = new LinkedHashMap(); new WriteCommandAction.Simple(file == null ? null : file.getProject()) { public void run() { - boolean checkWarnings= false; + boolean checkWarnings = false; boolean checkWeakWarnings = false; boolean checkInfos = false; @@ -138,13 +143,13 @@ public class ExpectedHighlightingData { initAdditionalHighlightingTypes(); } }.execute().throwException(); - } + public ExpectedHighlightingData(@NotNull final Document document, final boolean checkWarnings, final boolean checkWeakWarnings, final boolean checkInfos, - PsiFile file) { + @Nullable final PsiFile file) { this(document, file); if (checkWarnings) checkWarnings(); if (checkWeakWarnings) checkWeakWarnings(); @@ -290,6 +295,7 @@ public class ExpectedHighlightingData { TextAttributes forcedAttributes = null; if (foregroundColor != null) { + //noinspection MagicConstant forcedAttributes = new TextAttributes(Color.decode(foregroundColor), Color.decode(backgroundColor), Color.decode(effectColor), EffectType.valueOf(effectType), Integer.parseInt(fontType)); } @@ -334,15 +340,6 @@ public class ExpectedHighlightingData { private static final HighlightInfoType WHATEVER = new HighlightInfoType.HighlightInfoTypeImpl(); - public Collection getExtractedHighlightInfos(){ - final Collection result = new ArrayList(); - final Collection collection = highlightingTypes.values(); - for (ExpectedHighlightingSet set : collection) { - result.addAll(set.infos); - } - return result; - } - public void checkLineMarkers(Collection markerInfos, String text) { String fileName = myFile == null ? "" : myFile.getName() + ": "; String failMessage = ""; @@ -412,7 +409,7 @@ public class ExpectedHighlightingData { checkResult(infos, text, null); } - public void checkResult(Collection infos, String text, String filePath) { + public void checkResult(Collection infos, String text, @Nullable String filePath) { String fileName = myFile == null ? "" : myFile.getName() + ": "; String failMessage = ""; @@ -470,60 +467,84 @@ public class ExpectedHighlightingData { } } - private void compareTexts(Collection infos, String text, String failMessage, String filePath) { - final ArrayList list = new ArrayList(infos); - Collections.sort(list, new Comparator() { // by start offset descending then by end offset ascending + private void compareTexts(Collection infos, String text, String failMessage, @Nullable String filePath) { + String actual = composeText(highlightingTypes, infos, text); + if (filePath != null && !myText.equals(actual)) { + throw new FileComparisonFailure(failMessage, myText, actual, filePath); + } + Assert.assertEquals(failMessage + "\n", myText, actual); + Assert.fail(failMessage); + } + + public static String composeText(final Map types, Collection infos, String text) { + // filter highlighting data and map each highlighting to a tag name + List> list = ContainerUtil.mapNotNull(infos, new NullableFunction>() { @Override - public int compare(HighlightInfo o1, HighlightInfo o2) { - final int start = o2.startOffset - o1.startOffset; - return start != 0 ? start : o1.endOffset - o2.endOffset; + public Pair fun(HighlightInfo info) { + for (Map.Entry entry : types.entrySet()) { + final ExpectedHighlightingSet set = entry.getValue(); + if (set.enabled && set.severity == info.getSeverity() && set.endOfLine == info.isAfterEndOfLine) { + return Pair.create(entry.getKey(), info); + } + } + return null; } }); - StringBuilder sb = new StringBuilder(); + // sort filtered highlighting data by end offset in descending order + Collections.sort(list, new Comparator>() { + @Override + public int compare(Pair o1, Pair o2) { + HighlightInfo i1 = o1.second; + HighlightInfo i2 = o2.second; - int end = text.length(); - HighlightInfo prev = null; - String prevSeverity = null; - for (HighlightInfo info : list) { - for (Map.Entry entry : highlightingTypes.entrySet()) { - final ExpectedHighlightingSet set = entry.getValue(); - if (set.enabled - && set.severity == info.getSeverity() - && set.endOfLine == info.isAfterEndOfLine) { - final String severity = entry.getKey(); + int byEnds = i2.endOffset - i1.endOffset; + if (byEnds != 0) return byEnds; - if (prev != null && info.endOffset > prev.startOffset) { // nested ranges - Assert.assertTrue("Overlapped highlightings: " + info + " and " + prev, - info.endOffset >= prev.endOffset); + int byStarts = i1.startOffset - i2.startOffset; + if (byStarts != 0) return byStarts; - int offset = prevSeverity.length()*2 + 14 + (prev.description != null ? prev.description.length() : 4) + // open and closing tags - prev.endOffset - prev.startOffset + info.endOffset - prev.endOffset; - sb.insert(offset, ""); - sb.insert(0, text.substring(info.startOffset, prev.startOffset)); - sb.insert(0, "<" + severity + " descr=\"" + info.description + "\">"); - } - else { // sequential ranges - sb.insert(0, text.substring(info.endOffset, end)); - sb.insert(0, "<" + severity + " descr=\"" + info.description + "\">" + - text.substring(info.startOffset, info.endOffset) + - ""); - } + int bySeverity = i2.severity.compareTo(i1.severity); + if (bySeverity != 0) return bySeverity; - end = info.startOffset; - prev = info; - prevSeverity = severity; - break; - } + return Comparing.compare(i1.description, i2.description); } - } - sb.insert(0, text.substring(0, end)); + }); - if (filePath != null && !myText.equals(sb.toString())) { - throw new FileComparisonFailure(failMessage, myText, sb.toString(), filePath); + // combine highlighting data with original text + StringBuilder sb = new StringBuilder(); + Pair result = composeText(sb, list, 0, text, text.length(), 0); + sb.insert(0, text.substring(0, result.second)); + return sb.toString(); + } + + private static Pair composeText(StringBuilder sb, + List> list, int index, + String text, int endPos, int startPos) { + int i = index; + while (i < list.size()) { + Pair pair = list.get(i); + HighlightInfo info = pair.second; + if (info.endOffset < startPos) break; + String severity = pair.first; + HighlightInfo prev = i < list.size() - 1 ? list.get(i + 1).second : null; + + sb.insert(0, text.substring(info.endOffset, endPos)); + sb.insert(0, ""); + endPos = info.endOffset; + if (prev != null && prev.endOffset > info.startOffset) { + Pair result = composeText(sb, list, i + 1, text, endPos, info.startOffset); + i = result.first - 1; + endPos = result.second; + } + sb.insert(0, text.substring(info.startOffset, endPos)); + sb.insert(0, "<" + severity + " descr=\"" + info.description + "\">"); + + endPos = info.startOffset; + i++; } - Assert.assertEquals(failMessage + "\n", myText, sb.toString()); - Assert.fail(failMessage); + + return Pair.create(i, endPos); } private static boolean infosContainsExpectedInfo(Collection infos, HighlightInfo expectedInfo) { @@ -559,9 +580,9 @@ public class ExpectedHighlightingData { info.endOffset == expectedInfo.endOffset && info.isAfterEndOfLine == expectedInfo.isAfterEndOfLine && (expectedInfo.type == WHATEVER || expectedInfo.type.equals(info.type)) && - (Comparing.strEqual(ANY_TEXT, expectedInfo.description) || Comparing.strEqual(info.description, expectedInfo.description)) - && (expectedInfo.forcedTextAttributes == null || expectedInfo.getTextAttributes(null, null).equals(info.getTextAttributes(null, null))) - && (expectedInfo.forcedTextAttributesKey == null || expectedInfo.forcedTextAttributesKey.equals(info.forcedTextAttributesKey)) - ; + (Comparing.strEqual(ANY_TEXT, expectedInfo.description) || Comparing.strEqual(info.description, expectedInfo.description)) && + (expectedInfo.forcedTextAttributes == null || Comparing.equal(expectedInfo.getTextAttributes(null, null), + info.getTextAttributes(null, null))) && + (expectedInfo.forcedTextAttributesKey == null || expectedInfo.forcedTextAttributesKey.equals(info.forcedTextAttributesKey)); } } diff --git a/platform/testFramework/testSrc/com/intellij/testFramework/ExpectedHighlightingDataTest.java b/platform/testFramework/testSrc/com/intellij/testFramework/ExpectedHighlightingDataTest.java new file mode 100644 index 000000000000..afcac8ac0cd0 --- /dev/null +++ b/platform/testFramework/testSrc/com/intellij/testFramework/ExpectedHighlightingDataTest.java @@ -0,0 +1,125 @@ +/* + * 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.testFramework; + +import com.intellij.codeInsight.daemon.impl.HighlightInfo; +import com.intellij.codeInsight.daemon.impl.HighlightInfoType; +import com.intellij.lang.annotation.HighlightSeverity; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.*; + +import static org.junit.Assert.assertEquals; + +public class ExpectedHighlightingDataTest { + private static Map TYPES; + + @BeforeClass + public static void setUp() throws Exception { + TYPES = new HashMap(); + TYPES.put("err", new ExpectedHighlightingData.ExpectedHighlightingSet(HighlightSeverity.ERROR, false, true)); + TYPES.put("warn", new ExpectedHighlightingData.ExpectedHighlightingSet(HighlightSeverity.WARNING, false, true)); + } + + @AfterClass + public static void tearDown() throws Exception { + TYPES.clear(); + TYPES = null; + } + + @Test + public void empty() throws Exception { + doTest("text", Collections.emptyList(), "text"); + } + + @Test + public void sequential() throws Exception { + doTest("_my text_", + Arrays.asList(error(1, 3, "1"), error(4, 8, "2")), + "_my text_"); + } + + @Test + public void simpleNested() throws Exception { + doTest("[(nested)]", + Arrays.asList(error(1, 9, "1"), error(2, 8, "2")), + "[(nested)]"); + } + + @Test + public void deepNested() throws Exception { + doTest("m1(m2(m3(m4(x))))", + Arrays.asList(error(3, 16, "m1"), error(6, 15, "m2"), error(9, 14, "m3"), error(12, 13, "m4")), + "m1(m2(m3(m4(x))))"); + } + + @Test + public void sameStart() throws Exception { + doTest("same start", + Arrays.asList(error(0, 4, "1"), error(0, 10, "2")), + "same start"); + } + + @Test + public void sameEnd() throws Exception { + doTest("same end", + Arrays.asList(error(0, 8, "1"), error(5, 8, "2")), + "same end"); + } + + @Test + public void sameBothBounds() throws Exception { + doTest("same", + Arrays.asList(error(0, 4, "-"), warning(0, 4, "-")), + "same"); + } + + @Test + public void samePriority() throws Exception { + doTest("same", + Arrays.asList(warning(0, 4, "1"), warning(0, 4, "2")), + "same"); + } + + @Test + public void twoNests() throws Exception { + doTest("(two nests)", + Arrays.asList(error(0, 11, "-"), error(1, 4, "1"), error(5, 10, "2")), + "(two nests)"); + } + + @Test + public void realistic() throws Exception { + doTest("one and (two nests)", + Arrays.asList(error(4, 7, "-"), error(8, 19, "-"), error(9, 12, "1"), error(13, 18, "2")), + "one and (two nests)"); + } + + private static void doTest(String original, Collection highlighting, String expected) { + String text = ExpectedHighlightingData.composeText(TYPES, highlighting, original); + assertEquals(expected, text); + } + + private static HighlightInfo error(int start, int end, String description) { + return new HighlightInfo(HighlightInfoType.ERROR, start, end, description, null); + } + + private static HighlightInfo warning(int start, int end, String description) { + return new HighlightInfo(HighlightInfoType.WARNING, start, end, description, null); + } +} From 2bcfa96ad8b42f2d02d7441f657c96a0c7fcf3bf Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 16 May 2012 00:50:06 +0400 Subject: [PATCH 49/61] Fix highlighting performance tests; show a difference if failing --- .../advHighlighting/aClassLoader_hl.java | 1731 ++++++ .../advHighlighting/aThinlet_hl.java | 5393 +++++++++++++++++ .../LightAdvHighlightingPerformanceTest.java | 57 +- .../daemon/LightDaemonAnalyzerTestCase.java | 2 +- 4 files changed, 7156 insertions(+), 27 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/aClassLoader_hl.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/aThinlet_hl.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/aClassLoader_hl.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/aClassLoader_hl.java new file mode 100644 index 000000000000..c7f959b6a630 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/aClassLoader_hl.java @@ -0,0 +1,1731 @@ +/* + * @(#)ClassLoader.java 1.162 02/03/19 + * + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +import java.io.InputStream; +import java.io.IOException; +import java.io.StringWriter; +import java.io.PrintWriter; +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Hashtable; +import java.util.Enumeration; +import java.util.Vector; +import java.util.Stack; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.jar.Manifest; +import java.net.URL; +import java.net.MalformedURLException; +import java.security.AccessController; +import java.security.AccessControlContext; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.security.ProtectionDomain; +import java.security.Permissions; +import java.security.CodeSource; +import java.security.Policy; +import sun.misc.URLClassPath; +import sun.misc.Resource; +import sun.misc.CompoundEnumeration; +import sun.misc.ClassFileTransformer; +//import sun.misc.Launcher; +import sun.reflect.Reflection; +import sun.security.action.GetPropertyAction; + +/** + * A class loader is an object that is responsible for loading + * classes. The class ClassLoader is an abstract class. + * Given the name of a class, a class loader should attempt to locate + * or generate data that constitutes a definition for the class. A + * typical strategy is to transform the name into a file + * name and then read a "class file" of that name from a file system. + *

+ * Every Class object contains a + * {@link Class#getClassLoader() reference} to the + * ClassLoader that defined it. + *

+ * Class objects for array classes are not created by class loaders, but + * are created automatically as required by the Java runtime. The class + * loader for an array class, as returned by {@link Class#getClassLoader()} + * is the same as the class loader for its element type; if the element + * type is a primitive type, then the array class has no class loader. + *

+ * Applications implement subclasses of ClassLoader in + * order to extend the manner in which the Java virtual machine + * dynamically loads classes. + *

+ * Class loaders may typically be used by security managers to + * indicate security domains. + *

+ * The ClassLoader class uses a delegation model to + * search for classes and resources. Each instance of + * ClassLoader has an associated parent class loader. + * When called upon to find a class or resource, a + * ClassLoader instance will delegate the search for + * the class or resource to its parent class loader before + * attempting to find the class or resource itself. The virtual + * machine's built-in class loader, called the bootstrap class loader, + * does not itself have a parent but may serve as the parent of a + * ClassLoader instance. + *

+ * Normally, the Java virtual machine loads classes from the local + * file system in a platform-dependent manner. For example, on UNIX + * systems, the virtual machine loads classes from the directory + * defined by the CLASSPATH environment variable. + *

+ * However, some classes may not originate from a file; they may + * originate from other sources, such as the network, or they could + * be constructed by an application. The method + * defineClass converts an array of bytes into an + * instance of class Class. Instances of this newly + * defined class can be created using the newInstance + * method in class Class. + *

+ * The methods and constructors of objects created by a class loader + * may reference other classes. To determine the class(es) referred + * to, the Java virtual machine calls the loadClass + * method of the class loader that originally created the class. + *

+ * For example, an application could create a network class loader + * to download class files from a server. Sample code might look like: + *

+ *   ClassLoader loader = new NetworkClassLoader(host, port);
+ *   Object main = loader.loadClass("Main", true).newInstance();
+ *	  . . .
+ * 
+ *

+ * The network class loader subclass must define the methods + * findClass and loadClassData + * to load a class from the network. Once it + * has downloaded the bytes that make up the class, it should use the + * method defineClass to create a class instance. A + * sample implementation is: + *


+ *     class NetworkClassLoader extends ClassLoader {
+ *         String host;
+ *         int port;
+ *
+ *         public Class findClass(String name) {
+ *             byte[] b = loadClassData(name);
+ *             return defineClass(name, b, 0, b.length);
+ *         }
+ *
+ *         private byte[] loadClassData(String name) {
+ *             // load the class data from the connection
+ *              . . .
+ *         }
+ *     }
+ * 

+ * + * @version 1.162, 03/19/02 + * @see java.lang.Class + * @see java.lang.Class#newInstance() + * @see java.lang.ClassLoader#defineClass(byte[], int, int) + * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean) + * @see java.lang.ClassLoader#resolveClass(java.lang.Class) + * @since JDK1.0 + */ +public abstract class ClassLoader { + + private static native void registerNatives(); + static { + registerNatives(); + } + + /* + * If initialization succeed this is set to true and security checks will + * succeed. Otherwise the object is not initialized and the object is + * useless. + */ + private boolean initialized = false; + + /* + * The parent class loader for delegation. + */ + private ClassLoader parent; + + /* + * Hashtable that maps packages to certs + */ + private Hashtable package2certs = new Hashtable(11); + + /* + * shared among all packages with unsigned classes + */ + java.security.cert.Certificate[] nocerts; + + /* + * The classes loaded by this class loader. The only purpose of this + * table is to keep the classes from being GC'ed until the loader + * is GC'ed. + */ + private Vector classes = new Vector(); + + /* + * The initiating protection domains for all classes + * loaded by this loader. + */ + private Set domains = new HashSet(); + + /* + * Called by the VM to record every loaded class with this loader. + */ + void addClass(Class c) { + classes.addElement(c); + } + + /* + * The packages defined in this class loader. Each package name is + * mapped to its corresponding Package object. + */ + private HashMap packages = new HashMap(); + + /** + * Creates a new class loader using the specified parent class loader + * for delegation. + *

+ * If there is a security manager, its checkCreateClassLoader + * method is called. This may result in a security exception. + * + * @param parent the parent class loader + * + * @throws SecurityException if a security manager exists and its + * checkCreateClassLoader method doesn't allow creation of a + * new class loader. + * @see java.lang.SecurityException + * @see java.lang.SecurityManager#checkCreateClassLoader() + * @since 1.2 + */ + protected ClassLoader(ClassLoader parent) { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkCreateClassLoader(); + } + this.parent = parent; + initialized = true; + } + + /** + * Creates a new class loader using the ClassLoader + * returned by the method getSystemClassLoader() as the + * parent class loader. + *

+ * If there is a security manager, its checkCreateClassLoader + * method is called. This may result in a security exception. + * + * @throws SecurityException + * if a security manager exists and its checkCreateClassLoader + * method doesn't allow creation of a new class loader. + * + * @see java.lang.SecurityException + * @see java.lang.SecurityManager#checkCreateClassLoader() + */ + protected ClassLoader() { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkCreateClassLoader(); + } + this.parent = getSystemClassLoader(); + initialized = true; + } + + /** + * Loads the class with the specified name. This method searches for + * classes in the same manner as the {@link #loadClass(String, boolean)} + * method. It is called by the Java virtual machine to resolve class + * references. Calling this method is equivalent to calling + * loadClass(name, false). + * + * @param name the name of the class + * @return the resulting Class object + * @exception ClassNotFoundException if the class was not found + */ + public Class loadClass(String name) throws ClassNotFoundException + { + return loadClass(name, false); + } + + /** + * Loads the class with the specified name. The default implementation of + * this method searches for classes in the following order:

+ * + *

    + *
  1. Call {@link #findLoadedClass(String)} to check if the class has + * already been loaded.

    + *

  2. Call the loadClass method on the parent class + * loader. If the parent is null the class loader + * built-in to the virtual machine is used, instead.

    + *

  3. Call the {@link #findClass(String)} method to find the class.

    + *

+ * + * If the class was found using the above steps, and the + * resolve flag is true, this method will then call the + * {@link #resolveClass(Class)} method on the resulting class object. + *

+ * From the Java 2 SDK, v1.2, subclasses of ClassLoader are + * encouraged to override + * {@link #findClass(String)}, rather than this method.

+ * + * @param name the name of the class + * @param resolve if true then resolve the class + * @return the resulting Class object + * @exception ClassNotFoundException if the class could not be found + */ + protected synchronized Class loadClass(String name, boolean resolve) + throws ClassNotFoundException + { + // First, check if the class has already been loaded + Class c = findLoadedClass(name); + if (c == null) { + try { + if (parent != null) { + c = parent.loadClass(name, false); + } else { + c = findBootstrapClass0(name); + } + } catch (ClassNotFoundException e) { + // If still not found, then call findClass in order + // to find the class. + c = findClass(name); + } + } + if (resolve) { + resolveClass(c); + } + return c; + } + + /* + * This method is called by the virtual machine to load + * a class. + */ + private synchronized Class loadClassInternal(String name) + throws ClassNotFoundException { + + return loadClass(name); + } + + private void checkPackageAccess(Class cls, ProtectionDomain pd) { + final SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + final String name = cls.getName(); + final int i = name.lastIndexOf('.'); + if (i != -1) { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + sm.checkPackageAccess(name.substring(0, i)); + return null; + } + }, new AccessControlContext(new ProtectionDomain[] {pd})); + } + } + domains.add(pd); + } + + /** + * Finds the specified class. This method should be overridden + * by class loader implementations that follow the new delegation model + * for loading classes, and will be called by the loadClass + * method after checking the parent class loader for the requested class. + * The default implementation throws ClassNotFoundException. + * + * @param name the name of the class + * @return the resulting Class object + * @exception ClassNotFoundException if the class could not be found + * @since 1.2 + */ + protected Class findClass(String name) throws ClassNotFoundException { + throw new ClassNotFoundException(name); + } + + /** + * Converts an array of bytes into an instance of class + * Class. Before the Class can be used it must be + * resolved. This method is deprecated in favor of the version + * that takes the class name as its first argument, and is more + * secure. + * + * @param b the bytes that make up the class data. The bytes in + * positions off through off+len-1 + * should have the format of a valid class file as defined + * by the + * Java + * Virtual Machine Specification. + * @param off the start offset in b of the class data + * @param len the length of the class data + * @return the Class object that was created from the + * specified class data + * @exception ClassFormatError if the data did not contain a valid class + * @exception IndexOutOfBoundsException if either off or + * len is negative, or if + * off+len is greater than b.length. + * @see ClassLoader#loadClass(java.lang.String, boolean) + * @see ClassLoader#resolveClass(java.lang.Class) + * @deprecated Replaced by defineClass(java.lang.String, byte[], int, int) + */ + protected final Class defineClass(byte[] b, int off, int len) + throws ClassFormatError + { + return defineClass(null, b, off, len, null); + } + + /** + * Converts an array of bytes into an instance of class Class. + * Before the Class can be used it must be resolved. + *

+ * This method assigns a default ProtectionDomain to + * the newly defined class. The ProtectionDomain + * contains the set of permissions granted when + * a call to Policy.getPolicy().getPermissions() is made with + * a code source of null,null. The default domain is + * created on the first invocation of defineClass, and + * re-used on subsequent calls. + *

+ * To assign a specific ProtectionDomain to the class, + * use the defineClass method that takes a + * ProtectionDomain as one of its arguments. + * + * @param name the expected name of the class, or null + * if not known, using '.' and not '/' as the separator + * and without a trailing ".class" suffix. + * @param b the bytes that make up the class data. The bytes in + * positions off through off+len-1 + * should have the format of a valid class file as defined + * by the + * Java + * Virtual Machine Specification. + * @param off the start offset in b of the class data + * @param len the length of the class data + * @return the Class object that was created from the + * specified class data + * @exception ClassFormatError if the data did not contain a valid class + * @exception IndexOutOfBoundsException if either off or + * len is negative, or if + * off+len is greater than b.length. + * @exception SecurityException if an attempt is made to add this class + * to a package that contains classes that were signed by + * a different set of certificates than this class (which + * is unsigned), or if the class name begins with "java.". + * + * @see ClassLoader#loadClass(java.lang.String, boolean) + * @see ClassLoader#resolveClass(java.lang.Class) + * @see java.security.ProtectionDomain + * @see java.security.Policy + * @see java.security.CodeSource + * @see java.security.SecureClassLoader + * @since JDK1.1 + */ + protected final Class defineClass(String name, byte[] b, int off, int len) + throws ClassFormatError + { + return defineClass(name, b, off, len, null); + } + + /** + * Converts an array of bytes into an instance of class Class, + * with an optional ProtectionDomain. If the domain is null, + * then a default domain will be assigned to the class as specified + * in the documentation for {@link #defineClass(String,byte[],int,int)}. + * Before the class can be used it must be resolved. + * + *

The first class defined in a package determines the exact set of + * certificates that all subsequent classes defined in that package must + * contain. The set of certificates for a class is obtained from the + * CodeSource within the ProtectionDomain of + * the class. Any classes added to that package must contain + * the same set of certificates or a SecurityException + * will be thrown. Note that if the name argument is + * null, this check is not performed. You should always pass in the + * name of the class you are defining as well as the bytes. This + * ensures that the class you are defining is indeed the class + * you think it is. + * + *

The specified class name cannot begin with "java.", since all + * classes in the java.* packages can only be defined by the bootstrap + * class loader. If the name parameter is not null, it + * must be equal to the name of the class specified by the byte + * array b, otherwise a ClassFormatError is raised. + * + * @param name the expected name of the class, or null + * if not known, using '.' and not '/' as the separator + * and without a trailing ".class" suffix. + * @param b the bytes that make up the class data. The bytes in + * positions off through off+len-1 + * should have the format of a valid class file as defined + * by the + * Java + * Virtual Machine Specification. + * @param off the start offset in b of the class data + * @param len the length of the class data + * @param protectionDomain the ProtectionDomain of the class + * @return the Class object created from the data, + * and optional ProtectionDomain. + * @exception ClassFormatError if the data did not contain a valid class + * @exception IndexOutOfBoundsException if either off or + * len is negative, or if + * off+len is greater than b.length. + * @exception SecurityException if an attempt is made to add this class + * to a package that contains classes that were signed by + * a different set of certificates than this class, or if + * the class name begins with "java.". + */ + protected final Class defineClass(String name, byte[] b, int off, int len, + ProtectionDomain protectionDomain) + throws ClassFormatError + { + check(); + if ((name != null) && name.startsWith("java.")) { + throw new SecurityException("Prohibited package name: " + + name.substring(0, name.lastIndexOf('.'))); + } + if (protectionDomain == null) { + protectionDomain = getDefaultDomain(); + } + + if (name != null) + checkCerts(name, protectionDomain.getCodeSource()); + + Class c = null; + + try + { + c = defineClass0(name, b, off, len, protectionDomain); + } + catch (ClassFormatError cfe) + { + // Class format error - try to transform the bytecode and + // define the class again + // + Object[] transformers = ClassFileTransformer.getTransformers(); + + for (int i=0; transformers != null && i < transformers.length; i++) + { + try + { + // Transform byte code using transformer + byte[] tb = ((ClassFileTransformer) transformers[i]).transform(b, off, len); + c = defineClass0(name, tb, 0, tb.length, protectionDomain); + break; + } + catch (ClassFormatError cfe2) + { + // If ClassFormatError occurs, try next transformer + } + } + + // Rethrow original ClassFormatError if unable to transform + // bytecode to well-formed + // + if (c == null) + throw cfe; + } + + if (protectionDomain.getCodeSource() != null) { + java.security.cert.Certificate certs[] = + protectionDomain.getCodeSource().getCertificates(); + if (certs != null) + setSigners(c, certs); + } + return c; + } + + private synchronized void checkCerts(String name, CodeSource cs) + { + int i = name.lastIndexOf('.'); + String pname = (i == -1) ? "" : name.substring(0,i); + java.security.cert.Certificate[] pcerts = + (java.security.cert.Certificate[]) package2certs.get(pname); + if (pcerts == null) { + // first class in this package gets to define which + // certificates must be the same for all other classes + // in this package + if (cs != null) { + pcerts = cs.getCertificates(); + } + if (pcerts == null) { + if (nocerts == null) + nocerts = new java.security.cert.Certificate[0]; + pcerts = nocerts; + } + package2certs.put(pname, pcerts); + } else { + java.security.cert.Certificate[] certs = null; + if (cs != null) { + certs = cs.getCertificates(); + } + + if (!compareCerts(pcerts,certs)) { + throw new SecurityException("class \""+ name+ + "\"'s signer information does not match signer information of other classes in the same package"); + } + } + } + + /** + * check to make sure the certs for the new class (certs) are + * the same as the certs for the first class inserted + * in the package (pcerts) + */ + private boolean compareCerts(java.security.cert.Certificate[] pcerts, + java.security.cert.Certificate[] certs) + { + // certs can be null, indicating no certs. + if ((certs == null) || (certs.length == 0)) { + return pcerts.length == 0; + } + + // the length must be the same at this point + if (certs.length != pcerts.length) + return false; + + // go through and make sure all the certs in one array + // are in the other and vice-versa. + boolean match; + for (int i=0; i < certs.length; i++) { + match = false; + for (int j=0; j < pcerts.length; j++) { + if (certs[i].equals(pcerts[j])) { + match = true; + break; + } + } + if (!match) return false; + } + + // now do the same for pcerts + for (int i=0; i < pcerts.length; i++) { + match = false; + for (int j=0; j < certs.length; j++) { + if (pcerts[i].equals(certs[j])) { + match = true; + break; + } + } + if (!match) return false; + } + + return true; + } + + /** + * Links the specified class. + * This (misleadingly named) method may be used by a class loader to + * link a class. If the class c has already been linked, + * then this method simply returns. Otherwise, the class is linked + * as described in the "Execution" chapter of the Java Language + * Specification. + * + * @param c the class to link + * @exception NullPointerException if c is null. + * @see java.lang.ClassLoader#defineClass(java.lang.String,byte[],int,int) + */ + protected final void resolveClass(Class c) { + check(); + resolveClass0(c); + } + + /** + * Finds a class with the specified name, loading it if necessary.

+ * + * Prior to the Java 2 SDK, this method loads a class from the local file + * system in a platform-dependent manner, and returns a class object + * that has no associated class loader.

+ * + * Since the Java 2 SDK v1.2, this method loads the class through the + * system class loader(see {@link #getSystemClassLoader()}). Class objects + * returned might have ClassLoaders associated with them. + * Subclasses of ClassLoader need not usually call this + * method, because most class loaders need to override just {@link + * #findClass(String)}.

+ * + * @param name the name of the class that is to be found + * @return the Class object for the specified + * name + * @exception ClassNotFoundException if the class could not be found + * @see #ClassLoader(ClassLoader) + * @see #getParent() + */ + protected final Class findSystemClass(String name) + throws ClassNotFoundException + { + check(); + ClassLoader system = getSystemClassLoader(); + if (system == null) { + return findBootstrapClass(name); + } + return system.loadClass(name); + } + + /** + * Returns the parent class loader for delegation. Some implementations + * may use null to represent the bootstrap class + * loader. This method will return null in such + * implementations if this class loader's parent is the bootstrap + * class loader. + *

+ * If a security manager is present, and the caller's class loader is + * not null and is not an ancestor of this class loader, then + * this method calls the security manager's checkPermission + * method with a RuntimePermission("getClassLoader") + * permission to ensure it's ok to access the parent class loader. + * If not, a SecurityException will be thrown. + * + * @return the parent ClassLoader + * @throws SecurityException + * if a security manager exists and its + * checkPermission method doesn't allow + * access to this class loader's parent class loader. + * + * @see SecurityManager#checkPermission + * @see java.lang.RuntimePermission + * + * @since 1.2 + */ + public final ClassLoader getParent() { + if (parent == null) + return null; + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + ClassLoader ccl = getCallerClassLoader(); + if (ccl != null && !isAncestor(ccl)) { + sm.checkPermission(getGetClassLoaderPerm()); + } + } + return parent; + } + + /** + * Sets the signers of a class. This should be called after defining a + * class. + * + * @param c the Class object + * @param signers the signers for the class + * @since JDK1.1 + */ + protected final void setSigners(Class c, Object[] signers) { + check(); + c.setSigners(signers); + } + + private Class findBootstrapClass0(String name) + throws ClassNotFoundException { + check(); + return findBootstrapClass(name); + } + + private native Class defineClass0(String name, byte[] b, int off, int len, + ProtectionDomain pd); + private native void resolveClass0(Class c); + private native Class findBootstrapClass(String name) + throws ClassNotFoundException; + + /* + * Check to make sure the class loader has been initialized. + */ + private void check() { + if (!initialized) { + throw new SecurityException("ClassLoader object not initialized"); + } + } + + /** + * Finds the class with the given name if it had been previously loaded + * through this class loader. + * + * @param name the class name + * @return the Class object, or null if + * the class has not been loaded + * @since JDK1.1 + */ + protected native final Class findLoadedClass(String name); + + /** + * Finds the resource with the given name. A resource is some data + * (images, audio, text, etc) that can be accessed by class code in a way + * that is independent of the location of the code.

+ * + * The name of a resource is a "/"-separated path name that identifies + * the resource.

+ * + * This method will first search the parent class loader for the resource; + * if the parent is null the path of the class loader + * built-in to the virtual machine is searched. That failing, this method + * will call findResource to find the resource.

+ * + * @param name resource name + * @return a URL for reading the resource, or null if + * the resource could not be found or the caller doesn't have + * adequate privileges to get the resource. + * @since JDK1.1 + * @see #findResource(String) + */ + public URL getResource(String name) { + URL url; + if (parent != null) { + url = parent.getResource(name); + } else { + url = getBootstrapResource(name); + } + if (url == null) { + url = findResource(name); + } + return url; + } + + /** + * Finds all the resources with the given name. A resource is some data + * (images, audio, text, etc) that can be accessed by class code in a way + * that is independent of the location of the code.

+ * + * The name of a resource is a "/"-separated path name that identifies the + * resource.

+ * + * The search order is described in the documentation for {@link + * #getResource(String)}.

+ * + * @param name resource name + * @return an enumeration of URL to the resource. If no resources could + * be found, the enumeration will be empty. Resources that the + * doesn't have access to will not be in the enumeration. + * @throws IOException if I/O errors occur + * @since 1.2 + * @see #getResource + * @see #findResources + */ + public final Enumeration getResources(String name) throws IOException { + Enumeration[] tmp = new Enumeration[2]; + if (parent != null) { + tmp[0] = parent.getResources(name); + } else { + tmp[0] = getBootstrapResources(name); + } + tmp[1] = findResources(name); + + return new CompoundEnumeration(tmp); + } + + /** + * Returns an Enumeration of URLs representing all the resources with + * the given name. Class loader implementations should override this + * method to specify where to load resources from. + * + * @param name the resource name + * @return an Enumeration of URLs for the resources + * @throws IOException if I/O errors occur + * @since 1.2 + */ + protected Enumeration findResources(String name) throws IOException { + return new CompoundEnumeration(new Enumeration[0]); + } + + /** + * Finds the resource with the given name. Class loader + * implementations should override this method to specify where to + * find resources. + * + * @param name the resource name + * @return a URL for reading the resource, or null + * if the resource could not be found + * @since 1.2 + */ + protected URL findResource(String name) { + return null; + } + + /** + * Find a resource of the specified name from the search path used to load + * classes.

+ * + * In JDK1.1, the search path used is that of the virtual machine's + * built-in class loader.

+ * + * Since the Java 2 SDK v1.2, this method locates the resource through the system class + * loader (see {@link #getSystemClassLoader()}). + * + * @param name the resource name + * @return a URL for reading the resource, or null if + * the resource could not be found + * @since JDK1.1 + */ + public static URL getSystemResource(String name) { + ClassLoader system = getSystemClassLoader(); + if (system == null) { + return getBootstrapResource(name); + } + return system.getResource(name); + } + + /** + * Find resources from the VM's built-in classloader. + */ + private static URL getBootstrapResource(String name) { + URLClassPath ucp = getBootstrapClassPath(); + Resource res = ucp.getResource(name); + return res != null ? res.getURL() : null; + } + + /** + * Finds all resources of the specified name from the search path used to + * load classes. The resources thus found are returned as an + * Enumeration of URL objects.

+ * + * The search order is described in the documentation for {@link + * #getSystemResource(String)}.

+ * + * @param name the resource name + * @return an enumeration of resource URLs + * @throws IOException if I/O errors occur + * @since 1.2 + */ + public static Enumeration getSystemResources(String name) + throws IOException + { + ClassLoader system = getSystemClassLoader(); + if (system == null) { + return getBootstrapResources(name); + } + return system.getResources(name); + } + + /** + * Find resources from the VM's built-in classloader. + */ + private static Enumeration getBootstrapResources(String name) + throws IOException + { + final Enumeration e = getBootstrapClassPath().getResources(name); + return new Enumeration () { + public Object nextElement() { + return ((Resource)e.nextElement()).getURL(); + } + public boolean hasMoreElements() { + return e.hasMoreElements(); + } + }; + } + + /* + * Returns the URLClassPath that is used for finding system resources. + */ + static URLClassPath getBootstrapClassPath() { + if (bootstrapClassPath == null) { + bootstrapClassPath = sun.misc.Launcher.getBootstrapClassPath(); + } + return bootstrapClassPath; + } + + private static URLClassPath bootstrapClassPath; + + /** + * Returns an input stream for reading the specified resource. + * + * The search order is described in the documentation for {@link + * #getResource(String)}.

+ * + * @param name the resource name + * @return an input stream for reading the resource, or null + * if the resource could not be found + * @since JDK1.1 + */ + public InputStream getResourceAsStream(String name) { + URL url = getResource(name); + try { + return url != null ? url.openStream() : null; + } catch (IOException e) { + return null; + } + } + + /** + * Open for reading, a resource of the specified name from the search path + * used to load classes.

+ * + * The search order is described in the documentation for {@link + * #getSystemResource(String)}.

+ * + * @param name the resource name + * @return an input stream for reading the resource, or null + * if the resource could not be found + * @since JDK1.1 + */ + public static InputStream getSystemResourceAsStream(String name) { + URL url = getSystemResource(name); + try { + return url != null ? url.openStream() : null; + } catch (IOException e) { + return null; + } + } + + /** + * Returns the system class loader for delegation. This is the default + * delegation parent for new ClassLoader instances, and + * is typically the class loader used to start the application. + *

+ * This method is first invoked early in the runtime's startup + * sequence, at which point it creates the system class loader + * and sets it as the context class loader of the invoking + * Thread. + *

+ * The default system class loader is an implementation-dependent + * instance of this class. + *

+ * If the system property java.system.class.loader is + * defined when this method is first invoked then the value of that + * property is taken to be the name of a class that will be returned as + * the system class loader. The class is loaded using the default system + * class loader and must define a public constructor that takes a single + * parameter of type ClassLoader which is used + * as the delegation parent. An instance is then created using this + * constructor with the default system class loader as the parameter. + * The resulting class loader is defined to be the system class loader. + *

+ * If a security manager is present, and the caller's class loader is + * not null and the caller's class loader is not the same as or an ancestor of + * the system class loader, then + * this method calls the security manager's checkPermission + * method with a RuntimePermission("getClassLoader") + * permission to ensure it's ok to access the system class loader. + * If not, a SecurityException will be thrown. + * + * @return the system ClassLoader for delegation, or + * null if none + * @throws SecurityException + * if a security manager exists and its + * checkPermission method doesn't allow + * access to the system class loader. + * @throws IllegalStateException + * if invoked recursively during the construction + * of the class loader specified by the + * java.system.class.loader property. + * @throws Error + * if the system property java.system.class.loader + * is defined but the named class could not be loaded, the + * provider class does not define the required constructor, or an + * exception is thrown by that constructor when it is invoked. The + * underlying cause of the error can be retrieved via the + * {@link Throwable#getCause()} method. + * @see SecurityManager#checkPermission + * @see java.lang.RuntimePermission + * @revised 1.4 + */ + public static ClassLoader getSystemClassLoader() { + initSystemClassLoader(); + if (scl == null) { + return null; + } + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + ClassLoader ccl = getCallerClassLoader(); + if (ccl != null && ccl != scl && !scl.isAncestor(ccl)) { + sm.checkPermission(getGetClassLoaderPerm()); + } + } + return scl; + } + + private static synchronized void initSystemClassLoader() { + if (!sclSet) { + if (scl != null) + throw new IllegalStateException("recursive call"); + sun.misc.Launcher l = sun.misc.Launcher.getLauncher(); + if (l != null) { + Throwable oops = null; + scl = l.getClassLoader(); + try { + PrivilegedExceptionAction a; + a = new SystemClassLoaderAction(scl); + scl = (ClassLoader) AccessController.doPrivileged(a); + } catch (PrivilegedActionException pae) { + oops = pae.getCause(); + if (oops instanceof InvocationTargetException) { + oops = oops.getCause(); + } + } + if (oops != null) { + if (oops instanceof Error) { + throw (Error) oops; + } else { + // wrap the exception + throw new Error(oops); + } + } + } + sclSet = true; + } + } + + // Returns true if the specified class loader can be found + // in this class loader's delegation chain. + boolean isAncestor(ClassLoader cl) { + ClassLoader acl = this; + do { + acl = acl.parent; + if (cl == acl) { + return true; + } + } while (acl != null); + return false; + } + + // Returns the caller's class loader, or null if none. + // NOTE this must always be called when there is exactly one + // intervening frame from the core libraries on the stack between + // this method's invocation and the desired caller. + static ClassLoader getCallerClassLoader() { + // NOTE use of more generic Reflection.getCallerClass() + Class caller = Reflection.getCallerClass(3); + // This can be null if the VM is requesting it + if (caller == null) { + return null; + } + // Circumvent security check since this is package-private + return caller.getClassLoader0(); + } + + // The class loader for the system + private static ClassLoader scl; + + // Set to true once the system class loader has been set + private static boolean sclSet; + + // Permission to access system or parent class loader + private static RuntimePermission getClassLoaderPerm = null; + + static RuntimePermission getGetClassLoaderPerm() + { + if (getClassLoaderPerm == null) + getClassLoaderPerm = new RuntimePermission("getClassLoader"); + return getClassLoaderPerm; + } + + /** + * Defines a package by name in this ClassLoader. This allows class + * loaders to define the packages for their classes. Packages must be + * created before the class is defined, and package names must be + * unique within a class loader and cannot be redefined or changed + * once created. + * + * @param name the package name + * @param specTitle the specification title + * @param specVersion the specification version + * @param specVendor the specification vendor + * @param implTitle the implementation title + * @param implVersion the implementation version + * @param implVendor the implementation vendor + * @param sealBase If not null, then this package is sealed with + * respect to the given code source URL. Otherwise, + * the package is not sealed. + * @return the newly defined Package object + * @exception IllegalArgumentException if package name duplicates an + * existing package either in this class loader or one of + * its ancestors + * @since 1.2 + */ + protected Package definePackage(String name, String specTitle, + String specVersion, String specVendor, + String implTitle, String implVersion, + String implVendor, URL sealBase) + throws IllegalArgumentException + { + synchronized (packages) { + Package pkg = getPackage(name); + if (pkg != null) { + throw new IllegalArgumentException(name); + } + pkg = new Package(name, specTitle, specVersion, specVendor, + implTitle, implVersion, implVendor, + sealBase); + packages.put(name, pkg); + return pkg; + } + } + + /** + * Returns a Package that has been defined by this class loader or any + * of its ancestors. + * + * @param name the package name + * @return the Package corresponding to the given name, or null if not + * found + * @since 1.2 + */ + protected Package getPackage(String name) { + synchronized (packages) { + Package pkg = (Package)packages.get(name); + if (pkg == null) { + if (parent != null) { + pkg = parent.getPackage(name); + } else { + pkg = Package.getSystemPackage(name); + } + if (pkg != null) { + packages.put(name, pkg); + } + } + return pkg; + } + } + + /** + * Returns all of the Packages defined by this class loader and its + * ancestors. + * + * @return the array of Package objects defined by this + * ClassLoader + * @since 1.2 + */ + protected Package[] getPackages() { + Map map; + synchronized (packages) { + map = (Map)packages.clone(); + } + Package[] pkgs; + if (parent != null) { + pkgs = parent.getPackages(); + } else { + pkgs = Package.getSystemPackages(); + } + if (pkgs != null) { + for (int i = 0; i < pkgs.length; i++) { + String pkgName = pkgs[i].getName(); + if (map.get(pkgName) == null) { + map.put(pkgName, pkgs[i]); + } + } + } + return (Package[])map.values().toArray(new Package[map.size()]); + } + + /** + * Returns the absolute path name of a native library. The VM + * invokes this method to locate the native libraries that belong + * to classes loaded with this class loader. If this method returns + * null, the VM searches the library along the path + * specified as the java.library.path property. + * + * @param libname the library name + * @return the absolute path of the native library + * @see java.lang.System#loadLibrary(java.lang.String) + * @see java.lang.System#mapLibraryName(java.lang.String) + * @since 1.2 + */ + protected String findLibrary(String libname) { + return null; + } + + /** + * The inner class NativeLibrary denotes a loaded native library + * instance. Every classloader contains a vector of loaded native + * libraries in the private field nativeLibraries. + * The native libraries loaded into the system are entered into + * the systemNativeLibraries vector. + * + * Every native library reuqires a particular version of JNI. This + * is denoted by the private jniVersion field. This field is set + * by the VM when it loads the library, and used by the VM to pass + * the correct version of JNI to the native methods. + * + * @version 1.162, 03/19/02 + * @see java.lang.ClassLoader + * @since 1.2 + */ + static class NativeLibrary { + /* opaque handle to native library, used in native code. */ + long handle; + /* the version of JNI environment the native library requires. */ + private int jniVersion; + /* the class from which the library is loaded, also indicates + the loader this native library belongs. */ + private Class fromClass; + /* the canonicalized name of the native library. */ + String name; + + native void load(String name); + native long find(String name); + native void unload(); + + public NativeLibrary(Class fromClass, String name) { + this.name = name; + this.fromClass = fromClass; + } + + protected void finalize() { + synchronized (loadedLibraryNames) { + if (fromClass.getClassLoader() != null && handle != 0) { + /* remove the native library name */ + int size = loadedLibraryNames.size(); + for (int i = 0; i < size; i++) { + if (name.equals(loadedLibraryNames.elementAt(i))) { + loadedLibraryNames.removeElementAt(i); + break; + } + } + /* unload the library. */ + ClassLoader.nativeLibraryContext.push(this); + try { + unload(); + } finally { + ClassLoader.nativeLibraryContext.pop(); + } + } + } + } + /* Called in the VM to determine the context class in + JNI_Load/JNI_Unload */ + static Class getFromClass() { + return ((NativeLibrary) + (ClassLoader.nativeLibraryContext.peek())).fromClass; + } + } + + /* the "default" domain. Set as the default ProtectionDomain + * on newly created classses. + */ + private ProtectionDomain defaultDomain = null; + + /* + * returns (and initializes) the default domain. + */ + + private synchronized ProtectionDomain getDefaultDomain() { + if (defaultDomain == null) { + CodeSource cs = new CodeSource(null, null); + defaultDomain = new ProtectionDomain(cs, null, this, null); + } + return defaultDomain; + } + + /* All native library names we've loaded. */ + private static Vector loadedLibraryNames = new Vector(); + /* Native libraries belonging to system classes. */ + private static Vector systemNativeLibraries = new Vector(); + /* Native libraries associated with the class loader. */ + private Vector nativeLibraries = new Vector(); + + /* native libraries being loaded/unloaded. */ + private static Stack nativeLibraryContext = new Stack(); + + /* The paths searched for libraries */ + static private String usr_paths[]; + static private String sys_paths[]; + + private static String[] initializePath(String propname) { + String ldpath = System.getProperty(propname, ""); + String ps = File.pathSeparator; + int ldlen = ldpath.length(); + int i, j, n; + // Count the separators in the path + i = ldpath.indexOf(ps); + n = 0; + while (i >= 0) { + n++; + i = ldpath.indexOf(ps, i+1); + } + + // allocate the array of paths - n :'s = n + 1 path elements + String[] paths = new String[n + 1]; + + // Fill the array with paths from the ldpath + n = i = 0; + j = ldpath.indexOf(ps); + while (j >= 0) { + if (j - i > 0) { + paths[n++] = ldpath.substring(i, j); + } else if (j - i == 0) { + paths[n++] = "."; + } + i = j + 1; + j = ldpath.indexOf(ps, i); + } + paths[n] = ldpath.substring(i, ldlen); + return paths; + } + + + /* Called in the java.lang.Runtime class to implement load + * and loadLibrary. + */ + static void loadLibrary(Class fromClass, String name, + boolean isAbsolute) { + ClassLoader loader = + (fromClass == null) ? null : fromClass.getClassLoader(); + if (sys_paths == null) { + usr_paths = initializePath("java.library.path"); + sys_paths = initializePath("sun.boot.library.path"); + } + if (isAbsolute) { + if (loadLibrary0(fromClass, new File(name))) { + return; + } + throw new UnsatisfiedLinkError("Can't load library: " + name); + } + if (loader != null) { + String libfilename = loader.findLibrary(name); + if (libfilename != null) { + File libfile = new File(libfilename); + if (!libfile.isAbsolute()) { + throw new UnsatisfiedLinkError( + "ClassLoader.findLibrary failed to return an absolute path: " + libfilename); + } + if (loadLibrary0(fromClass, libfile)) { + return; + } + throw new UnsatisfiedLinkError ("Can't load " + libfilename); + } + } + for (int i = 0 ; i < sys_paths.length ; i++) { + File libfile = new File(sys_paths[i], System.mapLibraryName(name)); + if (loadLibrary0(fromClass, libfile)) { + return; + } + } + if (loader != null) { + for (int i = 0 ; i < usr_paths.length ; i++) { + File libfile = new File(usr_paths[i], + System.mapLibraryName(name)); + if (loadLibrary0(fromClass, libfile)) { + return; + } + } + } + // Oops, it failed + throw new UnsatisfiedLinkError("no " + name + " in java.library.path"); + } + + private static boolean loadLibrary0(Class fromClass, final File file) { + Boolean exists = (Boolean) + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + return new Boolean(file.exists()); + } + }); + if (!exists.booleanValue()) { + return false; + } + String name; + try { + name = file.getCanonicalPath(); + } catch (IOException e) { + return false; + } + ClassLoader loader = + (fromClass == null) ? null : fromClass.getClassLoader(); + Vector libs = + loader != null ? loader.nativeLibraries : systemNativeLibraries; + synchronized (libs) { + int size = libs.size(); + for (int i = 0; i < size; i++) { + NativeLibrary lib = (NativeLibrary)libs.elementAt(i); + if (name.equals(lib.name)) { + return true; + } + } + + synchronized (loadedLibraryNames) { + if (loadedLibraryNames.contains(name)) { + throw new UnsatisfiedLinkError + ("Native Library " + + name + + " already loaded in another classloader"); + } + /* If the library is being loaded (must be by + * the same thread, because Runtime.load and + * Runtime.loadLibrary are synchronous). The + * reason is can occur is that the JNI_OnLoad + * function can cause another loadLibrary call. + * + * Thus we can use a static stack to hold the list + * of libraries we are loading. + * + * If there is a pending load operation for the + * library, we immediately return success; otherwise, + * we raise UnsatisfiedLinkError. + */ + int n = nativeLibraryContext.size(); + for (int i = 0; i < n; i++) { + NativeLibrary lib = (NativeLibrary) + nativeLibraryContext.elementAt(i); + if (name.equals(lib.name)) { + if (loader == lib.fromClass.getClassLoader()) { + return true; + } else { + throw new UnsatisfiedLinkError + ("Native Library " + + name + + " is being loaded in another classloader"); + } + } + } + NativeLibrary lib = new NativeLibrary(fromClass, name); + nativeLibraryContext.push(lib); + try { + lib.load(name); + } finally { + nativeLibraryContext.pop(); + } + if (lib.handle != 0) { + loadedLibraryNames.addElement(name); + libs.addElement(lib); + return true; + } + return false; + } + } + } + + /* Called in the VM class linking code. */ + static long findNative(ClassLoader loader, String name) { + Vector libs = + loader != null ? loader.nativeLibraries : systemNativeLibraries; + synchronized (libs) { + int size = libs.size(); + for (int i = 0; i < size; i++) { + NativeLibrary lib = (NativeLibrary)libs.elementAt(i); + long entry = lib.find(name); + if (entry != 0) + return entry; + } + } + return 0; + } + + /* + * The default toggle for assertion checking. + */ + private boolean defaultAssertionStatus = false; + + /* + * Maps String packageName to Boolean package default assertion status + * Note that the default package is placed under a null map key. + * If this field is null then we are delegating assertion status queries + * to the VM, i.e., none of this ClassLoader's assertion status + * modification methods have been called. + */ + private Map packageAssertionStatus = null; + + /* + * Maps String fullyQualifiedClassName to Boolean assertionStatus + * If this field is null then we are delegating assertion status queries + * to the VM, i.e., none of this ClassLoader's assertion status + * modification methods have been called. + */ + Map classAssertionStatus = null; + + /** + * Sets the default assertion status for this class loader. This setting + * determines whether classes loaded by this class loader and initialized + * in the future will have assertions enabled or disabled by default. + * This setting may be overridden on a per-package or per-class basis by + * invoking {@link #setPackageAssertionStatus(String,boolean)} or {@link + * #setClassAssertionStatus(String,boolean)}. + * + * @param enabled true if classes loaded by this class loader + * will henceforth have assertions enabled by default, + * false if they will have assertions disabled by default. + * @since 1.4 + */ + public synchronized void setDefaultAssertionStatus(boolean enabled) { + if (classAssertionStatus == null) + initializeJavaAssertionMaps(); + + defaultAssertionStatus = enabled; + } + + /** + * Sets the package default assertion status for the named + * package. The package default assertion status determines the + * assertion status for classes initialized in the future that belong + * to the named package or any of its "subpackages." + *

+ * A subpackage of a package named p is any package whose name + * begins with "p." . For example, javax.swing.text is + * a subpackage of javax.swing, and both java.util + * and java.lang.reflect are subpackages of java. + *

+ * In the event that multiple package defaults apply to a given + * class, the package default pertaining to the most specific package + * takes precedence over the others. For example, if + * javax.lang and javax.lang.reflect both have + * package defaults associated with them, the latter package + * default applies to classes in javax.lang.reflect. + *

+ * Package defaults take precedence over the class loader's default + * assertion status, and may be overridden on a per-class basis by + * invoking {@link #setClassAssertionStatus(String,boolean)}. + * + * @param packageName the name of the package whose package default + * assertion status is to be set. A null value + * indicates the unnamed package that is "current" + * (JLS 7.4.2). + * @param enabled true if classes loaded by this classloader + * and belonging to the named package or any of its subpackages + * will have assertions enabled by default, false if they + * will have assertions disabled by default. + * @since 1.4 + */ + public synchronized void setPackageAssertionStatus(String packageName, + boolean enabled) + { + if (packageAssertionStatus == null) + initializeJavaAssertionMaps(); + + packageAssertionStatus.put(packageName, Boolean.valueOf(enabled)); + } + + /** + * Sets the desired assertion status for the named top-level class in + * this class loader and any nested classes contained therein. + * This setting takes precedence over the class loader's default + * assertion status, and over any applicable per-package default. + * This method has no effect if the named class has already been + * initialized. (Once a class is initialized, its assertion status cannot + * change.) + *

+ * If the named class is not a top-level class, this call will have no + * effect on the actual assertion status of any class, and its return + * value is undefined. + * + * @param className the fully qualified class name of the top-level class + * whose assertion status is to be set. + * @param enabled true if the named class is to have assertions + * enabled when (and if) it is initialized, false if the + * class is to have assertions disabled. + * @since 1.4 + */ + public synchronized void setClassAssertionStatus(String className, + boolean enabled) + { + if (classAssertionStatus == null) + initializeJavaAssertionMaps(); + + classAssertionStatus.put(className, Boolean.valueOf(enabled)); + } + + /** + * Sets the default assertion status for this class loader to + * false and discards any package defaults or class assertion + * status settings associated with the class loader. This call is + * provided so that class loaders can be made to ignore any command line + * or persistent assertion status settings and "start with a clean slate." + * + * @since 1.4 + */ + public synchronized void clearAssertionStatus() { + /* + * Whether or not "Java assertion maps" are initialized, set + * them to empty maps, effectively ignoring any present settings. + */ + classAssertionStatus = new HashMap(); + packageAssertionStatus = new HashMap(); + + defaultAssertionStatus = false; + } + + /** + * Returns the assertion status that would be assigned to the specified + * class if it were to be initialized at the time this method is invoked. + * If the named class has had its assertion status set, the most recent + * setting will be returned; otherwise, if any package default assertion + * status pertains to this class, the most recent setting for the most + * specific pertinent package default assertion status is returned; + * otherwise, this class loader's default assertion status is returned. + * + * @param className the fully qualified class name of the class whose + * desired assertion status is being queried. + * @return the desired assertion status of the specified class. + * @see #setClassAssertionStatus(String,boolean) + * @see #setPackageAssertionStatus(String,boolean) + * @see #setDefaultAssertionStatus(boolean) + * @since 1.4 + */ + synchronized boolean desiredAssertionStatus(String className) { + Boolean result; + + // assert classAssertionStatus != null; + // assert packageAssertionStatus != null; + + // Check for a class entry + result = (Boolean)classAssertionStatus.get(className); + if (result != null) + return result.booleanValue(); + + // Check for most specific package entry + int dotIndex = className.lastIndexOf("."); + if (dotIndex < 0) { // default package + result = (Boolean)packageAssertionStatus.get(null); + if (result != null) + return result.booleanValue(); + } + while(dotIndex > 0) { + className = className.substring(0, dotIndex); + result = (Boolean)packageAssertionStatus.get(className); + if (result != null) + return result.booleanValue(); + dotIndex = className.lastIndexOf(".", dotIndex-1); + } + + // Return the classloader default + return defaultAssertionStatus; + } + + // Set up the assertions with information provided by the VM. + private void initializeJavaAssertionMaps() { + // assert Thread.holdsLock(this); + + classAssertionStatus = new HashMap(); + packageAssertionStatus = new HashMap(); + AssertionStatusDirectives directives = retrieveDirectives(); + + for(int i=0; iclasses.length; i++) + classAssertionStatus.put(directives.classes[i], + Boolean.valueOf(directives.classEnabled[i])); + + for(int i=0; ipackages.length; i++) + packageAssertionStatus.put(directives.packages[i], + Boolean.valueOf(directives.packageEnabled[i])); + + defaultAssertionStatus = directives.deflt; + } + + // Retrieves the assertion directives from the VM. + private static native AssertionStatusDirectives retrieveDirectives(); + +} + + +class SystemClassLoaderAction implements PrivilegedExceptionAction { + private ClassLoader parent; + + SystemClassLoaderAction(ClassLoader parent) { + this.parent = parent; + } + + public Object run() throws Exception { + ClassLoader sys; + Constructor ctor; + Class c; + Class cp[] = { ClassLoader.class }; + Object params[] = { parent }; + + String cls = System.getProperty("java.system.class.loader"); + if (cls == null) { + return parent; + } + + c = Class.forName(cls, true, parent); + ctor = c.getDeclaredConstructor(cp); + sys = (ClassLoader) ctor.newInstance(params); + Thread.currentThread().setContextClassLoader(sys); + return sys; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/aThinlet_hl.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/aThinlet_hl.java new file mode 100644 index 000000000000..8aca05ad4bfb --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/aThinlet_hl.java @@ -0,0 +1,5393 @@ +/* + Thinlet GUI toolkit - www.thinlet.com + Copyright (C) 2002 Robert Bajzat (robert.bajzat@thinlet.com) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +//package thinlet; //java +//midp package thinlet.midp; + +import java.applet.*; //java +import java.awt.*; //java +import java.awt.datatransfer.*; //java +import java.awt.image.*; //java +import java.awt.event.*; //java +import java.lang.reflect.*; //java +import java.io.*; +import java.net.*; //java +import java.util.*; +//midp import javax.microedition.lcdui.*; +//midp import javax.microedition.midlet.*; + +/** + * + */ +public class Thinlet extends Container //java + implements Runnable, Serializable { //java +//midp public class Thinlet extends Canvas implements CommandListener { + + //midp private static final Boolean TRUE = new Boolean(true); + //midp private static final Boolean FALSE = new Boolean(false); + + //midp private transient Font font; + private transient Color c_bg; + private transient Color c_text; + private transient Color c_textbg; + private transient Color c_border; + private transient Color c_disable; + private transient Color c_hover; + private transient Color c_press; + private transient Color c_focus; + private transient Color c_select; + private transient Color c_ctrl = null; //java + //midp private transient Color c_ctrl; + private transient int block; + private transient Image gradient; //java + { + setFont(new Font("SansSerif", Font.PLAIN, 12)); //java + //midp setFont(Font.getDefaultFont()); + setColors(0xe6e6e6, 0x000000, 0xffffff, + 0x909090, 0xb0b0b0, 0xededed, 0xb9b9b9, 0x89899a, 0xc5c5dd); // f99237 eac16a // e68b2c ffc73c + } + + private transient Thread timer; + private transient long watchdelay; + private transient long watch; + private transient String clipboard; + + private Object content = createImpl("desktop"); + private transient Object mouseinside; + private transient Object insidepart; + private transient Object mousepressed; + private transient Object pressedpart; + private transient int referencex, referencey; + private transient int mousex, mousey; + private transient Object focusowner; + private transient boolean focusinside; //midp { focusinside = true; } + private transient Object popupowner; + private transient Object tooltipowner; + //private transient int pressedkey; + + //java> + private static final int DRAG_ENTERED = AWTEvent.RESERVED_ID_MAX + 1; + private static final int DRAG_EXITED = AWTEvent.RESERVED_ID_MAX + 2; + + private static long WHEEL_MASK = 0; + private static int MOUSE_WHEEL = 0; + private static Method wheelrotation = null; + static { + try { + WHEEL_MASK = AWTEvent.class.getField("MOUSE_WHEEL_EVENT_MASK").getLong(null); + MOUSE_WHEEL = MouseEvent.class.getField("MOUSE_WHEEL").getInt(null); + } catch (Exception exc) { /* not 1.4 */ } + } + { + if (MOUSE_WHEEL != 0) { // disable global focus-manager for this component in 1.4 + try { + getClass().getMethod("setFocusTraversalKeysEnabled", new Class[] { Boolean.TYPE }). + invoke(this, new Object[] { Boolean.FALSE }); + } catch (Exception exc) { /* never */ } + } + enableEvents(AWTEvent.COMPONENT_EVENT_MASK | + AWTEvent.FOCUS_EVENT_MASK | AWTEvent.KEY_EVENT_MASK | + AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK | WHEEL_MASK); + } + //Color(background); c_text = new Color(text); + c_textbg = new Color(textbackground); c_border = new Color(border); + c_disable = new Color(disable); c_hover = new Color(hover); + c_press = new Color(press); c_focus = new Color(focus); + c_select = new Color(select); + //midp c_ctrl = c_hover; + //java> + int[] pix = new int[block * block]; + int r1 = c_bg.getRed(); int r2 = c_press.getRed(); + int g1 = c_bg.getGreen(); int g2 = c_press.getGreen(); + int b1 = c_bg.getBlue(); int b2 = c_press.getBlue(); + for (int i = 0; i < block; i++) { + int r = r1 - (r1 - r2) * i / block; + int g = g1 - (g1 - g2) * i / block; + int b = b1 - (b1 - b2) * i / block; + int color = (255 << 24) | (r << 16) | (g << 8) | b; + for (int j = 0; j < block; j++) { + pix[i * block + j] = color; + //pix[j * block + i] = color; + } + } + gradient = createImage(new MemoryImageSource(block, block, pix, 0, block)); + //Font font) { + block = getFontMetrics(font).getHeight(); //java + super.setFont(font); //java + //midp block = font.getHeight(); + //midp this.font = font; + } + + /** + * + */ + private void doLayout(Object component) { + String classname = getClass(component); + if ("combobox" == classname) { + if (getBoolean(component, "editable", true)) { + Image icon = getIcon(component, "icon", null); + layoutField(component, block, false, + (icon != null) ? icon.getWidth(this) : 0); + } // set editable -> validate (overwrite textfield repaint) + else { + int selected = getInteger(component, "selected", -1); + if (selected != -1) { + Object choice = getItem(component, "choice", selected); + set(component, "text", get(choice, "text")); + set(component, "icon", get(choice, "icon")); + } + } + } + else if (("textfield" == classname) || ("passwordfield" == classname)) { + layoutField(component, 0, ("passwordfield" == classname), 0); + } + else if ("textarea" == classname) { + String text = getString(component, "text", ""); + int start = getInteger(component, "start", 0); + if (start > text.length()) { setInteger(component, "start", start = text.length(), 0); } + int end = getInteger(component, "end", 0); + if (end > text.length()) { setInteger(component, "end", end = text.length(), 0); } + int caretx = 0; int carety = 0; + FontMetrics fm = getFontMetrics(getFont()); //java + int width = 0, height = 0; + for (int i = 0, j = 0; j != -1; i = j + 1) { + j = text.indexOf('\n', i); + if (i != j) { // && i != text.length() + String line = (j != -1) ? text.substring(i, j) : text.substring(i); //java + width = Math.max(width, fm.stringWidth(line)); //java + //midp width = font.substringWidth(text, i, ((j != -1) ? j : text.length()) - i); + } + if ((end >= i) && ((j == -1) || (end <= j))) { + caretx = fm.stringWidth(text.substring(i, end)); //java + //midp caretx = font.substringWidth(text, i, end - i); + carety = height; + } + height += fm.getHeight(); + } + layoutScrollPane(component, width + 2, + height - fm.getLeading() + 2, 0, 0); + scrollToVisible(component, caretx, carety, + 2, fm.getAscent() + fm.getDescent() + 2); + } + else if ("tabbedpane" == classname) { + Rectangle bounds = getRectangle(component, "bounds"); + String placement = getString(component, "placement", "top"); + boolean horizontal = ((placement == "top") || (placement == "bottom")); + int tabd = 0; + int tabsize = 0; + for (Object comp = get(component, "tab"); + comp != null; comp = get(comp, ":next")) { + Dimension d = getSize(comp, 8, 4, "left"); + setRectangle(comp, "bounds", + horizontal ? tabd : 0, horizontal ? 0 : tabd, d.width, d.height); + tabd += horizontal ? d.width : d.height; + tabsize = Math.max(tabsize, horizontal ? d.height : d.width); + } + for (Object comp = get(component, "tab"); + comp != null; comp = get(comp, ":next")) { + Rectangle r = getRectangle(comp, "bounds"); + if (horizontal) { + if (placement == "bottom") { r.y = bounds.height - tabsize; } + r.height = tabsize; + } else { + if (placement == "right") { r.x = bounds.width - tabsize; } + r.width = tabsize; + } + } + int cx = (placement == "left") ? (tabsize + 1) : 2; + int cy = (placement == "top") ? (tabsize + 1) : 2; + int cwidth = bounds.width - (horizontal ? 4 : (tabsize + 3)); + int cheight = bounds.height - (horizontal ? (tabsize + 3) : 4); + for (Object comp = get(component, "component"); + comp != null; comp = get(comp, ":next")) { + if (!getBoolean(comp, "visible", true)) { continue; } + setRectangle(comp, "bounds", cx, cy, cwidth, cheight); + doLayout(comp); + } + } + else if (("panel" == classname) || (classname == "dialog")) { + int gap = getInteger(component, "gap", 0); + int[][] grid = getGrid(component, gap); + if (grid != null) { + int top = getInteger(component, "top", 0); + int left = getInteger(component, "left", 0); + int bottom = getInteger(component, "bottom", 0); + int right = getInteger(component, "right", 0); + if (classname == "dialog") { + int titleheight = getInteger(component, "titleheight", 0); + top += 4 + titleheight; left += 4; bottom += 4; right += 4; + } + + Rectangle bounds = getRectangle(component, "bounds"); + for (int i = 0; i < 2; i++) { + int d = ((i == 0) ? (bounds.width - left - right) : + (bounds.height - top - bottom)) - + getSum(grid[i], 0, grid[i].length, gap, false); + if (d != 0) { + int w = getSum(grid[2 + i], 0, grid[2 + i].length, 0, false); + if (w > 0) { + for (int j = 0; j < grid[i].length; j++) { + if (grid[2 + i][j] != 0) { + grid[i][j] += d * grid[2 + i][j] / w; + } + } + } + } + } + + int i = 0; + for (Object comp = get(component, "component"); + comp != null; comp = get(comp, ":next")) { + if (!getBoolean(comp, "visible", true)) { continue; } + int ix = left + getSum(grid[0], 0, grid[4][i], gap, true); + int iy = top + getSum(grid[1], 0, grid[5][i], gap, true); + int iwidth = getSum(grid[0], grid[4][i], grid[6][i], gap, false); + int iheight = getSum(grid[1], grid[5][i], grid[7][i], gap, false); + String halign = getString(comp, "halign", "fill"); + String valign = getString(comp, "valign", "fill"); + if ((halign != "fill") || (valign != "fill")) { + Dimension d = getPreferredSize(comp); + if (halign != "fill") { + int dw = Math.max(0, iwidth - d.width); + if (halign == "center") { ix += dw / 2; } + else if (halign == "right") { ix += dw; } + iwidth -= dw; + } + if (valign != "fill") { + int dh = Math.max(0, iheight - d.height); + if (valign == "center") { iy += dh / 2; } + else if (valign == "bottom") { iy += dh; } + iheight -= dh; + } + } + setRectangle(comp, "bounds", ix, iy, iwidth, iheight); + doLayout(comp); + i++; + } + } + } + else if ("desktop" == classname) { + Rectangle bounds = getRectangle(component, "bounds"); + for (Object comp = get(component, "component"); + comp != null; comp = get(comp, ":next")) { + String iclass = getClass(comp); + if (iclass == "dialog") { + Dimension d = getPreferredSize(comp); + if (get(comp, "bounds") == null) + setRectangle(comp, "bounds", + Math.max(0, (bounds.width - d.width) / 2), + Math.max(0, (bounds.height - d.height) / 2), + Math.min(d.width, bounds.width), Math.min(d.height, bounds.height)); + } else if ((iclass == "combolist") || (iclass == "popupmenu")) { + iclass = iclass; //compiler bug + } else { + setRectangle(comp, "bounds", 0, 0, bounds.width, bounds.height); + } + doLayout(comp); + } + } + else if ("spinbox" == classname) { + layoutField(component, block, false, 0); + } + else if ("splitpane" == classname) { + Rectangle bounds = getRectangle(component, "bounds"); + boolean horizontal = ("vertical" != get(component, "orientation")); + int divider = getInteger(component, "divider", -1); + int maxdiv = (horizontal ? bounds.width : bounds.height) - 5; + + Object comp1 = get(component, "component"); + boolean visible1 = (comp1 != null) && getBoolean(comp1, "visible", true); + if (divider == -1) { + int d1 = 0; + if (visible1) { + Dimension d = getPreferredSize(comp1); + d1 = horizontal ? d.width : d.height; + } + divider = Math.min(d1, maxdiv); + setInteger(component, "divider", divider, -1); + } + else if (divider > maxdiv) { + setInteger(component, "divider", divider = maxdiv, -1); + } + + if (visible1) { + setRectangle(comp1, "bounds", 0, 0, horizontal ? divider : bounds.width, + horizontal ? bounds.height : divider); + doLayout(comp1); + } + Object comp2 = (comp1 != null) ? get(comp1, ":next") : null; + if ((comp2 != null) && getBoolean(comp2, "visible", true)) { + setRectangle(comp2, "bounds", horizontal ? (divider + 5) : 0, + horizontal ? 0 : (divider + 5), + horizontal ? (bounds.width - 5 - divider) : bounds.width, + horizontal ? bounds.height : (bounds.height - 5 - divider)); + doLayout(comp2); + } + } + else if (("list" == classname) || + ("table" == classname) || ("tree" == classname)) { + int width = 0; + int columnheight = 0; + if ("table" == classname) { + for (Object column = get(component, "column"); + column != null; column = get(column, ":next")) { + width += getInteger(column, "width", 80); + Dimension d = getSize(column, 2, 2, "left"); + columnheight = Math.max(columnheight, d.height); + } + } + String itemname = ("list" == classname) ? "item" : + (("table" == classname) ? "row" : "node"); + int y = 0; + int level = 0; + for (Object item = get(component, itemname); item != null;) { + int x = 0; + int iwidth = 0; int iheight = 0; + if ("table" == classname) { + iwidth = width; + for (Object cell = get(item, "cell"); + cell != null; cell = get(cell, ":next")) { + Dimension d = getSize(cell, 2, 3, "left"); + iheight = Math.max(iheight, d.height); + } + } + else { + if ("tree" == classname) { + x = (level + 1) * block; + } + Dimension d = getSize(item, 2, 3, "left"); + iwidth = d.width; iheight = d.height; + width = Math.max(width, x + d.width); + } + setRectangle(item, "bounds", x, y, iwidth, iheight); + y += iheight; + if ("tree" == classname) { + Object next = get(item, "node"); + if ((next != null) && getBoolean(item, "expanded", true)) { + level++; + } else { + while (((next = get(item, ":next")) == null) && (level > 0)) { + item = getParent(item); + level--; + } + } + item = next; + } else { + item = get(item, ":next"); + } + } + layoutScrollPane(component, width, y - 1, 0, columnheight); + } + else if ("menubar" == classname) { + Rectangle bounds = getRectangle(component, "bounds"); + int x = 0; + for (Object menu = get(component, "menu"); + menu != null; menu = get(menu, ":next")) { + Dimension d = getSize(menu, 8, 4, "left"); + setRectangle(menu, "bounds", x, 0, d.width, bounds.height); + x += d.width; + } + } + else if (("combolist" == classname) || ("popupmenu" == classname)) { + boolean combo = ("combolist" == classname); + int pw = 0; int ph = 0; int pxy = combo ? 0 : 1; + for (Object item = get(get(component, combo ? "combobox" : "menu"), + combo ? "choice" : "menu"); item != null; item = get(item, ":next")) { + String itemclass = combo ? null : getClass(item); + Dimension d = (itemclass == "separator") ? new Dimension(1, 1) : + getSize(item, 8 , 4, "left"); + if (itemclass == "checkboxmenuitem") { + d.width = d.width + block + 3; + d.height = Math.max(block, d.height); + } + else if (itemclass == "menu") { + d.width += block; + } + setRectangle(item, "bounds", pxy, pxy + ph, d.width, d.height); + pw = Math.max(pw, d.width); + ph += d.height; + } + Rectangle r = getRectangle(component, "bounds"); + r.width = pw + 2; r.height = ph + 2; + if (combo) { + Rectangle db = getRectangle(content, "bounds"); + if (r.y + ph + 2 > db.height) { + r.width = pw + 2 + block; + r.height = db.height - r.y; + } + else { + r.height = Math.min(r.height, db.height - r.y); + } + r.width = Math.min(r.width, db.width - r.x); + layoutScrollPane(component, pw, ph, 0, 0);//~ + } + } + //java> + else if ("bean" == classname) { + Rectangle r = getRectangle(component, "bounds"); + ((Component) get(component, "bean")).setBounds(r); + } + //MouseEvent.MOUSE_ENTERED, mouseinside, insidepart); //java + } + popup(popupmenu, "popupmenu"); + } + if ((selected == null) || (getClass(selected) != "menu")) { return null; } + popup = createImpl("popupmenu"); + set(popup, "menu", selected); + set(component, "popupmenu", popup); + + Rectangle bounds = getRectangle(selected, "bounds"); + if ("menubar" == classname) { + px = bounds.x; py = bounds.y + bounds.height - 1; + } else { + px = bounds.x + getRectangle(component, "bounds").width - 4; + py = bounds.y; + } + } + else { //if ("combobox" == classname) { + popup = createImpl("combolist"); + set(popup, "combobox", component); + set(component, "combolist", popup); + + py = getRectangle(component, "bounds").height + 1; + } + if (("menubar" == classname) || ("combobox" == classname)) { + popupowner = component; + } + insertItem(content, "component", popup, 0); + set(popup, ":parent", content); + while (component != content) { + Rectangle r = getRectangle(component, "bounds"); + px += r.x; py += r.y; + component = getParent(component); + } + setRectangle(popup, "bounds", px, py, 0, 0); + doLayout(popup); repaint(popup); + return popup; + } + + /** + * + */ + private void closeup(Object combobox, Object combolist, Object item) { + if ((item != null) && getBoolean(item, "enabled", true)) { + String text = getString(item, "text", ""); + set(combobox, "text", text); // if editable + setInteger(combobox, "start", text.length(), 0); + setInteger(combobox, "end", 0, 0); + set(combobox, "icon", get(item, "icon")); + validate(combobox); + setInteger(combobox, "selected", getIndex(combobox, "choice", item), -1); + invoke(combobox, "action"); + } + set(combolist, "combobox", null); + set(combobox, "combolist", null); + removeItemImpl(content, "component", combolist); + repaint(combolist); + set(combolist, ":parent", null); + popupowner = null; + if (mouseinside == combolist) { + findComponent(content, mousex, mousey); + handleMouseEvent(mousex, mousex, 1, false, false, false, //java + MouseEvent.MOUSE_ENTERED, mouseinside, insidepart); //java + } + } + + /** + * + */ + private void closeup(Object menubar) { + set(menubar, "selected", null); + popup(menubar, "menubar"); + repaint(menubar); // , selected + popupowner = null; + } + + /** + * + */ + private void closeup() { + if (popupowner != null) { + String classname = getClass(popupowner); + if ("menubar" == classname) { + closeup(popupowner); + } + else if ("combobox" == classname) { + closeup(popupowner, get(popupowner, "combolist"), null); + } + } + } + + /** + * + */ + private void showTip() { + String text = null; + tooltipowner = null; + String classname = getClass(mouseinside); + if ((classname == "tabbedpane") || (classname == "menubar") || (classname == "popupmenu")) { + if (insidepart != null) { + text = getString(insidepart, "tooltip", null); + } + } + else if (classname == "combolist") { + if (insidepart instanceof Object[]) { + text = getString(insidepart, "tooltip", null); + } + } + //list table tree + if (text == null) { text = getString(mouseinside, "tooltip", null); } + else { tooltipowner = insidepart; } + if (text != null) { + FontMetrics fm = getFontMetrics(getFont()); + int width = fm.stringWidth(text) + 4; + int height = fm.getAscent() + fm.getDescent() + 4; + if (tooltipowner == null) { tooltipowner = mouseinside; } + setRectangle(tooltipowner, "tooltipbounds", mousex + 10, mousey + 10, width, height); + repaint(mousex + 10, mousey + 10, width, height); + } + } + + /** + * + */ + private void hideTip() { + if (tooltipowner != null) { + Rectangle bounds = getRectangle(tooltipowner, "tooltipbounds"); + set(tooltipowner, "tooltipbounds", null); + tooltipowner = null; + repaint(bounds.x, bounds.y, bounds.width, bounds.height); + } + } + + /** + * + */ + private void layoutField(Object component, int dw, boolean hidden, int left) { + int width = getRectangle(component, "bounds").width - left -dw; + String text = getString(component, "text", ""); + int start = getInteger(component, "start", 0); + if (start > text.length()) { setInteger(component, "start", start = text.length(), 0); } + int end = getInteger(component, "end", 0); + if (end > text.length()) { setInteger(component, "end", end = text.length(), 0); } + int offset = getInteger(component, "offset", 0); + int off = offset; + FontMetrics fm = getFontMetrics(getFont()); + int caret = hidden ? (fm.charWidth('*') * end) : + fm.stringWidth(text.substring(0, end)); //java + //midp font.substringWidth(text, 0, end); + if (off > caret) { + off = caret; + } + else if (off < caret - width + 4) { + off = caret - width + 4; + } + off = Math.max(0, Math.min(off, (hidden ? (fm.charWidth('*') * + text.length()) : fm.stringWidth(text)) - width + 4)); + if (off != offset) { + setInteger(component, "offset", off, 0); + } + } + + /** + * + */ + private void layoutScrollPane(Object component, + int contentwidth, int contentheight, int rowwidth, int columnheight) { + Rectangle bounds = getRectangle(component, "bounds"); + boolean hneed = false; boolean vneed = false; + if (contentwidth > bounds.width - rowwidth - 2) { + hneed = true; + vneed = (contentheight > bounds.height - columnheight - 2 - block); + } + if (vneed || (contentheight > bounds.height - columnheight - 2)) { + vneed = true; + hneed = hneed || (contentwidth > bounds.width - rowwidth - 2 - block); + } + int viewportwidth = bounds.width - rowwidth - (vneed ? block : 0); + int viewportheight = bounds.height - columnheight - (hneed ? block : 0); + setRectangle(component, ":port", + rowwidth, columnheight, viewportwidth, viewportheight); //?rowwidth + + Rectangle view = getRectangle(component, ":view"); + setRectangle(component, ":view", + (view != null) ? Math.max(0, + Math.min(view.x, contentwidth - viewportwidth + 2)) : 0, + (view != null) ? Math.max(0, + Math.min(view.y, contentheight - viewportheight + 2)) : 0, + Math.max(viewportwidth - 2, contentwidth), + Math.max(viewportheight - 2, contentheight)); + } + + /** + * + */ + private void scrollToVisible(Object component, + int x, int y, int width, int height) { + Rectangle view = getRectangle(component, ":view"); + Rectangle port = getRectangle(component, ":port"); + int vx = Math.max(x + width - port.width + 2, Math.min(view.x, x)); + int vy = Math.max(y + height - port.height + 2, Math.min(view.y, y)); + if ((view.x != vx) || (view.y != vy)) { + repaint(component); // horizontal | vertical + view.x = vx; view.y = vy; + } + } + + /** + * + */ + public Dimension getPreferredSize() { + return getPreferredSize(content); + } + + /** + * + */ + private Dimension getPreferredSize(Object component) { + int width = getInteger(component, "width", 0); + int height = getInteger(component, "height", 0); + if ((width > 0) && (height > 0)) { + return new Dimension(width, height); + } + String classname = getClass(component); + //System.out.println("classname: " + classname); + if ("label" == classname) { + return getSize(component, 0, 0, "left"); + } + if ("button" == classname) { + return getSize(component, 12, 6, "center"); + } + if ("checkbox" == classname) { + Dimension d = getSize(component, 0, 0, "left"); + d.width = d.width + block + 3; + d.height = Math.max(block, d.height); + return d; + } + if ("combobox" == classname) { + if (getBoolean(component, "editable", true)) { + Dimension size = getFieldSize(component); + Image icon = getIcon(component, "icon", null); + if (icon != null) { + size.width += icon.getWidth(this); + size.height = Math.max(size.height, icon.getHeight(this) + 2); + } + size.width += block; + return size; + } else { + int selected = getInteger(component, "selected", -1); + return getSize((selected != -1) ? + getItemImpl(component, "choice", selected) : + get(component, "choice"), 4 + block, 4, "left"); + } + } + if (("textfield" == classname) || ("passwordfield" == classname)) { + return getFieldSize(component); + } + if ("textarea" == classname) { + int columns = getInteger(component, "columns", 0); + int rows = getInteger(component, "rows", 0); // 'e' -> 'm' ? + FontMetrics fm = getFontMetrics(getFont()); //java + return new Dimension( + ((columns > 0) ? (columns * fm.charWidth('e') + 2) : 76) + 2 + block, + ((rows > 0) ? (rows * fm.getHeight() - fm.getLeading() + 2) : 76) + 2 + block); + } + if ("tabbedpane" == classname) { + String placement = getString(component, "placement", "top"); + boolean horizontal = ((placement == "top") || (placement == "bottom")); + int tabsize = 0; + int contentwidth = 0; int contentheight = 0; + for (Object comp = get(component, "tab"); + comp != null; comp = get(comp, ":next")) { + Dimension d = getSize(comp, 8, 4, "left"); + tabsize = Math.max(tabsize, horizontal ? d.height : d.width); + } + for (Object comp = get(component, "component"); + comp != null; comp = get(comp, ":next")) { + if (!getBoolean(comp, "visible", true)) { continue; } + Dimension d = getPreferredSize(comp); + contentwidth = Math.max(contentwidth, d.width); + contentheight = Math.max(contentheight, d.height); + } + return new Dimension(contentwidth + (horizontal ? 4 : (tabsize + 3)), + contentheight + (horizontal ? (tabsize + 3) : 4)); + } + if (("panel" == classname) || (classname == "dialog")) { + Dimension size = new Dimension( + getInteger(component, "left", 0) + getInteger(component, "right", 0), + getInteger(component, "top", 0) + getInteger(component, "bottom", 0)); + if (classname == "dialog") { + int titleheight = getSize(component, 0, 0, "left").height; + setInteger(component, "titleheight", titleheight, 0); + size.width += 8; size.height += 8 + titleheight; + } + int gap = getInteger(component, "gap", 0); + int[][] grid = getGrid(component, gap); + if (grid != null) { + size.width += getSum(grid[0], 0, grid[0].length, gap, false); + size.height += getSum(grid[1], 0, grid[1].length, gap, false); + } + return size; + } + else if ("desktop" == classname) { + Dimension size = new Dimension(); + for (Object comp = get(component, "component"); + comp != null; comp = get(comp, ":next")) { + String iclass = getClass(comp); + if ((iclass != "dialog") && (iclass != "popupmenu") && + (iclass != "combolist")) { + Dimension d = getPreferredSize(comp); + size.width = Math.max(d.width, size.width); + size.height = Math.max(d.height, size.height); + } + } + return size; + } + if ("spinbox" == classname) { + Dimension size = getFieldSize(component); + size.width += block; + return size; + } + if ("progressbar" == classname) { + boolean horizontal = ("vertical" != get(component, "orientation")); + return new Dimension(horizontal ? 76 : 6, horizontal ? 6 : 76); + } + if ("slider" == classname) { + boolean horizontal = ("vertical" != get(component, "orientation")); + return new Dimension(horizontal ? 76 : 10, horizontal ? 10 : 76); + } + if ("splitpane" == classname) { + boolean horizontal = ("vertical" != get(component, "orientation")); + Object comp1 = get(component, "component"); + Dimension size = ((comp1 == null) || !getBoolean(comp1, "visible", true)) ? + new Dimension() : getPreferredSize(comp1); + Object comp2 = get(comp1, ":next"); + if ((comp2 != null) && getBoolean(comp2, "visible", true)) { + Dimension d = getPreferredSize(comp2); + size.width = horizontal ? (size.width + d.width) : + Math.max(size.width, d.width); + size.height = horizontal ? Math.max(size.height, d.height) : + (size.height + d.height); + } + if (horizontal) { size.width += 5; } else { size.height += 5; } + return size; + } + if (("list" == classname) || + ("table" == classname) || ("tree" == classname)) { + return new Dimension(76 + 2 + block, 76 + 2 + block); + } + if ("separator" == classname) { + return new Dimension(1, 1); + } + if ("menubar" == classname) { + Dimension size = new Dimension(0, 0); + for (Object menu = get(component, "menu"); + menu != null; menu = get(menu, ":next")) { + Dimension d = getSize(menu, 8, 4, "left"); + size.width += d.width; + size.height = Math.max(size.height, d.height); + } + return size; + } + //java> + if ("bean" == classname) { + return ((Component) get(component, "bean")).getPreferredSize(); + } + // columns)) { + x = 0; y++; j = -1; + } + else if (columnheight[x + j] > y) { + x += (j + 1); j = -1; + } + } + if (y + rowspan > grid[1].length) { + int[] rowheights = new int[y + rowspan]; + System.arraycopy(grid[1], 0, rowheights, 0, grid[1].length); + grid[1] = rowheights; + int[] rowweights = new int[y + rowspan]; + System.arraycopy(grid[3], 0, rowweights, 0, grid[3].length); + grid[3] = rowweights; + } + for (int j = 0; j < colspan; j++) { + columnheight[x + j] = y + rowspan; + } + + int weightx = getInteger(comp, "weightx", 0); + int weighty = getInteger(comp, "weighty", 0); + Dimension d = getPreferredSize(comp); + + if (colspan == 1) { + grid[0][x] = Math.max(grid[0][x], d.width); // columnwidths + grid[2][x] = Math.max(grid[2][x], weightx); // columnweights + } + else { + if (cache == null) { cache = new int[4][count]; } + cache[0][i] = d.width; + cache[2][i] = weightx; + if ((nextsize == 0) || (colspan < nextsize)) { nextsize = colspan; } + } + if (rowspan == 1) { + grid[1][y] = Math.max(grid[1][y], d.height); // rowheights + grid[3][y] = Math.max(grid[3][y], weighty); // rowweights + } + else { + if (cache == null) { cache = new int[4][count]; } + cache[1][i] = d.height; + cache[3][i] = weighty; + if ((nextsize == 0) || (rowspan < nextsize)) { nextsize = rowspan; } + } + grid[4][i] = x; //gridx + grid[5][i] = y; //gridy + grid[6][i] = colspan; //gridwidth + grid[7][i] = rowspan; //gridheight + + x += colspan; + i++; + } + + while (nextsize != 0) { + int size = nextsize; nextsize = 0; + for (int j = 0; j < 2; j++) { // horizontal, vertical + for (int k = 0; k < count; k++) { + if (grid[6 + j][k] == size) { // gridwidth, gridheight + int gridpoint = grid[4 + j][k]; // gridx, gridy + + int weightdiff = cache[2 + j][k]; + for (int m = 0; (weightdiff > 0) && (m < size); m++) { + weightdiff -= grid[2 + j][gridpoint + m]; + } + if (weightdiff > 0) { + int weightsum = cache[2 + j][k] - weightdiff; + for (int m = 0; (weightsum > 0) && (m < size); m++) { + int weight = grid[2 + j][gridpoint + m]; + if (weight > 0) { + int weightinc = weight * weightdiff / weightsum; + grid[2 + j][gridpoint + m] += weightinc; + weightdiff -= weightinc; + weightsum -= weightinc; + } + } + grid[2 + j][gridpoint + size - 1] += weightdiff; + } + + int sizediff = cache[j][k]; + int weightsum = 0; + for (int m = 0; (sizediff > 0) && (m < size); m++) { + sizediff -= grid[j][gridpoint + m]; + weightsum += grid[2 + j][gridpoint + m]; + } + if (sizediff > 0) { + for (int m = 0; (weightsum > 0) && (m < size); m++) { + int weight = grid[2 + j][gridpoint + m]; + if (weight > 0) { + int sizeinc = weight * sizediff / weightsum; + grid[j][gridpoint + m] += sizeinc; + sizediff -= sizeinc; + weightsum -= weight; + } + } + grid[j][gridpoint + size - 1] += sizediff; + } + } + else if ((grid[6 + j][k] > size) && + ((nextsize == 0) || (grid[6 + j][k] < nextsize))) { + nextsize = grid[6 + j][k]; + } + } + } + } + return grid; + } + + /** + * + */ + private int getSum(int[] values, + int from, int length, int gap, boolean last) { + if (length <= 0) { return 0; } + int value = 0; + for (int i = 0; i < length; i++) { + value += values[from + i]; + } + return value + (length - (last ? 0 : 1)) * gap; + } + + /** + * + */ + private Dimension getFieldSize(Object component) { + String text = getString(component, "text", ""); + int columns = getInteger(component, "columns", 0); + FontMetrics fm = getFontMetrics(getFont()); + return new Dimension(((columns > 0) ? + (columns * fm.charWidth('e')) : 76) + 4, + fm.getAscent() + fm.getDescent() + 4); // fm.stringWidth(text) + } + + /** + * + */ + private Dimension getSize(Object component, + int dx, int dy, String defaultalignment) { + String text = getString(component, "text", null); + int tw = 0; int th = 0; + if (text != null) { + FontMetrics fm = getFontMetrics(getFont()); + tw = fm.stringWidth(text); + th = fm.getAscent() + fm.getDescent(); + } + Image icon = getIcon(component, "icon", null); + int iw = 0; int ih = 0; + if (icon != null) { + iw = icon.getWidth(this); + ih = icon.getHeight(this); + } + return new Dimension(tw + iw + dx, Math.max(th, ih) + dy); + } + //java> + + /** + * + */ + public void update(Graphics g) { + paint(g); + } + + /** + *~ + */ + public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { + if (infoflags == ImageObserver.ALLBITS) { + validate(content); + return super.imageUpdate(img, infoflags, x, y, width, height); + } + return true; + } + + /** + * + */ + public void paint(Graphics g) { + //g.setColor(Color.orange); + //g.fillRect(0, 0, getSize().width, getSize().height); + //long time = System.currentTimeMillis(); + Rectangle clip = g.getClipBounds(); + ///dg.setClip(r.x, r.y, r.width, r.height); + paint(g, clip.x, clip.y, clip.width, clip.height, content, isEnabled()); + //System.out.println(System.currentTimeMillis() - time); + ///g.setClip(0, 0, getSize().width, getSize().height); + //g.setColor(Color.red); g.drawRect(clip.x, clip.y, clip.width - 1, clip.height - 1); + } + + //Graphics g, + int clipx, int clipy, int clipwidth, int clipheight, + Object component, boolean enabled) { + if (!getBoolean(component, "visible", true)) { return; } + Rectangle bounds = getRectangle(component, "bounds"); + if (bounds == null) { return; } + if (bounds.width < 0) { + bounds.width = Math.abs(bounds.width); + doLayout(component); + } + if ((clipx + clipwidth < bounds.x) || + (clipx > bounds.x + bounds.width) || + (clipy + clipheight < bounds.y) || + (clipy > bounds.y + bounds.height)) { + return; + } + clipx -= bounds.x; clipy -= bounds.y; + String classname = getClass(component); + boolean pressed = (mousepressed == component); + boolean inside = (mouseinside == component) && + ((mousepressed == null) || pressed); + boolean focus = focusinside && (focusowner == component); + enabled = getBoolean(component, "enabled", true); //enabled && + g.translate(bounds.x, bounds.y); + //g.setClip(0, 0, bounds.width, bounds.height); + + if ("label" == classname) { + paintContent(component, g, clipx, clipy, clipwidth, clipheight, + 0, 0, bounds.width, bounds.height, + enabled ? c_text : c_disable, "left", true); + } + else if ("button" == classname) { + paintRect(g, 0, 0, bounds.width, bounds.height, + enabled ? c_border : c_disable, + enabled ? ((inside != pressed) ? c_hover : + (pressed ? c_press : c_ctrl)) : c_bg, true, true, true, true); + if (focus) { + g.setColor(c_focus); + g.drawRect(2, 2, bounds.width - 5, bounds.height - 5); + } + paintContent(component, g, clipx, clipy, clipwidth, clipheight, + 6, 3, bounds.width - 12, bounds.height - 6, + enabled ? c_text : c_disable, "center", true); + } + else if ("checkbox" == classname) { + boolean selected = getBoolean(component, "selected", false); + String group = getString(component, "group", null); + Color border = enabled ? c_border : c_disable; + Color foreground = enabled ? ((inside != pressed) ? c_hover : + (pressed ? c_press : c_ctrl)) : c_bg; + int dy = (bounds.height - block + 2) / 2; + if (group == null) { + paintRect(g, 1, dy + 1, block - 2, block - 2, + border, foreground, true, true, true, true); + } else { + g.setColor((foreground != c_ctrl) ? foreground : c_bg); + g.fillOval(1, dy + 1, block - 3, block - 3); //java + g.setColor(border); + g.drawOval(1, dy + 1, block - 3, block - 3); //java + } + if (focus) { + g.setColor(c_focus); + if (group == null) { + g.drawRect(3, dy + 3, block - 7, block - 7); + } else { + g.drawOval(3, dy + 3, block - 7, block - 7); //java + } + } + if((!selected && inside && pressed) || + (selected && (!inside || !pressed))) { + g.setColor(enabled ? c_text : c_disable); + if (group == null) { + g.fillRect(3, dy + block - 9, 2, 6); + g.drawLine(3, dy + block - 4, block - 4, dy + 3); + g.drawLine(4, dy + block - 4, block - 4, dy + 4); + } else { + g.fillOval(5, dy + 5, block - 10, block - 10); //java + g.drawOval(4, dy + 4, block - 9, block - 9); //java + } + } + paintContent(component, g, clipx, clipy, clipwidth, clipheight, + block + 3, 0, bounds.width - block - 3, bounds.height, + enabled ? c_text : c_disable, "left", true); + } + else if ("combobox" == classname) { + if (getBoolean(component, "editable", true)) { + Image icon = getIcon(component, "icon", null); + int left = (icon != null) ? icon.getWidth(this) : 0; + paintField(g, clipx, clipy, clipwidth, clipheight, component, + bounds.width - block, bounds.height, + inside, pressed, focus, enabled, false, left); + if (icon != null) { + g.drawImage(icon, 2, (bounds.height - icon.getHeight(this)) / 2, this); //java + //midp g.drawImage(icon, 2, bounds.height / 2, Graphics.LEFT | Graphics.VCENTER); + } + paintArrow(g, bounds.width - block, 0, block, bounds.height, + 'S', enabled, inside, pressed, "down", true, false, true, true); + } else { + paintRect(g, 0, 0, bounds.width, bounds.height, + enabled ? c_border : c_disable, + enabled ? ((inside != pressed) ? c_hover : + (pressed ? c_press : c_ctrl)) : c_bg, true, true, true, true); + paintContent(component, g, clipx, clipy, clipwidth, clipheight, + 2, 2, bounds.width - block - 4, bounds.height - 4, + enabled ? c_text : c_disable, "left", false); + paintArrow(g, bounds.width - block, 0, block, bounds.height, 'S'); + if (focus) { + g.setColor(c_focus); + g.drawRect(2, 2, bounds.width - block - 5, bounds.height - 5); + } + } + } + else if ("combolist" == classname) { + Rectangle view = getRectangle(component, ":view"); + Rectangle viewport = getRectangle(component, ":port"); + g.setColor(c_border); + g.drawRect(viewport.x, viewport.y, viewport.width - 1, viewport.height - 1); + if (paintScrollPane(g, clipx, clipy, clipwidth, clipheight, + bounds, view, viewport, enabled, inside, pressed)) { + Object selected = get(component, "inside"); + int ly = clipy - viewport.y - 1; + int yfrom = view.y + Math.max(0, ly); + int yto = view.y + Math.min(viewport.height - 2, ly + clipheight); + for (Object choice = get(get(component, "combobox"), "choice"); + choice != null; choice = get(choice, ":next")) { + Rectangle r = getRectangle(choice, "bounds"); + if (yto <= r.y) { break; } + if (yfrom >= r.y + r.height) { continue; } + boolean armed = (selected == choice); + paintRect(g, r.x, r.y, bounds.width - 2, r.height, c_border, + armed ? c_select : c_bg, false, false, false, false); + paintContent(choice, g, clipx, yfrom, clipwidth, yto - yfrom, + r.x + 4, r.y + 2, bounds.width - 10, r.height - 4, + getBoolean(choice, "enabled", true) ? c_text : c_disable, "left", false); + } + resetScrollPane(g, clipx, clipy, clipwidth, clipheight, view, viewport); + } + //paintRect(g, 0, 0, bounds.width, bounds.height, + // secondary1, c_ctrl, true, true, true, true); + } + else if (("textfield" == classname) || ("passwordfield" == classname)) { + paintField(g, clipx, clipy, clipwidth, clipheight, component, + bounds.width, bounds.height, + inside, pressed, focus, enabled, ("passwordfield" == classname), 0); + } + else if ("textarea" == classname) { + Rectangle view = getRectangle(component, ":view"); + Rectangle viewport = getRectangle(component, ":port"); + boolean editable = getBoolean(component, "editable", true); + paintRect(g, viewport.x, viewport.y, viewport.width, viewport.height, + enabled ? c_border : c_disable, editable ? c_textbg : c_bg, + true, true, true, true); + if (paintScrollPane(g, clipx, clipy, clipwidth, clipheight, + bounds, view, viewport, enabled, inside, pressed)) { + String text = getString(component, "text", ""); + int start = focus ? getInteger(component, "start", 0) : 0; + int end = focus ? getInteger(component, "end", 0) : 0; + int is = Math.min(start, end); int ie = Math.max(start, end); + boolean wrap = getBoolean(component, "wrap", false); + FontMetrics fm = g.getFontMetrics(); //java + int fontascent = fm.getAscent(); int fontheight = fm.getHeight(); //java + //midp int fontheight = fm.getHeight(); + int ascent = 1; + int ly = clipy - viewport.y - 1; + int yfrom = view.y + Math.max(0, ly); + int yto = view.y + Math.min(viewport.height - 2, ly + clipheight); + //g.setColor(Color.pink); g.fillRect(0, yfrom - 1, 75, 2); g.fillRect(0, yto - 1, 75, 2); + + boolean prevletter = false; int n = text.length(); char c = 0; + for (int i = 0, j = -1, k = 0; k <= n; k++) { // j is the last space index (before k) + if (yto <= ascent) { break; } + if (wrap) { + if (((k == n) || ((c = text.charAt(k)) == '\n') || (c == ' ')) && + (j > i) && (fm.stringWidth(text.substring(i, k)) > viewport.width - 4)) { + k--; // draw line to the begin of the current word (+ spaces) if it is out of width + } + else if ((k == n) || (c == '\n')) { // draw line to the text/line end + j = k; prevletter = false; + } + else { + if ((c == ' ') && (prevletter || (j > i))) { j = k; } // keep spaces starting the line + prevletter = (c != ' '); + continue; + } + } + else { + if ((k == n) || ((c = text.charAt(k)) == '\n')) { j = k; } else { continue; } + } + if (yfrom < ascent + fontheight) { + String line = (j != -1) ? text.substring(i, j) : text.substring(i); //java + if (focus && (is != ie) && (ie >= i) && ((j == -1) || (is <= j))) { + int xs = (is < i) ? -1 : (((j != -1) && (is > j)) ? (view.width - 1) : + fm.stringWidth(text.substring(i, is))); //java + //midp font.substringWidth(text, i, is - i)); + int xe = ((j != -1) && (ie > j)) ? (view.width - 1) : + fm.stringWidth(text.substring(i, ie)); //java + //midp font.substringWidth(text, i, ie - i); + g.setColor(c_select); + g.fillRect(1 + xs, ascent, xe - xs, fontheight); + } + g.setColor(enabled ? c_text : c_disable); + g.drawString(line, 1, ascent + fontascent); //java + //midp g.drawSubstring(text, i, ((j != -1) ? j : text.length()) - i, 1, ascent, Graphics.LEFT | Graphics.TOP); + if (focus && (end >= i) && ((j == -1) || (end <= j))) { + int caret = fm.stringWidth(text.substring(i, end)); //java + //midp int caret = font.substringWidth(text, i, end - i); + g.setColor(c_focus); + g.fillRect(caret, ascent, 1, fontheight); + } + } + ascent += fontheight; + i = j + 1; + } + resetScrollPane(g, clipx, clipy, clipwidth, clipheight, view, viewport); + } + } + else if ("tabbedpane" == classname) { + int i = 0; Rectangle last = null; + int selected = getInteger(component, "selected", 0); + String placement = getString(component, "placement", "top"); + for (Object comp = get(component, "tab"); + comp != null; comp = get(comp, ":next")) { + Rectangle r = getRectangle(comp, "bounds"); + boolean hover = !(selected == i) && inside && + (mousepressed == null) && (insidepart == comp); + boolean sel = (selected == i); + boolean tabenabled = enabled && getBoolean(comp, "enabled", true); + paintRect(g, r.x, r.y, r.width, r.height, + enabled ? c_border : c_disable, + tabenabled ? (sel ? c_bg : (hover ? c_hover : c_ctrl)) : c_ctrl, + (placement != "bottom") || !sel, (placement != "right") || !sel, + (placement == "bottom") || ((placement == "top") && !sel), + (placement == "right") || ((placement == "left") && !sel)); + if (focus && sel) { + g.setColor(c_focus); + g.drawRect(r.x + 2, r.y + 2, r.width - 4, r.height - 4); + } + paintContent(comp, g, clipx, clipy, clipwidth, clipheight, + r.x + 4, r.y + 2, r.width - 8, r.height - 4, + tabenabled ? c_text : c_disable, "left", true); + i++; last = r; + } + if (last != null) { + boolean horizontal = ((placement == "top") || (placement == "bottom")); + paintRect(g, horizontal ? (last.x + last.width) : last.x, + horizontal ? last.y : (last.y + last.height), + horizontal ? (bounds.width - last.x - last.width) : last.width, + horizontal ? last.height : (bounds.height - last.y - last.height), + enabled ? c_border : c_disable, c_bg, + (placement != "top"), (placement != "left"), + (placement == "top"), (placement == "left")); + paintRect(g, (placement == "left") ? last.width : 0, + (placement == "top") ? last.height : 0, + horizontal ? bounds.width : (bounds.width - last.width), + horizontal ? (bounds.height - last.height) : bounds.height, + enabled ? c_border : c_disable, c_bg, + (placement != "top"), (placement != "left"), + (placement != "bottom"), (placement != "right")); + } + Object tabcontent = getItemImpl(component, "component", selected); + if (tabcontent != null) { + paint(g, clipx, clipy, clipwidth, clipheight, tabcontent, enabled); + } + } + else if (("panel" == classname) || ("dialog" == classname)) { + if ("dialog" == classname) { + int titleheight = getInteger(component, "titleheight", 0); + paintRect(g, 0, 0, bounds.width, 3 + titleheight, + c_border, c_ctrl, true, true, false, true); + paintRect(g, 0, 3 + titleheight, bounds.width, bounds.height - 3 - titleheight, + c_border, c_press, false, true, true, true); + paintContent(component, g, clipx, clipy, clipwidth, clipheight, + 3, 2, bounds.width - 6, titleheight, c_text, "left", false); + paintRect(g, 3, 3 + titleheight, bounds.width - 6, bounds.height - 6 - titleheight, + c_border, c_bg, true, true, true, true); + } else { + paintRect(g, 0, 0, bounds.width, bounds.height, + c_border, c_bg, false, false, false, false); + } + for (Object comp = get(component, "component"); + comp != null; comp = get(comp, ":next")) { + paint(g, clipx, clipy, clipwidth, clipheight, comp, enabled); + } + } + else if ("desktop" == classname) { + paintReverse(g, clipx, clipy, clipwidth, clipheight, + get(component, "component"), enabled); + //g.setColor(Color.red); if (clip != null) g.drawRect(clipx, clipy, clipwidth, clipheight); + if (tooltipowner != null) { + Rectangle r = getRectangle(tooltipowner, "tooltipbounds"); + paintRect(g, r.x, r.y, r.width, r.height, + c_border, c_bg, true, true, true, true); + String text = getString(tooltipowner, "tooltip", null); + g.setColor(c_text); + g.drawString(text, r.x + 2, r.y + g.getFontMetrics().getAscent() + 2); //java + //midp g.drawString(text, r.x + 2, r.y + (r.height - font.getHeight()) / 2, Graphics.LEFT | Graphics.TOP); + } + } + else if ("spinbox" == classname) { + paintField(g, clipx, clipy, clipwidth, clipheight, component, + bounds.width - block, bounds.height, + inside, pressed, focus, enabled, false, 0); + paintArrow(g, bounds.width - block, 0, block, bounds.height / 2, + 'N', enabled, inside, pressed, "up", true, false, false, true); + paintArrow(g, bounds.width - block, bounds.height / 2, + block, bounds.height - (bounds.height / 2), + 'S', enabled, inside, pressed, "down", true, false, true, true); + } + else if ("progressbar" == classname) { + int minimum = getInteger(component, "minimum", 0); + int maximum = getInteger(component, "maximum", 100); + int value = getInteger(component, "value", 0); + boolean horizontal = ("vertical" != get(component, "orientation")); + int length = (value - minimum) * + ((horizontal ? bounds.width : bounds.height) - 1) / (maximum - minimum); + paintRect(g, 0, 0, horizontal ? length : bounds.width, + horizontal ? bounds.height : length, enabled ? c_border : c_disable, + c_select, true, true, horizontal, !horizontal); + paintRect(g, horizontal ? length : 0, horizontal ? 0 : length, + horizontal ? (bounds.width - length) : bounds.width , + horizontal ? bounds.height : (bounds.height - length), + enabled ? c_border : c_disable, c_bg, true, true, true, true); + } + else if ("slider" == classname) { + int minimum = getInteger(component, "minimum", 0); + int maximum = getInteger(component, "maximum", 100); + int value = getInteger(component, "value", 0); + boolean horizontal = ("vertical" != get(component, "orientation")); + int length = (value - minimum) * + ((horizontal ? bounds.width : bounds.height) - block) / + (maximum - minimum); + paintRect(g, horizontal ? 0 : 3, horizontal ? 3 : 0, + horizontal ? length : (bounds.width - 6), + horizontal ? (bounds.height - 6) : length, + enabled ? c_border : c_disable, + c_bg, true, true, horizontal, !horizontal); + paintRect(g, horizontal ? length : 0, horizontal ? 0 : length, + horizontal ? block : bounds.width, horizontal ? bounds.height : block, + enabled ? c_border : c_disable, + enabled ? c_ctrl : c_bg, true, true, true, true); + if (focus) { + g.setColor(c_focus); + g.drawRect(horizontal ? (length + 2) : 2, horizontal ? 2 : (length + 2), + (horizontal ? block : bounds.width) - 5, + (horizontal ? bounds.height : block) - 5); + //g.drawRect(length + 1, 1, block - 3, bounds.height - 3); + } + paintRect(g, horizontal ? (block + length) : 3, + horizontal ? 3 : (block + length), + bounds.width - (horizontal ? (block + length) : 6), + bounds.height - (horizontal ? 6 : (block + length)), + enabled ? c_border : c_disable, + c_bg, horizontal, !horizontal, true, true); + } + else if ("splitpane" == classname) { + boolean horizontal = ("vertical" != get(component, "orientation")); + int divider = getInteger(component, "divider", -1); + paintRect(g, horizontal ? divider : 0, horizontal ? 0 : divider, + horizontal ? 5 : bounds.width, horizontal ? bounds.height : 5, + c_border, c_bg, false, false, false, false); + g.setColor(enabled ? (focus ? c_focus : c_border) : c_disable); + int xy = horizontal ? bounds.height : bounds.width; + int xy1 = Math.max(0, xy / 2 - 12); + int xy2 = Math.min(xy / 2 + 12, xy - 1); + for (int i = divider + 1; i < divider + 4; i += 2) { + if (horizontal) { g.drawLine(i, xy1, i, xy2); } + else { g.drawLine(xy1, i, xy2, i); } + } + Object comp1 = get(component, "component"); + if (comp1 != null) { + paint(g, clipx, clipy, clipwidth, clipheight, comp1, enabled); + Object comp2 = get(comp1, ":next"); + if (comp2 != null) { + paint(g, clipx, clipy, clipwidth, clipheight, comp2, enabled); + } + } + } + else if (("list" == classname) || + ("table" == classname) || ("tree" == classname)) { + Rectangle view = getRectangle(component, ":view"); + Rectangle viewport = getRectangle(component, ":port"); + int[] columnwidths = null; + int lx = clipx - viewport.x - 1; + int xfrom = view.x + Math.max(0, lx); + int xto = view.x + Math.min(viewport.width - 2, lx + clipwidth); + if ("table" == classname) { + columnwidths = new int[getItemCountImpl(component, "column")]; + int i = 0; int x = 0; boolean drawheader = (clipy < viewport.y); + if (drawheader) { g.setClip(viewport.x, 0, viewport.width, viewport.y); } + for (Object column = get(component, "column"); + column != null; column = get(column, ":next")) { + boolean lastcolumn = (i == columnwidths.length - 1); + int width = getInteger(column, "width", 80); + if (lastcolumn) { width = Math.max(width, viewport.width - x); } + columnwidths[i] = width; + if (drawheader && (xfrom < x + width) && (xto > x)) { + paintRect(g, x - view.x, 0, width, viewport.y, + enabled ? c_border : c_disable, enabled ? c_ctrl : c_bg, + true, true, false, lastcolumn); + paintContent(column, g, clipx, clipy, clipwidth, clipheight, + x + 2 - view.x, 1, width - 2, + viewport.y - 2, enabled ? c_text : c_disable, "left", false); + } + i++; x += width; + } + if (drawheader) { g.setClip(clipx, clipy, clipwidth, clipheight); } + } + paintRect(g, viewport.x, viewport.y, viewport.width, viewport.height, + enabled ? c_border : c_disable, c_textbg, true, true, true, true); + if (paintScrollPane(g, clipx, clipy, clipwidth, clipheight, bounds, + view, viewport, enabled, inside, pressed)) { + Object lead = get(component, "lead"); + int ly = clipy - viewport.y - 1; + int yfrom = view.y + Math.max(0, ly); + int yto = view.y + Math.min(viewport.height - 2, ly + clipheight); + for (Object item = get(component, ("list" == classname) ? "item" : + (("table" == classname) ? "row" : "node")); item != null;) { + Rectangle r = getRectangle(item, "bounds"); + if (lead == null) { + set(component, "lead", lead = item); // draw first item focused when lead is null + } + if (yto <= r.y) { break; } // the clip bounds are above + + Object next = ("tree" == classname) ? get(item, "node") : null; + boolean expanded = (next != null) && + getBoolean(item, "expanded", true); + if (yfrom < r.y + r.height) { // the clip rectangle is not bellow the current item + boolean selected = getBoolean(item, "selected", false); + paintRect(g, 0, r.y, view.width, r.height, + c_bg, selected ? c_select : c_textbg, false, false, true, false); + if (focus && (lead == item)) { + g.setColor(c_focus); + g.drawRect(0, r.y, view.width - 1, r.height - 2); + } + if ("table" == classname) { + int x = 0; int i = 0; + for (Object cell = get(item, "cell"); + cell != null; cell = get(cell, ":next")) { + if (xto <= x) { break; } + int iwidth = (i < columnwidths.length) ? columnwidths[i] : 80; + if (xfrom < x + iwidth) { + boolean cellenabled = enabled && getBoolean(cell, "enabled", true); + paintContent(cell, g, xfrom, yfrom, xto - xfrom, yto - yfrom, + r.x + x + 1, r.y + 1, iwidth - 2, r.height - 3, + cellenabled ? c_text : c_disable, "left", false); + } + x += iwidth; i++; + } + } else { + boolean itemenabled = enabled && getBoolean(item, "enabled", true); + paintContent(item, g, xfrom, yfrom, xto - xfrom, yto - yfrom, + r.x + 1, r.y + 1, view.width - r.x - 2, + r.height - 3, itemenabled ? c_text : c_disable, "left", false); + + if (next != null) { + int x = r.x - block / 2; + int y = r.y + (r.height - 1) / 2; + //g.drawRect(x - 4, y - 4, 8, 8); + paintRect(g, x - 4, y - 4, 9, 9, itemenabled ? c_border : c_disable, + itemenabled ? c_ctrl : c_bg, true, true, true, true); + g.setColor(itemenabled ? c_text : c_disable); + g.drawLine(x - 2, y, x + 2, y); + if (!expanded) { + g.drawLine(x, y - 2, x, y + 2); + } + } + } + } + if ("tree" == classname) { + if ((next == null) || !expanded) { + while ((item != component) && ((next = get(item, ":next")) == null)) { + item = getParent(item); + } + } + item = next; + } else { + item = get(item, ":next"); + } + } + /*if (columnwidths != null) { + g.setColor(c_bg); + for (int i = 0, cx = -1; i < columnwidths.length - 1; i++) { + cx += columnwidths[i]; + g.drawLine(cx, 0, cx, view.height); + } + }*/ + resetScrollPane(g, clipx, clipy, clipwidth, clipheight, view, viewport); + } + } + else if ("separator" == classname) { + g.setColor(enabled ? c_border : c_disable); + g.fillRect(0, 0, bounds.width, bounds.height); + } + else if ("menubar" == classname) { + Object selected = get(component, "selected"); + int lastx = 0; + for (Object menu = get(component, "menu"); + menu != null; menu = get(menu, ":next")) { + Rectangle mb = getRectangle(menu, "bounds"); + if (clipx + clipwidth <= mb.x) { break; } + if (clipx >= mb.x + mb.width) { continue; } + boolean armed = (selected == menu); + boolean hoover = (selected == null) && (insidepart == menu); + paintRect(g, mb.x, 0, mb.width, bounds.height, enabled ? c_border : c_disable, + enabled ? (armed ? c_select : (hoover ? c_hover : c_ctrl)) : c_bg, + armed, armed, true, armed); + paintContent(menu, g, clipx, clipy, clipwidth, clipheight, + mb.x + 4, 1, mb.width, bounds.height, + (enabled && getBoolean(menu, "enabled", true)) ? c_text : c_disable, + "left", true); + lastx = mb.x + mb.width; + } + paintRect(g, lastx, 0, bounds.width - lastx, bounds.height, + enabled ? c_border : c_disable, enabled ? c_ctrl : c_bg, + false, false, true, false); + } + else if ("popupmenu" == classname) { + paintRect(g, 0, 0, bounds.width, bounds.height, + c_border, c_bg, true, true, true, true); + Object selected = get(component, "selected"); + for (Object menu = get(get(component, "menu"), "menu"); + menu != null; menu = get(menu, ":next")) { + Rectangle r = getRectangle(menu, "bounds"); + if (clipy + clipheight <= r.y) { break; } + if (clipy >= r.y + r.height) { continue; } + String itemclass = getClass(menu); + if (itemclass == "separator") { + g.setColor(c_border); + g.fillRect(r.x, r.y, bounds.width - 2, r.height); + } else { + boolean armed = (selected == menu); + boolean menuenabled = getBoolean(menu, "enabled", true); + paintRect(g, r.x, r.y, bounds.width - 2, r.height, c_border, + armed ? c_select : c_bg, false, false, false, false); + int tx = r.x; + if (itemclass == "checkboxmenuitem") { + tx += block + 3; + boolean checked = getBoolean(menu, "selected", false); + String group = getString(menu, "group", null); + g.translate(r.x + 4, r.y + 2); + g.setColor(menuenabled ? c_border : c_disable); + if (group == null) { + g.drawRect(1, 1, block - 3, block - 3); + } else { + g.drawOval(1, 1, block - 3, block - 3); //java + } + if (checked) { + g.setColor(menuenabled ? c_text : c_disable); + if (group == null) { + g.fillRect(3, block - 9, 2, 6); + g.drawLine(3, block - 4, block - 4, 3); + g.drawLine(4, block - 4, block - 4, 4); + } else { + g.fillOval(5, 5, block - 10, block - 10); //java + g.drawOval(4, 4, block - 9, block - 9); //java + } + } + g.translate(-r.x - 4, -r.y - 2); + } + paintContent(menu, g, clipx, clipy, clipwidth, clipheight, + tx + 4, r.y + 2, bounds.width - 10, + r.height - 4, menuenabled ? c_text : c_disable, "left", true); + if (itemclass == "menu") { + paintArrow(g, r.x + bounds.width - block, r.y, block, r.height, 'E'); + } + } + } + } + //java> + else if ("bean" == classname) { + g.clipRect(0, 0, bounds.width, bounds.height); + ((Component) get(component, "bean")).paint(g); + g.setClip(clipx, clipy, clipwidth, clipheight); + } + //translate(-bounds.x, -bounds.y); + clipx += bounds.x; clipy += bounds.y; + } + + /** + * + */ + private void paintReverse(Graphics g, + int clipx, int clipy, int clipwidth, int clipheight, + Object component, boolean enabled) { + if (component != null) { + Rectangle bounds = getRectangle(component, "bounds"); + if ((clipx < bounds.x) || + (clipx + clipwidth > bounds.x + bounds.width) || + (clipy < bounds.y) || + (clipy + clipheight > bounds.y + bounds.height)) { + paintReverse(g, clipx, clipy, clipwidth, clipheight, + get(component, ":next"), enabled); + } + paint(g, clipx, clipy, clipwidth, clipheight, component, enabled); + } + } + + /** + * + */ + private void paintField(Graphics g, + int clipx, int clipy, int clipwidth, int clipheight, Object component, + int width, int height, boolean inside, boolean pressed, + boolean focus, boolean enabled, boolean hidden, int left) { + boolean editable = getBoolean(component, "editable", true); + paintRect(g, 0, 0, width, height, enabled ? c_border : c_disable, + editable ? c_textbg : c_bg, true, true, true, true); + g.clipRect(1 + left, 1, width - left - 2, height - 2); + + String text = getString(component, "text", ""); + int offset = getInteger(component, "offset", 0); + FontMetrics fm = g.getFontMetrics(); //java + + int caret = 0; + if (focus) { + int start = getInteger(component, "start", 0); + int end = getInteger(component, "end", 0); + caret = hidden ? (fm.charWidth('*') * end) : + fm.stringWidth(text.substring(0, end)); //java + //midp font.substringWidth(text, 0, end); + if (start != end) { + int is = hidden ? (fm.charWidth('*') * start) : + fm.stringWidth(text.substring(0, start)); //java + //midp font.substringWidth(text, 0, start); + g.setColor(c_select); + g.fillRect(2 + left - offset + Math.min(is, caret), 1, + Math.abs(caret - is), height - 2); + } + } + + if (focus) { + g.setColor(c_focus); + g.fillRect(1 + left - offset + caret, 1, 1, height - 2); + } + + g.setColor(enabled ? c_text : c_disable); + int fx = 2 + left - offset; + int fy = (height + fm.getAscent() - fm.getDescent()) / 2; //java + //midp int fy = (height - font.getHeight()) / 2; + if (hidden) { + int fh = fm.charWidth('*'); + for (int i = text.length(); i > 0; i--) { + g.drawString("*", fx, fy); //java + //midp g.drawChar('*', fx, fy, Graphics.LEFT | Graphics.TOP); + fx += fh; + } + } else { + g.drawString(text, fx, fy); //java + //midp g.drawString(text, fx, fy, Graphics.LEFT | Graphics.TOP); + } + g.setClip(clipx, clipy, clipwidth, clipheight); + } + + /** + * + */ + private boolean paintScrollPane(Graphics g, + int clipx, int clipy, int clipwidth, int clipheight, Rectangle bounds, + Rectangle view, Rectangle viewport, + boolean enabled, boolean inside, boolean pressed) { + if ((viewport.y + viewport.height < bounds.height) && + (clipy + clipheight > viewport.y + viewport.height)) { // need horizontal + int x = viewport.x; + int y = viewport.y + viewport.height; + int height = bounds.height - y; + int button = Math.min(block, viewport.width / 2); + int track = viewport.width - (2 * button); //max 10 + int knob = Math.min(track, Math.max(track * (viewport.width - 2) / view.width, 6)); + int decrease = view.x * (track - knob) / + (view.width - viewport.width + 2); + int increase = track - decrease - knob; + paintArrow(g, x, y, button, height, + 'W', enabled, inside, pressed, "left", false, true, true, false); + paintRect(g, x + button, y, decrease, height, + enabled ? c_border : c_disable, c_bg, false, true, true, false); + paintRect(g, x + button + decrease, y, knob, height, + enabled ? c_border : c_disable, enabled ? c_ctrl : c_bg, false, true, true, true); + int n = Math.min(5, (knob - 4) / 3); + g.setColor(enabled ? c_border : c_disable); + int cx = (x + button + decrease) + (knob + 2 - n * 3) / 2; + for (int i = 0; i < n; i++ ) { + g.drawLine(cx + i * 3, y + 2, cx + i * 3, y + height - 4); + } + paintRect(g, x + button + decrease + knob, y, increase, height, + enabled ? c_border : c_disable, c_bg, false, false, true, true); + paintArrow(g, x + button + track, y, button, height, + 'E', enabled, inside, pressed, "right", false, false, true, true); + } + if ((viewport.x + viewport.width < bounds.width) && + (clipx + clipwidth > viewport.x + viewport.width)) { // need vertical + int x = viewport.x + viewport.width; + int y = viewport.y; + int width = bounds.width - x; + //if (y > 0) { + // paintRect(g, x - 1, 0, width + 1, y, + // enabled ? c_border : c_disable, c_bg, false, true, false, false); + //} + int track = viewport.height - (2 * block); + int knob = track * (viewport.height - 2) / view.height; + int decrease = view.y * (track - knob) / + (view.height - viewport.height + 2); + int increase = track - decrease - knob; + paintArrow(g, x, y, width, block, + 'N', enabled, inside, pressed, "up", true, false, false, true); + paintRect(g, x, y + block, width, decrease, + enabled ? c_border : c_disable, c_bg, true, false, false, true); + paintRect(g, x, y + block + decrease, width, knob, + enabled ? c_border : c_disable, enabled ? c_ctrl : c_bg, true, false, true, true); + int n = Math.min(5, (knob - 4) / 3); + g.setColor(enabled ? c_border : c_disable); + int cy = (y + block + decrease) + (knob + 2 - n * 3) / 2; + for (int i = 0; i < n; i++ ) { + g.drawLine(x + 2, cy + i * 3, x + width - 4, cy + i * 3); + } + paintRect(g, x, y + block + decrease + knob, width, increase, + enabled ? c_border : c_disable, c_bg, false, false, true, true); + paintArrow(g, x, y + block + track, width, block, + 'S', enabled, inside, pressed, "down", false, false, true, true); + } + if ((clipx + clipwidth > viewport.x) && (clipy + clipheight > viewport.y) && + (clipx < viewport.x + viewport.width) && (clipy < viewport.y + viewport.height)) { + g.clipRect(viewport.x + 1, viewport.y + 1, viewport.width - 2, viewport.height - 2); + g.translate(viewport.x + 1 - view.x, viewport.y + 1 - view.y); + return true; + } + return false; + } + + /** + * + */ + private void resetScrollPane(Graphics g, + int clipx, int clipy, int clipwidth, int clipheight, + Rectangle view, Rectangle viewport) { + g.translate(view.x - viewport.x - 1, view.y - viewport.y - 1); + g.setClip(clipx, clipy, clipwidth, clipheight); + } + + /** + * + */ + private void paintRect(Graphics g, int x, int y, int width, int height, + Color border, Color bg, + boolean top, boolean left, boolean bottom, boolean right) { + if ((width <= 0) || (height <= 0)) return; + g.setColor(border); + if (top) { + g.drawLine(x + width - 1, y, x, y); + y++; height--; if (height <= 0) return; + } + if (left) { + g.drawLine(x, y, x, y + height - 1); + x++; width--; if (width <= 0) return; + } + if (bottom) { + g.drawLine(x, y + height - 1, x + width - 1, y + height - 1); + height--; if (height <= 0) return; + } + if (right) { + g.drawLine(x + width - 1, y + height - 1, x + width - 1, y); + width--; if (width <= 0) return; + } + + //java> + if (bg == c_ctrl) { + if (height > block) { + g.setColor(c_bg); + g.fillRect(x, y, width, height - block); + } + for (int i = 0; i < width; i += block) { + g.drawImage(gradient, x + i, (height > block) ? (y + height - block) : y, + x + Math.min(i + block, width), y + height, + 0, 0, Math.min(block, width - i), Math.min(block, height), null); + } + /*if (width > block) { + g.setColor(c_bg); + g.fillRect(x, y, width - block, height); + } + for (int i = 0; i < height; i += block) { + g.drawImage(gradient, (width > block) ? (x + width - block) : x, y + i, + x + width, y + Math.min(i + block, height), + 0, 0, Math.min(block, width), Math.min(block, height - i), null); + }*/ + } + else { + g.setColor(bg); + g.fillRect(x, y, width, height); + } + //Graphics g, int x, int y, int width, int height, + char dir, boolean enabled, boolean inside, boolean pressed, String part, + boolean top, boolean left, boolean bottom, boolean right) { + inside = inside && (insidepart == part); + pressed = pressed && (pressedpart == part); + paintRect(g, x, y, width, height, enabled ? c_border : c_disable, + enabled ? ((inside != pressed) ? c_hover : + (pressed ? c_press : c_ctrl)) : c_bg, + top, left, bottom, right); + g.setColor(enabled ? c_text : c_disable); + paintArrow(g, x, y, width, height, dir); + } + + /** + * + */ + private void paintArrow(Graphics g, + int x, int y, int width, int height, char dir) { + int cx = x + width / 2 - 2; + int cy = y + height / 2 - 2; + for (int i = 0; i < 4; i++) { + if (dir == 'N') { // north + g.drawLine(cx + 1 - i, cy + i, cx + 1/*2*/ + i, cy + i); + } + else if (dir == 'W') { // west + g.drawLine(cx + i, cy + 1 - i, cx + i, cy + 1/*2*/ + i); + } + else if (dir == 'S') { // south + g.drawLine(cx + 1 - i, cy + 4 - i, cx + 1/*2*/ + i, cy + 4 - i); + } + else { // east + g.drawLine(cx + 4 - i, cy + 1 - i, cx + 4 - i, cy + 1/*2*/ + i); + } + } + } + + /** + * + */ + private void paintContent(Object component, Graphics g, + int clipx, int clipy, int clipwidth, int clipheight, + int x, int y, int width, int height, Color fg, String defaultalignment, + boolean checkmnemonic) { + String text = getString(component, "text", null); + Image icon = getIcon(component, "icon", null); + if ((text == null) && (icon == null)) { return; } + String alignment = getString(component, "alignment", defaultalignment); + + FontMetrics fm = null; //java + int tw = 0, th = 0; + int ta = 0; //java + if (text != null) { + fm = g.getFontMetrics(); //java + tw = fm.stringWidth(text); + ta = fm.getAscent(); //java + th = fm.getDescent() + ta; //java + //midp th = font.getHeight(); + g.setColor(fg); + } + int iw = 0, ih = 0; + if (icon != null) { + iw = icon.getWidth(this); + ih = icon.getHeight(this); //java + } + + boolean clipped = (tw + iw > width) || (th > height) || (ih > height); + int cx = x; + if ("center" == alignment) { cx += (width - tw - iw) / 2; } + else if ("right" == alignment) { cx += width - tw - iw; } + + if (clipped) { g.clipRect(x, y, width, height); } + if (icon != null) { + g.drawImage(icon, cx, y + (height - ih) / 2, this); //java + //midp g.drawImage(icon, cx, y + height / 2, Graphics.LEFT | Graphics.VCENTER); + cx += iw; + } + if (text != null) { + int ty = y + (height - th) / 2 + ta; //java + g.drawString(text, cx, ty); //java + //midp g.drawString(text, cx, y + (height - th) / 2, Graphics.LEFT | Graphics.TOP); + if (checkmnemonic) { + int mnemonic = getInteger(component, "mnemonic", -1); + if ((mnemonic != -1) && (mnemonic < text.length())) { + int mx = cx + fm.stringWidth(text.substring(0, mnemonic)); //java + //midp int mx = cx + font.substringWidth(text, 0, mnemonic); + //midp int ty = (height + th) / 2; + g.drawLine(mx, ty + 1, mx + fm.charWidth(text.charAt(mnemonic)), ty + 1); + } + } + } + if (clipped) { g.setClip(clipx, clipy, clipwidth, clipheight); } + } + //midp private void setTimer(long delay) {} + //java> + + /** + * + */ + public synchronized void run() { + while (timer == Thread.currentThread()) { + try { + if (watch == 0) { + wait(0); + } else { + long current = System.currentTimeMillis(); + if (watch > current) { + wait(watch - current); + } else { + watch = 0; + if ((watchdelay == 300L) || (watchdelay == 60L)) { + if (processScroll(mousepressed, pressedpart)) { setTimer(60L); } + } else if ((watchdelay == 375L) || (watchdelay == 75L)) { + if (processSpin(mousepressed, pressedpart)) { setTimer(75L); } + } else if (watchdelay == 750L) { + //System.out.println("> tip: " + getClass(mouseinside) + " : " + ((insidepart instanceof Object[]) ? getClass(insidepart) : insidepart)); + showTip(); + } + } + } + } catch (InterruptedException ie) {} //ie.printStackTrace(); + } + } + + /** + * + */ + private void setTimer(long delay) { + watchdelay = delay; + if (delay == 0) { + watch = 0; + } else { + long prev = watch; + watch = System.currentTimeMillis() + delay; + if (timer == null) { + timer = new Thread(this); + timer.setPriority(Thread.MIN_PRIORITY); + timer.setDaemon(true); + timer.start(); + } + if ((prev == 0) || (watch < prev)) { + synchronized (this) { notify(); } //try {}catch (IllegalMonitorStateException imse) {} + } + } + } + + /** + * + */ + public boolean isFocusTraversable() { + return true; + } + + // 0) { + processKeyPress((popupowner != null) ? popupowner : focusowner, + false, false, 1, keyCode, 0); + } + else { + int keychar = 0, key = 0; + switch (getGameAction(keyCode)) { + case UP: key = KeyEvent.VK_UP; break; + case LEFT: key = KeyEvent.VK_LEFT; break; + case DOWN: key = KeyEvent.VK_DOWN; break; + case RIGHT: key = KeyEvent.VK_RIGHT; break; + case FIRE: key = KeyEvent.VK_ENTER; keychar = KeyEvent.VK_SPACE; break; + case GAME_A: key = KeyEvent.VK_ESCAPE; break; + } + if (key != 0) { + processKeyPress((popupowner != null) ? popupowner : focusowner, + false, false, 1, keychar, key); + } + //if (keyCode == getKeyCode(LEFT)) { + } + } + } + + protected void keyRepeated(int keyCode) { + keyPressed(keyCode); + } + + private static final Command nextcommand = new Command("Next", Command.SCREEN, 0); + //private static final Command prevcommand = new Command("Previous", Command.SCREEN, 0); + { + addCommand(nextcommand); + //addCommand(prevcommand); + setCommandListener(this); + } + + public void commandAction(Command command, Displayable displayable) { + if (command == nextcommand) { + setNextFocusable(focusowner, false); + repaint(focusowner); + closeup(); + } + //else if (command == prevcommand) { + //setPreviousFocusable(focusowner, null, true, true, false); + //repaint(focusowner); + //closeup(); + //} + } + midp*/ + //java> + + /** + * + */ + protected void processEvent(AWTEvent e) { + int id = e.getID(); + if ((id >= MouseEvent.MOUSE_FIRST) && (id <= MouseEvent.MOUSE_LAST)) { + MouseEvent me = (MouseEvent) e; + int x = me.getX(); + int y = me.getY(); + int clickcount = me.getClickCount(); + boolean shiftdown = me.isShiftDown(); + boolean controldown = me.isControlDown(); + boolean popuptrigger = me.isPopupTrigger(); + if (id == MouseEvent.MOUSE_ENTERED) { + if (mousepressed == null) { + findComponent(content, x, y); + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_ENTERED, mouseinside, insidepart); + } + } + else if (id == MouseEvent.MOUSE_MOVED) { + Object previnside = mouseinside; + Object prevpart = insidepart; + findComponent(content, x, y); + if ((previnside == mouseinside) && (prevpart == insidepart)) { + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_MOVED, mouseinside, insidepart); + } + else { + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_EXITED, previnside, prevpart); + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_ENTERED, mouseinside, insidepart); + } + } + else if (id == MouseEvent.MOUSE_EXITED) { + if (mousepressed == null) { + Object mouseexit = mouseinside; + Object exitpart = insidepart; + mouseinside = insidepart = null; + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_EXITED, mouseexit, exitpart); + } + } + else if (id == MouseEvent.MOUSE_PRESSED) { + if (popupowner != null) { + String classname = getClass(mouseinside); + if ((popupowner != mouseinside) && + (classname != "popupmenu") && (classname != "combolist")) { + closeup(); + } + } + mousepressed = mouseinside; + pressedpart = insidepart; + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_PRESSED, mousepressed, pressedpart); + } + else if (id == MouseEvent.MOUSE_DRAGGED) { + Object previnside = mouseinside; + Object prevpart = insidepart; + findComponent(content, x, y); + boolean same = (previnside == mouseinside) && (prevpart == insidepart); + boolean isin = (mousepressed == mouseinside) && (pressedpart == insidepart); + boolean wasin = (mousepressed == previnside) && (pressedpart == prevpart); + + if (wasin && !isin) { + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_EXITED, mousepressed, pressedpart); + } + else if (!same && (popupowner != null) && !wasin) { + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + DRAG_EXITED, previnside, prevpart); + } + if (isin && !wasin) { + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_ENTERED, mousepressed, pressedpart); + } + else if (!same && (popupowner != null) && !isin) { + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + DRAG_ENTERED, mouseinside, insidepart); + } + if (isin == wasin) { + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_DRAGGED, mousepressed, pressedpart); + } + } + else if (id == MouseEvent.MOUSE_RELEASED) { + Object mouserelease = mousepressed; + Object releasepart = pressedpart; + mousepressed = pressedpart = null; + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_RELEASED, mouserelease, releasepart); + if ((mouseinside != null) && + ((mouserelease != mouseinside) || (releasepart != insidepart))) { + handleMouseEvent(x, y, clickcount, shiftdown, controldown, popuptrigger, + MouseEvent.MOUSE_ENTERED, mouseinside, insidepart); + } + } + } + else if (id == MOUSE_WHEEL) { + Rectangle port = getRectangle(mouseinside, ":port"); + if (port != null) { // is scrollable + Rectangle bounds = getRectangle(mouseinside, "bounds"); + try { // mouse wheel is supported since 1.4 thus it use reflection + if (wheelrotation == null) { + wheelrotation = e.getClass().getMethod("getWheelRotation", null); + } + int rotation = ((Integer) wheelrotation.invoke(e, null)).intValue(); + + if (port.x + port.width < bounds.width) { // has vertical scrollbar + processScroll(mouseinside, (rotation > 0) ? "down" : "up"); + } + else if (port.y + port.height < bounds.height) { // has horizontal scrollbar + processScroll(mouseinside, (rotation > 0) ? "right" : "left"); + } + } catch (Exception exc) { /* never */ } + } + } + else if ((id == KeyEvent.KEY_PRESSED) || (id == KeyEvent.KEY_TYPED)) { + if (focusinside && ((popupowner != null) || (focusowner != null))) { + hideTip(); + KeyEvent ke = (KeyEvent) e; + int keychar = ke.getKeyChar(); + boolean control = (keychar <= 0x1f) || + ((keychar >= 0x7f) && (keychar <= 0x9f)) || + (keychar >= 0xffff) || ke.isControlDown(); + if (control == (id == KeyEvent.KEY_PRESSED)) { + int keycode = control ? ke.getKeyCode() : 0; + if (!processKeyPress((popupowner != null) ? popupowner : focusowner, + ke.isShiftDown(), ke.isControlDown(), ke.getModifiers(), + control ? 0 : keychar, keycode)) { + if ((keycode == KeyEvent.VK_TAB) || + ((keycode == KeyEvent.VK_F6) && (ke.isAltDown() || ke.isControlDown()))) { + boolean outgo = (keycode == KeyEvent.VK_F6); + if (!ke.isShiftDown() ? setNextFocusable(focusowner, outgo) : + setPreviousFocusable(focusowner, outgo)) { + ke.consume(); + } else if (MOUSE_WHEEL != 0) { // 1.4 + if (!ke.isShiftDown()) { + transferFocus(); + } + else { try { + getClass().getMethod("transferFocusBackward", null). invoke(this, null); + } catch (Exception exc) { /* never */ } } + } + repaint(focusowner); + closeup(); + } + else if (keycode == KeyEvent.VK_F8) { + for (Object splitpane = focusowner; + splitpane != null; splitpane = getParent(splitpane)) { + if (getClass(splitpane) == "splitpane") { + setFocus(splitpane); repaint(splitpane); break; //middle + } + } + } + } + else ke.consume(); + /*else if (keycode == KeyEvent.VK_F10) { + Object menubar = null; // find("class", "menubar") + if ((menubar != null) && (get(menubar, "selected") == null)) { + set(menubar, "selected", getMenu(menubar, null, true, false)); + Object popup = popup(menubar, "menubar"); + set(popup, "selected", getMenu(popup, null, true, true)); + repaint(menubar); // , selected + } + }*/ + } + } + } + /*else if (id == KeyEvent.KEY_RELEASED) { + if (focusinside && (focusowner != null)) { + KeyEvent ke = (KeyEvent) e; + //pressedkey = 0; + processKeyRelease(focusowner, ke, ke.getKeyCode()); + } + }*/ + else if (id == FocusEvent.FOCUS_LOST) { + focusinside = false; + if (focusowner != null) { repaint(focusowner); } + closeup(); + } + else if (id == FocusEvent.FOCUS_GAINED) { + focusinside = true; + if (focusowner == null) { setFocus(content); } + else { repaint(focusowner); } + } + else if ((id == ComponentEvent.COMPONENT_RESIZED) || + (id == ComponentEvent.COMPONENT_SHOWN)) { + Dimension d = getSize(); + //System.out.println(id + ": " + d.width + ", " + d.height); + setRectangle(content, "bounds", 0, 0, d.width, d.height); + validate(content); + closeup(); + if (!focusinside) { requestFocus(); } + } + } + + /** + * + */ + /*private boolean processKeyPress(Object component, + KeyEvent e, int keycode, Object invoker) { + if (processKeyPress(component, e, keycode)) { return true; } + for (Object comp = get(component, "component"); + comp != null; comp = get(comp, ":next")) { + if ((comp != invoker) && processKeyPress(comp, e, keycode, null)) { + return true; + } + } + if ((invoker != null) && (component != content)) { + Object parent = getParent(component); + if (parent != null) { + return processKeyPress(parent, e, keycode, component); + } + } + return false; + }*/ + //KeyEvent.VK_SPACE || + ((keycode == KeyEvent.VK_ENTER) && + (getString(component, "type", null) == "default")) || + ((keycode == KeyEvent.VK_ESCAPE) && //... + (getString(component, "type", null) == "cancel"))) { + //pressedkey = keychar; + invoke(component, "action"); + repaint(component); + return true; + } + } + else if ("checkbox" == classname) { + if (keychar == KeyEvent.VK_SPACE) { + changeCheck(component, true); + repaint(component); + return true; + } + } + else if ("combobox" == classname) { + Object combolist = get(component, "combolist"); + if (combolist == null) { + if (getBoolean(component, "editable", true) && + processField(component, shiftdown, controldown, modifiers, + keychar, keycode, false, false)) { + setInteger(component, "selected", -1, -1); + return true; + } + if ((keychar == KeyEvent.VK_SPACE) || (keycode == KeyEvent.VK_DOWN)) { + combolist = popup(component, classname); + int selected = getInteger(component, "selected", -1); + set(combolist, "inside", (selected != -1) ? + getItemImpl(component, "choice", selected) : + get(component, "choice")); //scroll to it! + } + else return false; + } else { + if ((keycode == KeyEvent.VK_UP) || + (keycode == KeyEvent.VK_DOWN) || (keycode == KeyEvent.VK_PAGE_UP) || + (keycode == KeyEvent.VK_PAGE_DOWN) || + (keycode == KeyEvent.VK_HOME) || (keycode == KeyEvent.VK_END)) { + Object selected = get(combolist, "inside"); + Object next = getListItem(component, combolist, + keycode, selected, "choice", null); + if (next != null) { + set(combolist, "inside", next); + Rectangle r = getRectangle(next, "bounds"); + scrollToVisible(combolist, r.x, r.y, 0, r.height); + if (selected != null) { repaint(combolist, "combolist", selected); } + repaint(combolist, "combolist", next); + } + } + else if ((keycode == KeyEvent.VK_ENTER) || (keychar == KeyEvent.VK_SPACE)) { + closeup(component, combolist, get(combolist, "inside")); //Alt+Up + } + else if (keycode == KeyEvent.VK_ESCAPE) { + closeup(component, combolist, null); + } + else return processField(component, shiftdown, controldown, modifiers, + keychar, keycode, false, false); + } + return true; + } + else if (("textfield" == classname) || ("passwordfield" == classname)) { + return processField(component, shiftdown, controldown, modifiers, + keychar, keycode, false, ("passwordfield" == classname)); + } + else if ("textarea" == classname) { + String text = getString(component, "text", ""); + int start = getInteger(component, "start", 0); + int end = getInteger(component, "end", 0); + + int istart = start; + int iend = end; + String insert = null; + if ((keycode == KeyEvent.VK_HOME) && !controldown) { + while ((iend > 0) && (text.charAt(iend - 1) != '\n')) { iend--; } + if (!shiftdown) { istart = iend; } + } + else if ((keycode == KeyEvent.VK_END) && !controldown) { + iend = text.indexOf('\n', end); + if (iend == -1) { iend = text.length(); } + if (!shiftdown) { istart = iend; } + } + else if ((keycode == KeyEvent.VK_UP) || + (keycode == KeyEvent.VK_PAGE_UP)) { + int prev = end; + while ((prev > 0) && (text.charAt(prev - 1) != '\n')) { prev--; } + if (prev != 0) { + int dx = end - prev; + int lines = (keycode == KeyEvent.VK_PAGE_UP) ? + (getRectangle(component, ":port").height / + getFontMetrics(getFont()).getHeight()) : 1; + int first = prev; + do { + prev = first; first--; lines--; + while ((first > 0) && (text.charAt(first - 1) != '\n')) { first--; } + } while ((first > 0) && (lines > 0)); + iend = Math.min(first + dx, prev - 1); + if (!shiftdown) { istart = iend; } + } + } + else if ((keycode == KeyEvent.VK_DOWN) || + (keycode == KeyEvent.VK_PAGE_DOWN)) { + int next = text.indexOf('\n', end); + if (next != -1) { + int prev = end; + while ((prev > 0) && (text.charAt(prev - 1) != '\n')) { prev--; } + if (keycode == KeyEvent.VK_PAGE_DOWN) { + int lines = getRectangle(component, ":port").height / + getFontMetrics(getFont()).getHeight(); + for (int more = 0; (lines > 1) && + ((more = text.indexOf('\n', next + 1)) != -1); next = more) { + lines--; + } + } + int last = text.indexOf('\n', next + 1); + iend = Math.min(next + 1 + end - prev, + (last == -1) ? (text.length() + 1) : last); + if (!shiftdown) { istart = iend; } + } + } + return changeField(component, text, insert, istart, iend, start, end) ? + true : processField(component, shiftdown, controldown, modifiers, + keychar, keycode, true, false); + } + else if ("tabbedpane" == classname) { + if ((keycode == KeyEvent.VK_RIGHT) || (keycode == KeyEvent.VK_DOWN) || + (keycode == KeyEvent.VK_LEFT) || (keycode == KeyEvent.VK_UP)) { + int selected = getInteger(component, "selected", 0); + boolean increase = (keycode == KeyEvent.VK_RIGHT) || (keycode == KeyEvent.VK_DOWN); + int newvalue = selected; + int n = increase ? getItemCountImpl(component, "tab") : 0; + int d = (increase ? 1 : -1); + for (int i = selected + d; increase ? (i < n) : (i >= 0); i += d) { + if (getBoolean(getItemImpl(component, "tab", i), "enabled", true)) { + newvalue = i; break; + } + } + if (newvalue != selected) { + setInteger(component, "selected", newvalue, 0); + repaint(component); + invoke(component, "action"); + } + } + } + else if ("spinbox" == classname) { + if ((keycode == KeyEvent.VK_UP) || (keycode == KeyEvent.VK_DOWN)) { + processSpin(component, (keycode == KeyEvent.VK_UP)? "up" : "down"); + return true; + } + return processField(component, shiftdown, controldown, modifiers, + keychar, keycode, false, false); + } + else if ("slider" == classname) { + int value = getInteger(component, "value", 0); + int d = 0; + if ((keycode == KeyEvent.VK_HOME) || (keycode == KeyEvent.VK_LEFT) || + (keycode == KeyEvent.VK_UP) || (keycode == KeyEvent.VK_PAGE_UP)) { + d = getInteger(component, "minimum", 0) - value; + if ((keycode == KeyEvent.VK_LEFT) || (keycode == KeyEvent.VK_UP)) { + d = Math.max(d, -getInteger(component, "unit", 5)); + } + else if (keycode == KeyEvent.VK_PAGE_UP) { + d = Math.max(d, -getInteger(component, "block", 25)); + } + } + else if ((keycode == KeyEvent.VK_END) || (keycode == KeyEvent.VK_RIGHT) || + (keycode == KeyEvent.VK_DOWN) || (keycode == KeyEvent.VK_PAGE_DOWN)) { + d = getInteger(component, "maximum", 100) - value; + if ((keycode == KeyEvent.VK_RIGHT) || (keycode == KeyEvent.VK_DOWN)) { + d = Math.min(d, getInteger(component, "unit", 5)); + } + else if (keycode == KeyEvent.VK_PAGE_DOWN) { + d = Math.min(d, getInteger(component, "block", 25)); + } + } + if (d != 0) { + setInteger(component, "value", value + d, 0); + repaint(component); + invoke(component, "action"); + } + } + else if ("splitpane" == classname) { + int divider = getInteger(component, "divider", -1); + int d = 0; + if (keycode == KeyEvent.VK_HOME) { + d = -divider; + } + else if ((keycode == KeyEvent.VK_LEFT) || (keycode == KeyEvent.VK_UP)) { + d = Math.max(-10, -divider); + } + else if ((keycode == KeyEvent.VK_END) || + (keycode == KeyEvent.VK_RIGHT) || (keycode == KeyEvent.VK_DOWN)) { + boolean horizontal = ("vertical" != get(component, "orientation")); + Rectangle bounds = getRectangle(component, "bounds"); + int max = (horizontal ? bounds.width : bounds.height) - 5; + d = max - divider; + if (keycode != KeyEvent.VK_END) { + d = Math.min(d, 10); + } + } + if (d != 0) { + setInteger(component, "divider", divider + d, -1); + validate(component); + } + } + else if ("list" == classname) { + return processList(component, shiftdown, controldown, keychar, keycode, "item", null); + } + else if ("table" == classname) { + return processList(component, shiftdown, controldown, keychar, keycode, "row", null); + } + else if ("tree" == classname) { + //? clear childs' selection, select this is its subnode was selected + if (keycode == KeyEvent.VK_LEFT) { + Object lead = get(component, "lead"); + if ((get(lead, "node") != null) && getBoolean(lead, "expanded", true)) { + setBoolean(lead, "expanded", false, true); + selectItem(component, lead, "node", "node"); + validate(component); + invoke(component, "collapse"); //lead + return true; + } + else { + Object parent = getParent(lead); + if (parent != component) { + selectItem(component, parent, "node", "node"); + setLead(component, lead, parent); + return true; + } + } + } + //? for interval mode select its all subnode or deselect all after + else if (keycode == KeyEvent.VK_RIGHT) { + Object lead = get(component, "lead"); + Object node = get(lead, "node"); + if (node != null) { + if (getBoolean(lead, "expanded", true)) { + selectItem(component, node, "node", "node"); + setLead(component, lead, node); + } + else { + setBoolean(lead, "expanded", true, true); + selectItem(component, lead, "node", "node"); + validate(component); + invoke(component, "expand"); //lead + } + return true; + } + } + return processList(component, shiftdown, controldown, keychar, keycode, "node", "node"); + } + else if ("menubar" == classname) { + Object previous = null; Object last = null; + for (Object i = get(component, "popupmenu"); + i != null; i = get(i, "popupmenu")) { + previous = last; last = i; + } + Object selected = get(last, "selected"); + Object hotpopup = ((selected != null) || (previous == null)) ? + last : previous; + if ((selected == null) && (previous != null)) { + selected = get(previous, "selected"); + } + + if ((keycode == KeyEvent.VK_UP) || (keycode == KeyEvent.VK_DOWN)) { + set(hotpopup, "selected", null); + popup(hotpopup, "popupmenu"); + selected = getMenu(hotpopup, + selected, keycode == KeyEvent.VK_DOWN, true); + set(hotpopup, "selected", selected); + repaint(hotpopup); + } + else if (keycode == KeyEvent.VK_LEFT) { + if (previous != null) { + selected = get(previous, "selected"); + set(previous, "selected", null); + popup(previous, "popupmenu"); + set(previous, "selected", selected); + repaint(previous); // , selected + } + else { + selected = getMenu(component, get(component, "selected"), false, false); + set(component, "selected", selected); + Object popup = popup(component, "menubar"); + set(popup, "selected", getMenu(popup, null, true, true)); + repaint(component); // , selected + } + } + else if (keycode == KeyEvent.VK_RIGHT) { + if ((previous != null) && (selected == null)) { + set(last, "selected", get(get(last, "menu"), "menu")); + repaint(last); // , selected + } + else if ((selected != null) && (getClass(selected) == "menu")) { + Object popup = popup(last, "popupmenu"); + set(popup, "selected", get(get(popup, "menu"), "menu")); + } + else { + selected = getMenu(component, get(component, "selected"), true, false); + set(component, "selected", selected); + Object popup = popup(component, "menubar"); + set(popup, "selected", getMenu(popup, null, true, true)); + repaint(component); // , selected + } + } + else if ((keycode == KeyEvent.VK_ENTER) || + (keychar == KeyEvent.VK_SPACE) || (keycode == KeyEvent.VK_ESCAPE)) { + if ((keycode != KeyEvent.VK_ESCAPE) && + getBoolean(selected, "enabled", true)) { + if ((selected != null) && (getClass(selected) == "checkboxmenuitem")) { + changeCheck(selected, false); + } + else invoke(selected, "action"); + } + closeup(component); + } + else return false; + return true; + } + return false; + } + + /** + * + */ + private boolean changeCheck(Object component, boolean box) { + String group = getString(component, "group", null); + if (group != null) { + if (getBoolean(component, "selected", false)) { return false; } + for (Object comp = get(getParent(component), + box ? "component" : "menu"); comp != null; comp = get(comp, ":next")) { + if (comp == component) { + setBoolean(component, "selected", true); + } + else if (group.equals(get(comp, "group")) && + getBoolean(comp, "selected", false)) { + setBoolean(comp, "selected", false); + if (box) { repaint(comp); } //checkbox only + } + } + } + else { + setBoolean(component, "selected", + !getBoolean(component, "selected", false), false); + } + invoke(component, "action"); + return true; + } + + /** + * + */ + private Object getMenu(Object component, Object part, + boolean forward, boolean popup) { + if (forward) { + if (part != null) { part = get(part, ":next"); } + if (part == null) { + part = get(popup ? get(component, "menu") : component, "menu"); + } + } + else { + Object prev = get(popup ? get(component, "menu") : component, "menu"); + for (Object next = get(prev, ":next"); + (next != null) && (next != part); next = get(next, ":next")) { + prev = next; + } + part = prev; + } + return (getClass(part) == "separator") ? + getMenu(component, part, forward, popup) : part; + } + + /** + * + */ + /*private boolean processKeyRelease(Object component, KeyEvent e, int keycode) { + return true; + }*/ + + /** + * + */ + private boolean processField(Object component, + boolean shiftdown, boolean controldown, int modifiers, + int keychar, int keycode, boolean multiline, boolean hidden) { + String text = getString(component, "text", ""); + int start = getInteger(component, "start", 0); + int end = getInteger(component, "end", 0); + boolean editable = getBoolean(component, "editable", true); + + int istart = start; + int iend = end; + String insert = null; + //midp if (editable && (keychar != 0)) { + if (editable && (keychar != 0) && //java + ((modifiers == 0) || (modifiers == InputEvent.SHIFT_MASK))) { //java + insert = String.valueOf((char) keychar); + } + else if (multiline && editable && (keycode == KeyEvent.VK_ENTER)) { + insert = "\n"; + } + else if (editable && (keycode == KeyEvent.VK_BACK_SPACE)) { + insert = ""; + if (start == end) { istart -= 1; } + } + else if (keycode == KeyEvent.VK_END) { + iend = text.length(); + if (!shiftdown) { istart = iend; } + } + else if (keycode == KeyEvent.VK_HOME) { + iend = 0; + if (!shiftdown) { istart = iend; } + } + else if (keycode == KeyEvent.VK_LEFT) { + //java> + if (controldown) { + for (int i = 0; i < 2; i++) { + while ((iend > 0) && ((i != 0) == + Character.isLetterOrDigit(text.charAt(iend - 1)))) { iend--; } + } + } else { + iend -= 1; + } + //KeyEvent.VK_RIGHT) { + //java> + if (controldown) { + for (int i = 0; i < 2; i++) { + while ((iend < text.length()) && ((i == 0) == + Character.isLetterOrDigit(text.charAt(iend)))) { iend++; } + } + } else { + iend += 1; + } + //KeyEvent.VK_DELETE)) { + insert = ""; + if (start == end) { iend += 1; } + } + else if (controldown && + ((keycode == KeyEvent.VK_A) || (keycode == 0xBF))) { + istart = 0; // KeyEvent.VK_SLASH + iend = text.length(); + } + else if (controldown && (keycode == 0xDC)) { + istart = iend = text.length(); // KeyEvent.VK_BACK_SLASH + } + else if ((editable && !hidden && controldown && (keycode == KeyEvent.VK_X)) || + (!hidden && controldown && (keycode == KeyEvent.VK_C))) { + if (start != end) { + clipboard = text.substring( + Math.min(start, end), Math.max(start, end)); + //java> + try { + /* Personal Basis Profile doesn't contain datatransfer package + Toolkit toolkit = getToolkit(); + Object systemclipboard = toolkit.getClass().getMethod("getSystemClipboard", null).invoke(toolkit, null); + Class selectionclass = Class.forName("java.awt.datatransfer." + "StringSelection"); + Object selection = selectionclass.getConstructor(new Class[] { String.class }). + newInstance(new Object[] { clipboard }); + systemclipboard.getClass().getMethod("setContents", new Class[] { + Class.forName("java.awt.datatransfer." + "Transferable"), + Class.forName("java.awt.datatransfer." + "ClipboardOwner") }). + invoke(systemclipboard, new Object[] { selection, null });*/ + getToolkit().getSystemClipboard().setContents( + new StringSelection(clipboard), null); + } catch (Exception exc) {} + //KeyEvent.VK_X) { insert = ""; } + } + } + else if (editable && controldown && (keycode == KeyEvent.VK_V)) { + //java> + try { + /* no datatransfer package in PBP + Toolkit toolkit = getToolkit(); + Object systemclipboard = toolkit.getClass().getMethod("getSystemClipboard", null).invoke(toolkit, null); + Object contents = systemclipboard.getClass().getMethod("getContents", new Class[] { Object.class }). + invoke(systemclipboard, new Object[] { this }); + Class dataflavor = Class.forName("java.awt.datatransfer." + "DataFlavor"); + insert = (String) (contents.getClass().getMethod("getTransferData", new Class[] { dataflavor }). + invoke(contents, new Object[] { dataflavor.getField("stringFlavor").get(null) }));*/ + insert = (String) getToolkit().getSystemClipboard(). + getContents(this).getTransferData(DataFlavor.stringFlavor); + } catch (Exception exc) { + insert = clipboard; + } + // 0x1f) && (ckey < 0x7f)) || + ((ckey > 0x9f) && (ckey < 0xffff)) || + (multiline && (ckey == '\n'))) { + filtered.append(ckey); + } + } + if (filtered.length() != insert.length()) { + insert = filtered.toString(); + } + } + return changeField(component, text, insert, istart, iend, start, end); + } + + /** + * + */ + private boolean changeField(Object component, String text, String insert, + int movestart, int moveend, int start, int end) { + if ((insert == null) && (start == movestart) && (end == moveend)) { + return false; + } + movestart = Math.max(0, Math.min(movestart, text.length())); + moveend = Math.max(0, Math.min(moveend, text.length())); + if (insert != null) { + int min = Math.min(movestart, moveend); + set(component, "text", text.substring(0, min) + insert + + text.substring(Math.max(movestart, moveend))); + movestart = moveend = min + insert.length(); + invoke(component, "action"); + } + if (start != movestart) { setInteger(component, "start", movestart, 0); } + if (end != moveend) { setInteger(component, "end", moveend, 0); } + if ((insert != null) || (start != movestart) || (end != moveend)) { + validate(component); + } + return true; + } + + /** + * + */ + private boolean processList(Object component, boolean shiftdown, boolean controldown, + int keychar, int keycode, String itemname, String leafname) { + if ((keycode == KeyEvent.VK_UP) || + (keycode == KeyEvent.VK_DOWN) || (keycode == KeyEvent.VK_PAGE_UP) || + (keycode == KeyEvent.VK_PAGE_DOWN) || + (keycode == KeyEvent.VK_HOME) || (keycode == KeyEvent.VK_END)) { + Object lead = get(component, "lead"); + Object row = getListItem(component, component, + keycode, lead, itemname, leafname); + if (row != null) { + String selection = getString(component, "selection", "single"); + if (shiftdown && (selection != "single") && (lead != null)) { + extend(component, lead, row, itemname, leafname); + } + else if (!controldown) { + selectItem(component, row, itemname, leafname); + } + setLead(component, lead, row); + Rectangle r = getRectangle(row, "bounds"); + scrollToVisible(component, r.x, r.y, 0, r.height - 1); + return true; + } + } + else if (keychar == KeyEvent.VK_SPACE) { + select(component, get(component, "lead"), + itemname, leafname, shiftdown, controldown); //... + return true; + } + else if (controldown) { + if (((keycode == KeyEvent.VK_A) || (keycode == 0xBF)) && //KeyEvent.VK_SLASH + (getString(component, "selection", "single") != "single")) { + selectAll(component, true, itemname, leafname); + return true; + } + else if (keycode == 0xDC) { //KeyEvent.VK_BACK_SLASH + selectAll(component, false, itemname, leafname); + return true; + } + } + return false; + } + + /** + * + */ + private Object getListItem(Object component, Object scrollpane, + int keycode, Object lead, String itemname, String leafname) { + Object row = null; + if (keycode == KeyEvent.VK_UP) { + for (Object prev = get(component, itemname); prev != lead; + prev = getNextItem(component, prev, leafname)) { + row = prev; // component -> getParent(lead) + } + } + else if (keycode == KeyEvent.VK_DOWN) { + row = (lead == null) ? get(component, itemname) : + getNextItem(component, lead, leafname); + } + else if ((keycode == KeyEvent.VK_PAGE_UP) || + (keycode == KeyEvent.VK_PAGE_DOWN)) { + Rectangle view = getRectangle(scrollpane, ":view"); + Rectangle port = getRectangle(scrollpane, ":port"); + Rectangle rl = (lead != null) ? getRectangle(lead, "bounds") : null; + int vy = (keycode == KeyEvent.VK_PAGE_UP) ? + view.y : (view.y + port.height - 2); + if ((keycode == KeyEvent.VK_PAGE_UP) && + (rl != null) && (rl.y <= view.y)) { + vy -= port.height - 2; + } + if ((keycode == KeyEvent.VK_PAGE_DOWN) && + (rl != null) && (rl.y + rl.height >= view.y + port.height - 2)) { + vy += port.height - 2; + } + for (Object item = get(component, itemname); item != null; + item = getNextItem(component, item, leafname)) { + Rectangle r = getRectangle(item, "bounds"); + if (keycode == KeyEvent.VK_PAGE_UP) { + row = item; + if (r.y + r.height > vy) { break; } + } else { + if (r.y > vy) { break; } + row = item; + } + } + } + else if (keycode == KeyEvent.VK_HOME) { + row = get(component, itemname); + } + else if (keycode == KeyEvent.VK_END) { + for (Object last = lead; last != null; + last = getNextItem(component, last, leafname)) { + row = last; + } + } + return row; + } + + /** + * + */ + private void selectAll(Object component, + boolean selected, String itemname, String leafname) { + boolean changed = false; + for (Object item = get(component, itemname); + item != null; item = getNextItem(component, item, leafname)) { + if (setBoolean(item, "selected", selected, false)) { + repaint(component, null, item); changed = true; + } + } + set(component, "anchor", null); + if (changed) {invoke(component, "action"); } + } + + /** + * + */ + private void selectItem(Object component, + Object row, String itemname, String leafname) { + boolean changed = false; + for (Object item = get(component, itemname); + item != null; item = getNextItem(component, item, leafname)) { + if (setBoolean(item, "selected", (item == row), false)) { + repaint(component, null, item); changed = true; + } + } + set(component, "anchor", null); + if (changed) { invoke(component, "action"); } + } + + /** + * + */ + private void extend(Object component, Object lead, + Object row, String itemname, String leafname) { + Object anchor = get(component, "anchor"); + if (anchor == null) { set(component, "anchor", anchor = lead); } + char select = 'n'; boolean changed = false; + for (Object item = get(component, itemname); // anchor - row + item != null; item = getNextItem(component, item, leafname)) { + if (item == anchor) select = (select == 'n') ? 'y' : 'r'; + if (item == row) select = (select == 'n') ? 'y' : 'r'; + if (setBoolean(item, "selected", (select != 'n'), false)) { + repaint(component, null, item); changed = true; + } + if (select == 'r') select = 'n'; + } + if (changed) { invoke(component, "action"); } + } + + /** + * + */ + private void setLead(Object component, Object oldlead, Object lead) { + if (oldlead != lead) { //? + if (oldlead != null) { repaint(component, null, oldlead); } + set(component, "lead", lead); + repaint(component, null, lead); + } + } + + /*public void repaint(int x, int y, int width, int height) { + System.out.println("repaint(" + x + ", " + y + ", " + width + ", " + height + ")"); + super.repaint(x, y, width, height); + }*/ + + /** + * + */ + private void handleMouseEvent(int x, int y, int clickcount, + boolean shiftdown, boolean controldown, boolean popuptrigger, + int id, Object component, Object part) { + if (id == MouseEvent.MOUSE_ENTERED) { + setTimer(750L); + } + else if (id == MouseEvent.MOUSE_EXITED) { + hideTip(); + } + if (!getBoolean(component, "enabled", true)) { return; } + String classname = getClass(component); + if (("button" == classname) || ("checkbox" == classname)) { + if ((id == MouseEvent.MOUSE_ENTERED) || + (id == MouseEvent.MOUSE_EXITED) || + (id == MouseEvent.MOUSE_PRESSED) || + (id == MouseEvent.MOUSE_RELEASED)) { + if (id == MouseEvent.MOUSE_PRESSED) { + setFocus(component); + } + else if ((id == MouseEvent.MOUSE_RELEASED) && + (mouseinside == component)) { + if ("checkbox" == classname) { + changeCheck(component, true); + } + else invoke(component, "action"); + } + repaint(component); + } + } + else if ("combobox" == classname) { + boolean editable = getBoolean(component, "editable", true); + if (editable && (part == null)) { + Image icon = null; + int left = ((id == MouseEvent.MOUSE_PRESSED) && + ((icon = getIcon(component, "icon", null)) != null)) ? + icon.getWidth(this) : 0; + processField(x, y, clickcount, id, component, part, false, false, left); + } + else if (part != "icon") { // part = "down" + if (((id == MouseEvent.MOUSE_ENTERED) || + (id == MouseEvent.MOUSE_EXITED)) && (mousepressed == null)) { + if (editable) { repaint(component, "combobox", part); } + else { repaint(component); } + } + else if (id == MouseEvent.MOUSE_PRESSED) { + Object combolist = get(component, "combolist"); + if (combolist == null) { + setFocus(component); + repaint(component); + popup(component, classname); + } else { + closeup(component, combolist, null); + } + } + else if (id == MouseEvent.MOUSE_RELEASED) { + if (mouseinside != component) { + Object combolist = get(component, "combolist"); + closeup(component, combolist, + (mouseinside == combolist) ? insidepart : null); + } else { + repaint(component); + } + } + } + } + else if ("combolist" == classname) { + if (!processScroll(x, y, id, component, part)) { + if ((id == MouseEvent.MOUSE_ENTERED) || (id == DRAG_ENTERED)) { + if (part != null) { + // repaint previous inside + set(component, "inside", part); + repaint(component, classname, part); + } + } + else if ((id == MouseEvent.MOUSE_EXITED) || (id == DRAG_EXITED)) { + if (part != null) { + set(component, "inside", null); + repaint(component, classname, part); + } + } + else if (id == MouseEvent.MOUSE_RELEASED) { + closeup(get(component, "combobox"), component, part); + } + } + } + else if (("textfield" == classname) || ("passwordfield" == classname)) { + processField(x, y, clickcount, id, component, part, + false, ("passwordfield" == classname), 0); + } + else if ("textarea" == classname) { + if (!processScroll(x, y, id, component, part)) { + processField(x, y, clickcount, id, component, part, true, false, 0); + } + } + //java> + else if ("desktop" == classname) { + if (id == MouseEvent.MOUSE_ENTERED) { + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + } + else if (id == MouseEvent.MOUSE_EXITED) { + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + } + //MouseEvent.MOUSE_ENTERED) || + (id == MouseEvent.MOUSE_EXITED) || + (id == MouseEvent.MOUSE_PRESSED) || + (id == MouseEvent.MOUSE_RELEASED)) { + if (id == MouseEvent.MOUSE_PRESSED) { + setFocus(component); + if (processSpin(component, part)) { setTimer(375L); } + //settext: start end selection, parse exception... + } + else { + if (id == MouseEvent.MOUSE_RELEASED) { + setTimer(0L); + } + } + repaint(component, classname, part); + } + } + } + else if ("tabbedpane" == classname) { + if ((id == MouseEvent.MOUSE_ENTERED) || + (id == MouseEvent.MOUSE_EXITED)) { + if ((part != null) && getBoolean(part, "enabled", true) && + (getInteger(component, "selected", 0) != getIndex(component, "tab", part))) { + repaint(component, "tabbedpane", part); + } + } + else if ((part != null) && (id == MouseEvent.MOUSE_PRESSED) && + getBoolean(part, "enabled", true)) { + int selected = getInteger(component, "selected", 0); + int current = getIndex(component, "tab", part); + if (selected == current) { + setFocus(component); + repaint(component, "tabbedpane", part); + } + else { + setInteger(component, "selected", current, 0); + //Object tabcontent = getItemImpl(component, "component", current); + //setFocus((tabcontent != null) ? tabcontent : component); + setNextFocusable(component, false); + repaint(component); + invoke(component, "action"); + } + } + } + else if ("slider" == classname) { + if ((id == MouseEvent.MOUSE_PRESSED) || + (id == MouseEvent.MOUSE_DRAGGED)) { + if (id == MouseEvent.MOUSE_PRESSED) { + setReference(component, block / 2, block / 2); + setFocus(component); + } + int minimum = getInteger(component, "minimum", 0); + int maximum = getInteger(component, "maximum", 100); + int value = getInteger(component, "value", 50); + Rectangle bounds = getRectangle(component, "bounds"); + boolean horizontal = ("vertical" != get(component, "orientation")); + int newvalue = minimum + + (horizontal ? (mousex - referencex) : (mousey - referencey)) * + (maximum - minimum) / + ((horizontal ? bounds.width : bounds.height) - block); //... +0.5 + newvalue = Math.max(minimum, Math.min(newvalue, maximum)); + if (value != newvalue) { + setInteger(component, "value", newvalue, 50); + invoke(component, "action"); + } + if ((value != newvalue) || (id == MouseEvent.MOUSE_PRESSED)) { + repaint(component); + } + } + } + else if ("splitpane" == classname) { + if (id == MouseEvent.MOUSE_PRESSED) { + setReference(component, 2, 2); + } + else if (id == MouseEvent.MOUSE_DRAGGED) { + int divider = getInteger(component, "divider", -1); + boolean horizontal = ("vertical" != get(component, "orientation")); + int moveto = horizontal ? (mousex - referencex) : + (mousey - referencey); + Rectangle bounds = getRectangle(component, "bounds"); + moveto = Math.max(0, Math.min(moveto, + Math.abs(horizontal ? bounds.width : bounds.height) - 5)); + if (divider != moveto) { + setInteger(component, "divider", moveto, -1); + validate(component); + } + } + //java> + else if ((id == MouseEvent.MOUSE_ENTERED) && (mousepressed == null)) { + boolean horizontal = ("vertical" != get(component, "orientation")); + setCursor(Cursor.getPredefinedCursor(horizontal ? + Cursor.E_RESIZE_CURSOR : Cursor.S_RESIZE_CURSOR)); + } + else if (((id == MouseEvent.MOUSE_EXITED) && (mousepressed == null)) || + ((id == MouseEvent.MOUSE_RELEASED) && (mouseinside != component))) { + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + //MouseEvent.MOUSE_PRESSED)|| + ((id == MouseEvent.MOUSE_DRAGGED) && + !shiftdown && !controldown)) && + !popuptrigger) { // e.getClickCount() + Rectangle view = getRectangle(component, ":view"); + Rectangle viewport = getRectangle(component, ":port"); + int my = mousey + view.y - referencey; + String itemname = ("list" == classname) ? "item" : + (("table" == classname) ? "row" : "node"); + String subitem = ("tree" == classname) ? "node" : null; + for (Object item = get(component, itemname); item != null;) { + Rectangle r = getRectangle(item, "bounds"); + if (my < r.y + r.height) { + if (id == MouseEvent.MOUSE_DRAGGED) { //!!! + scrollToVisible(component, r.x, r.y, 0, r.height - 1); + } + else if ("tree" == classname) { + int mx = mousex + view.x - referencex; + if (mx < r.x) { + if ((mx >= r.x - block) && (get(item, "node") != null)) { + boolean expanded = getBoolean(item, "expanded", true); + setBoolean(item, "expanded", !expanded, true); + selectItem(component, item, "node", "node"); + setLead(component, get(component, "lead"), item); + setFocus(component); + validate(component); + invoke(component, expanded ? "collapse" : "expand"); //item + } + break; + } + } + if ((id != MouseEvent.MOUSE_DRAGGED) || + !getBoolean(item, "selected", false)) { + select(component, item, itemname, subitem, shiftdown, controldown); + if (id != MouseEvent.MOUSE_DRAGGED) { + if (setFocus(component)) { repaint(component, classname, item); } //? + } + } + break; + } + item = getNextItem(component, item, subitem); + } + } + } + } + else if ("menubar" == classname) { + Object selected = get(component, "selected"); + if (((id == MouseEvent.MOUSE_ENTERED) || (id == MouseEvent.MOUSE_EXITED)) && + (part != null) && (selected == null)) { + repaint(component, classname, part); + } + else if ((part != null) && ((selected == null) ? + (id == MouseEvent.MOUSE_PRESSED) : + ((id == MouseEvent.MOUSE_ENTERED) || (id == DRAG_ENTERED)))) { + set(component, "selected", part); + popup(component, classname); + repaint(component, classname, part); + } + else if ((id == MouseEvent.MOUSE_PRESSED) && (selected != null)) { + closeup(component); + } + else if (id == MouseEvent.MOUSE_RELEASED) { + if ((part != insidepart) && + ((insidepart == null) || (getClass(insidepart) != "menu"))) { + if ((insidepart != null) && getBoolean(insidepart, "enabled", true)) { + if (getClass(insidepart) == "checkboxmenuitem") { + changeCheck(insidepart, false); + } + else invoke(insidepart, "action"); + } + closeup(component); + } + } + } + else if ("popupmenu" == classname) { + if (part != null) { + if ((id == MouseEvent.MOUSE_ENTERED) || (id == DRAG_ENTERED)) { + set(component, "selected", part); + popup(component, classname); + repaint(component, classname, part); + } + else if (id == MouseEvent.MOUSE_RELEASED) { + if ((insidepart == null) || (getClass(insidepart) != "menu")) { + Object menubar = part; + do { + menubar = getParent(menubar); + } while (getClass(menubar) != "menubar"); + if ((insidepart != null) && getBoolean(insidepart, "enabled", true)) { + if (getClass(insidepart) == "checkboxmenuitem") { + changeCheck(insidepart, false); + } + else invoke(insidepart, "action"); + } + closeup(menubar); + } + } + else if ((id == MouseEvent.MOUSE_EXITED) || (id == DRAG_EXITED)) { + if (getClass(part) != "menu") { + set(component, "selected", null); + } + repaint(component, classname, part); + } + } + } + else if ("dialog" == classname) { + if (part == "header") { + if (id == MouseEvent.MOUSE_PRESSED) { + referencex = mousex; referencey = mousey; + if (!getBoolean(component, "modal", false) && + (get(content, "component") != component)) { + removeItemImpl(content, "component", component); + insertItem(content, "component", component, 0); + set(component, ":parent", content); + repaint(component); + } + } + else if (id == MouseEvent.MOUSE_DRAGGED) { + Rectangle bounds = getRectangle(component, "bounds"); + int dx = mousex - referencex; int dy = mousey - referencey; + repaint(component, + bounds.x + Math.min(0, dx), bounds.y + Math.min(0, dy), + bounds.width + Math.abs(dx), bounds.height + Math.abs(dy)); + bounds.x += dx; bounds.y += dy; + referencex = mousex; referencey = mousey; + } + } + } + } + + /** + * + */ + private void setReference(Object component, int x, int y) { + referencex = x; referencey = y; + for (; component != null; component = getParent(component)) { + Rectangle bounds = getRectangle(component, "bounds"); + referencex += bounds.x; referencey += bounds.y; + } + } + + /** + * + */ + private void select(Object component, Object row, String first, + String child, boolean shiftdown, boolean controldown) { + String selection = getString(component, "selection", "single"); + Object lead = null; + if (shiftdown && (selection != "single") && + ((lead = get(component, "lead")) != null)) { + extend(component, lead, row, first, child); + } + else { + if (controldown && (selection == "multiple")) { + setBoolean(row, "selected", + !getBoolean(row, "selected", false), false); + repaint(component, null, row); + invoke(component, "action"); + set(component, "anchor", null); + } + else if (controldown && getBoolean(row, "selected", false)) { + for (Object item = row; + item != null; item = getNextItem(component, item, child)) { + if (setBoolean(item, "selected", false, false)) { + repaint(component, null, item); + } + } + invoke(component, "action"); + set(component, "anchor", null); + } + else { + selectItem(component, row, first, child); + } + } + setLead(component, (lead != null) ? lead : get(component, "lead"), row); + } + + /** + * + */ + private Object getNextItem(Object component, + Object item, String subitem) { + if (subitem == null) { return get(item, ":next"); } + Object next = get(item, subitem); + if ((next == null) || !getBoolean(item, "expanded", true)) { + while ((item != component) && ((next = get(item, ":next")) == null)) { + item = getParent(item); + } + } + return next; + } + + /** + * + */ + private void processField(int x, int y, int clickcount, + int id, Object component, + Object part, boolean multiline, boolean hidden, int left) { + if (id == MouseEvent.MOUSE_PRESSED) { + setReference(component, 2 + left, 2); + int mx = x - referencex; + int my = 0; + if (!multiline) { + mx += getInteger(component, "offset", 0); + } else { + Rectangle view = getRectangle(component, ":view"); + mx += view.x - 1; + my = y - referencey + view.y - 1; + } + int caretstart = getCaretLocation(component, mx, my, hidden); + int caretend = caretstart; + //java> + if (clickcount > 1) { + String text = getString(component, "text", ""); + while ((caretstart > 0) && ((clickcount == 2) ? + Character.isLetterOrDigit(text.charAt(caretstart - 1)) : + (text.charAt(caretstart - 1) != '\n'))) { caretstart--; } + while ((caretend < text.length()) && ((clickcount == 2) ? + Character.isLetterOrDigit(text.charAt(caretend)) : + (text.charAt(caretend) != '\n'))) { caretend++; } + } + //MouseEvent.MOUSE_DRAGGED) { + int mx = x - referencex; + int my = 0; + if (!multiline) { + mx += getInteger(component, "offset", 0); + } else { + Rectangle view = getRectangle(component, ":view"); + mx += view.x - 1; + my = y - referencey + view.y - 1; + } + int dragcaret = getCaretLocation(component, mx, my, hidden); + if (dragcaret != getInteger(component, "end", 0)) { + setInteger(component, "end", dragcaret, 0); + validate(component); // caret check only + } + } + //java> + else if ((id == MouseEvent.MOUSE_ENTERED) && (mousepressed == null)) { + setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)); + } + else if (((id == MouseEvent.MOUSE_EXITED) && (mousepressed == null)) || + ((id == MouseEvent.MOUSE_RELEASED) && + ((mouseinside != component) || (insidepart != null)))) { + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + //FontMetrics fm = getFontMetrics(getFont()); + for (int i = 0, j = 0; true; i = j + 1) { + j = text.indexOf('\n', i); + if ((j == -1) || y < fm.getHeight()) { + if (j == -1) { j = text.length(); } + for (int k = i; k < j; k++) { + int charwidth = fm.charWidth(hidden ? '*' : text.charAt(k)); + if (x <= (charwidth / 2)) { + return k; + } + x -= charwidth; + } + return j; + } + y -= fm.getHeight(); + } + } + + /** + * + */ + private boolean processScroll(int x, int y, + int id, Object component, Object part) { + if ((part == "up") || (part == "down") || + (part == "left") || (part == "right")) { + if ((id == MouseEvent.MOUSE_ENTERED) || + (id == MouseEvent.MOUSE_EXITED) || + (id == MouseEvent.MOUSE_PRESSED) || + (id == MouseEvent.MOUSE_RELEASED)) { + if (id == MouseEvent.MOUSE_PRESSED) { + if (processScroll(component, part)) { + setTimer(300L); return true; + } + } + else { + if (id == MouseEvent.MOUSE_RELEASED) { setTimer(0L); } + repaint(component, null, part); + } + } + } + else if ((part == "uptrack") || (part == "downtrack") || + (part == "lefttrack") || (part == "righttrack")) { + if (id == MouseEvent.MOUSE_PRESSED) { + if (processScroll(component, part)) { + setTimer(300L); + } + } + else if (id == MouseEvent.MOUSE_RELEASED) { + setTimer(0L); + } + } + else if ((part == "vknob") || (part == "hknob")) { + if (id == MouseEvent.MOUSE_PRESSED) { + Rectangle port = getRectangle(component, ":port"); + Rectangle view = getRectangle(component, ":view"); + if (part == "hknob") { + referencex = x - + view.x * (port.width - 2 * block) / view.width; + } else { + referencey = y - + view.y * (port.height - 2 * block) / view.height; + } + } + else if (id == MouseEvent.MOUSE_DRAGGED) { + Rectangle port = getRectangle(component, ":port"); + Rectangle view = getRectangle(component, ":view"); + if (part == "hknob") { + int viewx = (x - referencex) * + view.width / (port.width - 2 * block); + viewx = Math.max(0, Math.min(viewx, view.width - port.width + 2)); + if (view.x != viewx) { + view.x = viewx; + repaint(component, null, "horizontal"); + } + } else { + int viewy = (y - referencey) * + view.height / (port.height - 2 * block); + viewy = Math.max(0, Math.min(viewy, view.height - port.height + 2)); + if (view.y != viewy) { + view.y = viewy; + repaint(component, null, "vertical"); + } + } + } + } + else if (part == "corner") { + part = "corner"; // compiler bug + } + else { + if (id == MouseEvent.MOUSE_PRESSED) { + Rectangle port = getRectangle(component, ":port"); + setReference(component, port.x + 1, port.y + 1); + } + return false; + } + return true; + } + + /** + * + */ + private boolean processScroll(Object component, Object part) { + Rectangle view = getRectangle(component, ":view"); + Rectangle port = ((part == "left") || (part == "up")) ? null : + getRectangle(component, ":port"); + int dx = 0; int dy = 0; + if (part == "left") { dx = -10; } + else if (part == "lefttrack") { dx = -port.width; } + else if (part == "right") { dx = 10; } + else if (part == "righttrack") { dx = port.width; } + else if (part == "up") { dy = -10; } + else if (part == "uptrack") { dy = -port.height; } + else if (part == "down") { dy = 10; } + else if (part == "downtrack") { dy = port.height; } + if (dx != 0) { + dx = (dx < 0) ? Math.max(-view.x, dx) : + Math.min(dx, view.width - port.width + 2 - view.x); + } + else if (dy != 0) { + dy = (dy < 0) ? Math.max(-view.y, dy) : + Math.min(dy, view.height - port.height + 2 - view.y); + } + else return false; + view.x += dx; view.y += dy; + repaint(component, null, (dx != 0) ? "horizontal" : "vertical"); + return (((part == "left") || (part == "lefttrack")) && (view.x > 0)) || + (((part == "right") || (part == "righttrack")) && + (view.x < view.width - port.width + 2)) || + (((part == "up") || (part == "uptrack")) && (view.y > 0)) || + (((part == "down") || (part == "downtrack")) && + (view.y < view.height - port.height + 2)); + } + + /** + * + */ + private boolean processSpin(Object component, Object part) { + String text = getString(component, "text", null); + if (text != null) { + try { + String value = String.valueOf( + Integer.parseInt(text) + ((part == "up") ? 1 : -1)); + setString(component, "text", value, null); + setInteger(component, "start", value.length(), 0); + setInteger(component, "end", 0, 0); + repaint(component, "spinbox", null); + invoke(component, "action"); + return true; + } catch (NumberFormatException nfe) {} + } + return false; + } + + //java> + /*public void setEventHandler(Object component, Object eventhandler) { + set(component, ":handler", eventhandler); + }*/ + + /** + * + */ + private void invoke(Object component, String event) { + Method method = (Method) get(component, event); + if (method != null) { + try { + method.invoke(this, null); + } catch (InvocationTargetException ite) { + ite.getTargetException().printStackTrace(); + } catch (Exception exc) { + exc.printStackTrace(); + } + } + } + //Rectangle bounds = getRectangle(component, "bounds"); + if ((bounds == null) || !(bounds.contains(x, y))) { return false; } //java + //midp if ((bounds == null) || (x < bounds.x) || (x - bounds.x >= bounds.width) || + //midp (y < bounds.y) || (y - bounds.y >= bounds.height)) { return false; } + mouseinside = component; + x -= bounds.x; y -= bounds.y; + String classname = getClass(component); + + if ("combobox" == classname) { + if (getBoolean(component, "editable", true) && (x <= bounds.width - block)) { + Image icon = getIcon(component, "icon", null); + insidepart = ((icon != null) && (x <= 2 + icon.getWidth(this))) ? + "icon" : null; + } else { + insidepart = "down"; + } + } + else if ("combolist" == classname) { + if (!findScrollPane(component, x, y, bounds)) { + y += getRectangle(component, ":view").y; + for (Object choice = get(get(component, "combobox"), "choice"); + choice != null; choice = get(choice, ":next")) { + Rectangle r = getRectangle(choice, "bounds"); + if ((y >= r.y) && (y < r.y + r.height)) { + insidepart = choice; break; + } + } + } + } + else if ("textarea" == classname) { + findScrollPane(component, x, y, bounds); + } + else if ("tabbedpane" == classname) { + Object tabcontent = getItemImpl(component, + "component", getInteger(component, "selected", 0)); + if ((tabcontent == null) || !findComponent(tabcontent, x, y)) { + for (Object comp = get(component, "tab"); + comp != null; comp = get(comp, ":next")) { + Rectangle r = getRectangle(comp, "bounds"); + if (r.contains(x, y)) { //java + //midp if ((x >= r.x) && (x - r.x < r.width) && (y >= r.y) && (y - r.y < r.height)) { + insidepart = comp; break; + } + } + } + } + else if (("panel" == classname) || ("desktop" == classname) || + ("dialog" == classname)) { + if (("dialog" == classname) && + (y < 4 + getInteger(component, "titleheight", 0))) { + insidepart = "header"; + } else { + for (Object comp = get(component, "component"); + comp != null; comp = get(comp, ":next")) { + if (findComponent(comp, x, y)) { break; } + if (("desktop" == classname) && + getBoolean(comp, "modal", false)) { break; } // && dialog + } + } + } + else if ("spinbox" == classname) { + insidepart = (x <= bounds.width - block) ? null : + ((y <= bounds.height / 2) ? "up" : "down"); + } + else if ("splitpane" == classname) { + Object comp1 = get(component, "component"); + if (comp1 != null) { + if (!findComponent(comp1, x, y)) { + Object comp2 = get(comp1, ":next"); + if (comp2 != null) { + findComponent(comp2, x, y); + } + } + } + } + else if ("list" == classname) { + findScrollPane(component, x, y, bounds); + } + else if ("table" == classname) { + findScrollPane(component, x, y, bounds); + } + else if ("tree" == classname) { + findScrollPane(component, x, y, bounds); + } + else if ("menubar" == classname) { + for (Object menu = get(component, "menu"); + menu != null; menu = get(menu, ":next")) { + Rectangle r = getRectangle(menu, "bounds"); + if ((x >= r.x) && (x < r.x + r.width)) { + insidepart = menu; break; + } + } + } + else if ("popupmenu" == classname) { + for (Object menu = get(get(component, "menu"), "menu"); + menu != null; menu = get(menu, ":next")) { + Rectangle r = getRectangle(menu, "bounds"); + if ((y >= r.y) && (y < r.y + r.height)) { + insidepart = menu; break; + } + } + } + return true; + } + + /** + * + */ + private boolean findScrollPane(Object component, + int x, int y, Rectangle bounds) { + Rectangle port = getRectangle(component, ":port"); + if ((x < port.x) || (y < port.y) || + ((x >= port.x + port.width) && (y >= port.y + port.height))) { + insidepart = "corner"; + } + else if ((x >= port.x + port.width) || (y >= port.y + port.height)) { + boolean horizontal = (y >= port.y + port.height); + int p = horizontal ? (x - port.x) : (y - port.y); + int portsize = horizontal ? port.width : port.height; + int button = Math.min(block, portsize / 2); + if (p < button) { + insidepart = horizontal ? "left" : "up"; + } + else if (p >= portsize - button) { + insidepart = horizontal ? "right" : "down"; + } + else { + Rectangle view = getRectangle(component, ":view"); + int viewp = horizontal ? view.x : view.y; + int viewsize = horizontal ? view.width : view.height; + int track = portsize - (2 * button); + int knob = Math.min(track, + Math.max(track * (portsize - 2) / viewsize, 6)); + int decrease = viewp * (track - knob) / (viewsize - portsize + 2); + if (p < button + decrease) { + insidepart = horizontal ? "lefttrack" : "uptrack"; + } + else if (p < button + decrease + knob) { + insidepart = horizontal ? "hknob" : "vknob"; + } + else { + insidepart = horizontal ? "righttrack" : "downtrack"; + } + } + } + else { return false; } + return true; + } + + /** + * + */ + private void repaint(Object component, Object classname, Object part) { + Rectangle b = getRectangle(component, "bounds"); + if ((classname == "combobox") || (classname == "spinbox")) { + boolean down = (part == "up") || (part == "down"); // else text + repaint(component, down ? (b.x + b.width - block) : b.x, b.y, + down ? block : (b.width - block), b.height); + } + //else if (classname == "dialog") {} + //int titleheight = getInteger(component, "titleheight", 0); + //else if (classname == "splitpane") {} + else if ((classname == "tabbedpane") || + (classname == "menubar") || (classname == "popupmenu")) { + Rectangle r = getRectangle(part, "bounds"); + repaint(component, b.x + r.x, b.y + r.y, + (classname == "popupmenu") ? b.width : r.width, r.height); + } + else //if ((classname == "combolist") || (classname == "textarea") || + {//(classname == "list") || (classname == "table") || (classname == "tree")) { + Rectangle port = getRectangle(component, ":port"); + if (part == "left") { + repaint(component, b.x + port.x, b.y + b.height - block, block, block); + } + else if (part == "right") { + repaint(component, b.x + port.x + port.width - block, b.y + b.height - block, block, block); + } + else if (part == "up") { + repaint(component, b.x + b.width - block, b.y + port.y, block, block); + } + else if (part == "down") { + repaint(component, b.x + b.width - block, b.y + port.y + port.height - block, block, block); + } + else if (part == "horizontal") { // horizontaly center part + repaint(component, b.x + port.x, b.y, port.width, b.height); + } + else if (part == "vertical") { + repaint(component, b.x, b.y + port.y, b.width, port.height); + } + else if (part == "text") { //textarea + repaint(component, b.x + port.x, b.y + port.y, port.width, port.height); + } + else { + Rectangle view = getRectangle(component, ":view"); + Rectangle r = getRectangle(part, "bounds"); + if ((r.y + r.height >= view.y) && (r.y <= view.y + port.height)) { + repaint(component, b.x + port.x, b.y + port.y - view.y + 1 + r.y, + port.width, r.height); + //? need cut item rectangle above/bellow viewport + } + } + } + } + + /** + * + */ + private void validate(Object component) { + repaint(component); + Rectangle bounds = getRectangle(component, "bounds"); + bounds.width = -1 * Math.abs(bounds.width); + } + + /** + * + */ + private void repaint(Object component) { + Rectangle bounds = getRectangle(component, "bounds"); + if (bounds != null) { + repaint(component, bounds.x, bounds.y, bounds.width, bounds.height); + } + } + + /** + * + */ + private void repaint(Object component, int x, int y, int width, int height) { + while ((component = getParent(component)) != null) { + Rectangle bounds = getRectangle(component, "bounds"); + x += bounds.x; + y += bounds.y; + } + repaint(x, y, width, height); + } + + /*private void clip(Graphics g, + Rectangle clip, int x, int y, int width, int height) { + int x1 = Math.max(clip.x, x); + int y1 = Math.max(clip.y, y); + int x2 = Math.min(clip.x + clip.width, x + width); + int y2 = Math.min(clip.y + clip.height, y + height); + g.setClip(x1, y1, x2 - x1, y2 - y1); + }*/ + + /** + * + */ + public boolean requestFocus(Object component) { + if (checkFocusable(component, true)) { + setFocus(component); return true; + } + return false; + } + + /** + * + */ + private boolean setFocus(Object component) { + if (!focusinside) { //java + requestFocus(); //java + } //java + if (focusowner != component) { + Object focused = focusowner; + focusowner = component; + if (focused != null) { + //mouseEvent(null, FocusEvent.FOCUS_LOST, focused, null, null); + repaint(focused); + //focusGained(component); + } + return true; + } + return false; + } + + /** + * @return next focusable component is found (not the first of the desktop/dialog) + */ + private boolean setNextFocusable(Object current, boolean outgo) { + boolean consumed = true; + for (Object next = null, component = current; true; component = next) { + next = get(component, "component"); // check first subcomponent + if (next == null) { next = get(component, ":next"); } // check next component + while (next == null) { // find the next of the parents, or the topmost + component = getParent(component); // current is not on the desktop + if (component == null) { return false; } + if ((component == content) || ((getClass(component) == "dialog") && + (!outgo || getBoolean(component, "modal", false)))) { + consumed = false; // find next focusable but does not consume event + next = component; // the topmost (desktop or modal dialog) + } + else { + next = get(component, ":next"); + } + } + if (next == current) { return false; } // one fucusable, no loop + if (checkFocusable(next, false)) { + setFocus(next); + return consumed; + } + } + } + + //java> + /** + * @return previous focusable component is found (not the last of the desktop/dialog) + */ + private boolean setPreviousFocusable(Object component, boolean outgo) { + for (int i = 0; i < 2; i++) { // 0 is backward direction + Object previous = getPreviousFocusable(component, null, true, false, (i == 0), outgo); + if (previous != null) { + setFocus(previous); + return (i == 0); + } + } + return false; + } + + /** + * For the starting component search its parent direction for a focusable component, and then + * its next component (if not search backward from the component).
+ * For its parent components check its first component, the current one, and its parent direction + * (backward search), or its parent, then next component (forward direction).
+ * For the rest components check the next, then the first subcomponent direction, and finally + * check whether the component is focusable. + */ + private Object getPreviousFocusable(Object component, + Object block, boolean start, boolean upward, boolean backward, boolean outgo) { + Object previous = null; + if ((component != null) && (component != block)) { + boolean go = ((getClass(component) != "dialog") || + (outgo && !getBoolean(component, "modal", false))); + if (!start && !upward && go) { + previous = getPreviousFocusable(get(component, ":next"), block, false, false, backward, outgo); + } + if ((previous == null) && ((upward && backward) || (!start && !upward))) { + previous = getPreviousFocusable(get(component, "component"), block, false, false, backward, outgo); + if ((previous == null) && checkFocusable(component, false)) { + previous = component; + } + } + if ((previous == null) && (start || upward) && go) { + previous = getPreviousFocusable(getParent(component), component, false, true, backward, outgo); + } + if ((previous == null) && (start || upward) && !backward && go) { + previous = getPreviousFocusable(get(component, ":next"), block, false, false, backward, outgo); + } + } + return previous; + } + // " + path + " " + inputstream); + } catch (Throwable e) {} //java + //if (inputstream == null) { // applet code + // inputstream = new URL(getCodeBase(), path).openStream(); + //} + return parse(inputstream); //, Object handler + } + + /** + * + */ + public Object parse(InputStream inputstream) throws Exception { + return parse(inputstream, true); + } + + /** + * + */ + protected void parseXML(InputStream inputstream) throws Exception { + parse(inputstream, false); + } + + /** + * + */ + protected void startElement(String name, Hashtable attributelist) {} + + /** + * + */ + protected void characters(String text) {} + + /** + * + */ + protected void endElement() {} + + /** + * + */ + private Object parse(InputStream inputstream, boolean validate) throws Exception { + BufferedReader reader = new BufferedReader(new InputStreamReader(inputstream)); //java + //midp InputStreamReader reader = new InputStreamReader(inputstream); + Object[] parentlist = null; + Object current = null; + Hashtable attributelist = null; + StringBuffer text = new StringBuffer(); + for (int c = reader.read(); c != -1;) { + if (c == '<') { + if ((c = reader.read()) == '/') { //endtag + if (text.length() > 0) { + if (text.charAt(text.length() - 1) == ' ') { + text.setLength(text.length() - 1); + } + if (!validate) { + characters(text.toString()); + }// else { + //addContent(current, text.toString()); + //} + text.setLength(0); + } + String tagname = (String) parentlist[2]; //getClass(current); + for (int i = 0; i < tagname.length(); i++) { // current-tag + if ((c = reader.read()) != tagname.charAt(i)) { + throw new IllegalArgumentException(tagname); + } + } + while (" \t\n\r".indexOf(c = reader.read()) != -1); // whitespace + if (c != '>') throw new IllegalArgumentException(); // '>' + c = reader.read(); + if (!validate) { endElement(); } + if (parentlist[0] == null) { + reader.close(); + return current; + } + current = parentlist[0]; + parentlist = (Object[]) parentlist[1]; + } + else { //start or standalone tag + boolean instruction = (c == '?'); // Processing Instructions + if (c == '!') { while ((c = reader.read()) != '>'); continue; } // DOCTYPE + if (instruction) { c = reader.read(); } + text.setLength(0); + boolean iscomment = false; + while (">/ \t\n\r".indexOf(c) == -1) { + text.append((char) c); + if ((text.length() == 3) && (text.charAt(0) == '!') && + (text.charAt(1) == '-') && (text.charAt(2) == '-')) { + int m = 0; + while (true) { + c = reader.read(); + if (c == '-') { m++; } + else if ((c == '>') && (m >= 2)) { break; } + else { m = 0; } + } + iscomment = true; + } + c = reader.read(); + } + if (iscomment) { continue; } + if (!instruction) { + String tagname = text.toString(); + parentlist = new Object[] { current, parentlist, tagname }; + if (validate) { + current = (current != null) ? + addElement(current, tagname) : create(tagname); + } else { + current = tagname; + } + } + text.setLength(0); + while (true) { + boolean whitespace = false; + while (" \t\n\r".indexOf(c) != -1) { + c = reader.read(); + whitespace = true; + } + if (c == '>') { + if (instruction) throw new IllegalArgumentException(); // '?>' + if (!validate) { + startElement((String) current, attributelist); attributelist = null; + } + c = reader.read(); + break; + } + else if (c == '/') { + if (instruction) throw new IllegalArgumentException(); // '?>' + if ((c = reader.read()) != '>') { + throw new IllegalArgumentException(); // '>' + } + if (!validate) { + startElement((String) current, attributelist); attributelist = null; + endElement(); + } + if (parentlist[0] == null) { + reader.close(); + return current; + } + current = parentlist[0]; + parentlist = (Object[]) parentlist[1]; + c = reader.read(); + break; + } + else if (instruction && (c == '?')) { + if ((c = reader.read()) != '>') { + throw new IllegalArgumentException(); // '>' + } + c = reader.read(); + break; + } + else if (whitespace) { + while ("= \t\n\r".indexOf(c) == -1) { + text.append((char) c); + c = reader.read(); + } + String key = text.toString(); + text.setLength(0); + while (" \t\n\r".indexOf(c) != -1) c = reader.read(); + if (c != '=') throw new IllegalArgumentException(); + while (" \t\n\r".indexOf(c = reader.read()) != -1); + char quote = (char) c; + if ((c != '\"') && (c != '\'')) throw new IllegalArgumentException(); + while (quote != (c = reader.read())) { + if (c == '&') { + StringBuffer eb = new StringBuffer(); + while (';' != (c = reader.read())) { eb.append((char) c); } + String entity = eb.toString(); + if ("lt".equals(entity)) { text.append('<'); } + else if ("gt".equals(entity)) { text.append('>'); } + else if ("amp".equals(entity)) { text.append('&'); } + else if ("quot".equals(entity)) { text.append('"'); } + else if ("apos".equals(entity)) { text.append('\''); } + else if (entity.startsWith("#")) { + text.append((char) Integer.parseInt(entity.substring(1))); + } + else throw new IllegalArgumentException("unknown " + "entity " + entity); + } + else text.append((char) c); + } + if (!instruction) { + if (validate) { + addAttribute(current, key, text.toString()); + } else { + if (attributelist == null) { attributelist = new Hashtable(); } + attributelist.put(key, text.toString()); + } + } + text.setLength(0); + c = reader.read(); + } + else throw new IllegalArgumentException(); + } + } + } + else { + if (" \t\n\r".indexOf(c) != -1) { + if ((text.length() > 0) && (text.charAt(text.length() - 1) != ' ')) { + text.append(' '); + } + } + else { + text.append((char) c); + } + c = reader.read(); + } + } + throw new IllegalArgumentException(); + } + + /** + * Convert entities. + */ + private static String convert(StringBuffer text) { + return null; + } + + /*private InputStream inputreader; + private byte[] data; + private int inputfrom = 0, inputto = 0; + private int read() throws Exception { + if (data == null) { data = new byte[1024]; } + if (inputfrom >= inputto) { + inputfrom = 0; + inputto = inputreader.read(data); + } + inputfrom++; + return data[inputfrom - 1]; + }*/ + + /** + * + */ + private void addImpl(Object parent, Object component, int index) { + String parentclass = getClass(parent); + String classname = getClass(component); + //System.out.println("add " + classname + " -> " + parentclass); + if ((("combobox" == parentclass) && ("choice" == classname)) || + (("tabbedpane" == parentclass) && ("tab" == classname)) || + (("list" == parentclass) && ("item" == classname)) || + (("table" == parentclass) && (("column" == classname) || ("row" == classname))) || + (("row" == parentclass) && ("cell" == classname)) || + ((("tree" == parentclass) || ("node" == parentclass)) && ("node" == classname)) || + (("menubar" == parentclass) && ("menu" == classname))) { + classname = classname; // compiler bug + } + else if (("menu" == parentclass) && (("menu" == classname) || ("menuitem" == classname) || + ("checkboxmenuitem" == classname) || ("separator" == classname))) { + classname = "menu"; + } + else if (("panel" == parentclass) || ("desktop" == parentclass) || + ("splitpane" == parentclass) || ("dialog" == parentclass) || + ("tabbedpane" == parentclass)) { + while ("component" != classname) { + String extendclass = null; + for (int i = 0; i < dtd.length; i += 3) { + if (classname == dtd[i]) { + extendclass = (String) dtd[i + 1]; break; + } + } + if (extendclass == null) throw new IllegalArgumentException(classname + " not component"); + classname = extendclass; + } + } + else throw new IllegalArgumentException(classname + " add " + parentclass); + insertItem(parent, (String) classname, component, index); + set(component, ":parent", parent); + //if (parent == content) System.out.println(getClass(parent) + ".add(" + getClass(component) + ") : " + classname); + } + + /** + * + */ + private Object addElement(Object parent, String name) { + //System.out.println("create '" + name + "'"); + Object component = create(name); + addImpl(parent, component, -1); + return component; + } + + /** + * + */ + private void addAttribute(Object component, String key, String value) { + //System.out.println("attribute '" + key + "'='" + value + "'"); + Object[] definition = getDefinition(component, key, null); + key = (String) definition[1]; + if ("string" == definition[0]) { + setString(component, key, value, (String) definition[3]); + } + else if ("choice" == definition[0]) { + String[] values = (String[]) definition[3]; + setChoice(component, key, value, values, values[0]); + } + else if ("boolean" == definition[0]) { + if ("true".equals(value)) { + if (definition[3] == Boolean.FALSE) { + set(component, key, Boolean.TRUE); + } + } + else if ("false".equals(value)) { + if (definition[3] == Boolean.TRUE) { + set(component, key, Boolean.FALSE); + } + } + else throw new IllegalArgumentException(value); + } + else if ("integer" == definition[0]) { + set(component, key, Integer.valueOf(value)); + } + else if ("icon" == definition[0]) { + set(component, key, getIcon(value)); + } + else if ("method" == definition[0]) { + try { //java + set(component, key, getClass().getMethod(value, null)); //java + } catch (Exception exc) { System.err.println(value); exc.printStackTrace(); } //java + //midp setMethod(component, key, value); + } + //java> + else if ("bean" == definition[0]) { + try { + set(component, key, (Component) Class.forName(value).newInstance()); + } catch (Exception exc) { System.err.println(value); exc.printStackTrace(); } + } + //Image icon) { + Object[] definition = getDefinition(component, key, "icon"); + if (set(component, (String) definition[1], icon)) { + update(component, definition[2]); + } + } + + /** + * + */ + public Image getIcon(Object component, String key) { + Object[] definition = getDefinition(component, key, "icon"); + return getIcon(component, (String) definition[1], (Image) definition[3]); + } + + /** + * + */ + public void setMethod(Object component, String key, Method method) { //java + //midp public void setMethod(Object component, String key, String method) { + Object[] definition = getDefinition(component, key, "method"); + if (set(component, (String) definition[1], method)) { + update(component, definition[2]); + } + } + + /** + * + */ + public Method getMethod(Object component, String key) { //java + //midp public String getMethod(Object component, String key) { + Object[] definition = getDefinition(component, key, "method"); + return (Method) get(component, (String) definition[1]); //java + //midp return (String) get(component, (String) definition[1]); + } + + /** + * + */ + private void update(Object component, Object mode) { + if ("parent" == mode) { + component = getParent(component); + mode = "validate"; + } + boolean firstpaint = true; + int x = 0; int y = 0; int width = 0; int height = 0; + while (component != null) { + if (!getBoolean(component, "visible", true)) { break; } + if ("paint" == mode) {//|| (firstpaint && (component == content)) + Rectangle bounds = getRectangle(component, "bounds"); + if (bounds == null) { return; } + if (firstpaint) { + x = bounds.x; y = bounds.y; + width = Math.abs(bounds.width); height = bounds.height; + firstpaint = false; + } else { + x += bounds.x; y += bounds.y; + } + if (component == content) { + repaint(x, y, width, height); + } + } + Object parent = getParent(component); + String classname = getClass(parent); + if ("combobox" == classname) { + parent = get(parent, "combolist"); + } + else if ("menu" == classname) { + parent = get(parent, "popupmenu"); + } + else if (("paint" == mode) && ("tabbedpane" == classname)) { + if (getItemImpl(parent, "component", + getInteger(parent, "selected", 0)) != component) { break; } + } + if (("layout" == mode) || (("validate" == mode) && + (("list" == classname) || ("table" == classname) || + ("tree" == classname) || ("dialog" == classname) || (parent == content)))) { + Rectangle bounds = getRectangle(parent, "bounds"); + if (bounds == null) { return; } + bounds.width = -1 * Math.abs(bounds.width); + mode = "paint"; + } + component = parent; + } + } + + // ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + + /** + * + */ + private boolean setString(Object component, + String key, String value, String defaultvalue) { + /*boolean changed = set(component, key, value); + if (changed && ("name" == key)) { + //for (Class cls = getClass(); cls != null; cls = cls.getSuperclass()) { + Field[] fields = getClass().getDeclaredFields(); + for (int i = 0; i < fields.length; i++) { + if ((fields[i].getType() == Object.class) && + fields[i].getName().equals(value)) { + try { + fields[i].set(this, component); + return true; + } catch (IllegalAccessException iae) {} + } + } + //} + try { + getClass().getField(value).set(this, component); + } catch (Exception exc) {} + } + return changed;*/ + return set(component, key, value); + } + + /** + * + */ + private String getString(Object component, + String key, String defaultvalue) { + Object value = get(component, key); + return (value == null) ? defaultvalue : (String) value; + } + + /** + * + */ + private boolean setChoice(Object component, + String key, String value, String[] values, String defaultvalue) { + if (value == null) { + return set(component, key, defaultvalue); + } + for (int i = 0; i < values.length; i++) { + if (value.equals(values[i])) { + return set(component, key, values[i]); + } + } + throw new IllegalArgumentException("unknown " + value + " for " + key); + } + + /** + * + */ + private boolean setIcon(Object component, + String key, String path, Image defaultvalue) { + return set(component, key, (path != null) ? getIcon(path) : defaultvalue); + } + + /** + * + */ + private Image getIcon(Object component, String key, Image defaultvalue) { + Object value = get(component, key); + return (value == null) ? defaultvalue : (Image) value; + } + + /** + * + */ + private boolean setBoolean(Object component, + String key, boolean value, boolean defaultvalue) { + return set(component, key, (value == defaultvalue) ? null : + (value ? Boolean.TRUE : Boolean.FALSE)); + } + + /** + * + */ + private boolean getBoolean(Object component, + String key, boolean defaultvalue) { + Object value = get(component, key); + return (value == null) ? defaultvalue : ((Boolean) value).booleanValue(); + } + + /** + * + */ + private boolean setInteger(Object component, + String key, int value, int defaultvalue) { + return set(component, key, (value == defaultvalue) ? null : new Integer(value)); + } + + /** + * + */ + private int getInteger(Object component, String key, int defaultvalue) { + Object value = get(component, key); + return (value == null) ? defaultvalue : ((Integer) value).intValue(); + } + + /** + * + */ + private void setRectangle(Object component, + String key, int x, int y, int width, int height) { + Rectangle rectangle = getRectangle(component, key); + if (rectangle != null) { + rectangle.x = x; rectangle.y = y; + rectangle.width = width; rectangle.height = height; + } + else { + set(component, key, new Rectangle(x, y, width, height)); //java + //midp set(component, key, new int[] { width, height, x, y }); + } + } + + /** + * + */ + private Rectangle getRectangle(Object component, String key) { + return (Rectangle) get(component, key); //java + //midp return (int[]) get(component, key); + } + + // ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + + /** + * + */ + public Image getIcon(String path) { + return getIcon(path, true); + } + + /** + * + */ + public Image getIcon(String path, boolean preload) { + if ((path == null) || (path.length() == 0)) { + return null; + } + Image image = null; //(Image) imagepool.get(path); + //midp try { + //midp image = Image.createImage(path); + //midp } catch (IOException ioe) {} + //java> + try { + image = Toolkit.getDefaultToolkit().getImage(getClass().getResource(path)); + //image = Toolkit.getDefaultToolkit().getImage(ClassLoader.getSystemResource(path)); + } catch (Throwable e) {} + if (image == null) { + try { + InputStream is = getClass().getResourceAsStream(path); + //InputStream is = ClassLoader.getSystemResourceAsStream(path); + if (is != null) { + byte[] data = new byte[is.available()]; + is.read(data, 0, data.length); + image = getToolkit().createImage(data); + is.close(); + } + } catch (Throwable e) {} + } + //if (image == null) { // applet code + // try { + // image = getImage(getCodeBase(), path); + // } catch (Throwable e) {} + //} + if (preload && (image != null)) { + MediaTracker mediatracker = new MediaTracker(this); + mediatracker.addImage(image, 1); + try { + mediatracker.waitForID(1, 50); + } catch (InterruptedException ie) { } + //imagepool.put(path, image); + } + // doTest(final int maxMillis) throws Exception { - @NonNls String filePath = LightAdvHighlightingTest.BASE_PATH + "/" + getTestName(false) + ".java"; - configureByFile(filePath); + configureByFile(getFilePath("")); PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); getFile().getText(); //to load text @@ -92,32 +106,23 @@ public class LightAdvHighlightingPerformanceTest extends LightDaemonAnalyzerTest infos.addAll(h); } }).cpuBound().usesAllCPUCores().assertTiming(); + return DaemonAnalyzerTestCase.filter(infos, HighlightSeverity.ERROR); } - public void testaThinlet() throws Exception { + public void testAThinlet() throws Exception { List errors = doTest(Math.max(10000, 24000 - JobSchedulerImpl.CORES_COUNT * 1000)); - dump("thinlet", errors); - assertEquals(1230, errors.size()); + if (1226 != errors.size()) { + doTest(getFilePath("_hl"), false, false); + fail("Actual: " + errors.size()); + } } - private static void dump(String msg, List errors) { - if (true) return; - Collections.sort(errors, new Comparator() { - @Override - public int compare(HighlightInfo o1, HighlightInfo o2) { - return o1.toString().compareTo(o2.toString()); - } - }); - final String s = StringUtil.join(errors, StringUtil.createToStringFunction(HighlightInfo.class), "\n"); - System.out.println(msg+":\n-----------------------------------------"); - System.out.println(s); - System.out.println("\n--------------------------------------------"); - } - - public void testaClassLoader() throws Exception { + public void testAClassLoader() throws Exception { List errors = doTest(Math.max(1000, 10000 - JobSchedulerImpl.CORES_COUNT * 1000)); - dump("classloader", errors); - assertEquals(178, errors.size()); + if (173 != errors.size()) { + doTest(getFilePath("_hl"), false, false); + fail("Actual: " + errors.size()); + } } } diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java index 54cf9b45539a..8438576d3790 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java @@ -82,7 +82,7 @@ public abstract class LightDaemonAnalyzerTestCase extends LightCodeInsightTestCa protected void doTestConfiguredFile(boolean checkWarnings, boolean checkInfos, @Nullable String filePath) { getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE); - ExpectedHighlightingData data = new ExpectedHighlightingData(getEditor().getDocument(),checkWarnings, checkInfos); + ExpectedHighlightingData data = new ExpectedHighlightingData(getEditor().getDocument(), checkWarnings, checkInfos); checkHighlighting(data, composeLocalPath(filePath)); } From 4703151399956e2d60be7cb3b13c0009e2c06cfc Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Wed, 16 May 2012 09:34:09 +0400 Subject: [PATCH 50/61] IDEA-85100 Deleting wrapped lines with Ctrl+Y doen't work properly with "soft wrapped" lines *) more tests have been refactored and checked; *) refactoring; --- .../rearranger/entry/ClassContentsEntry.java | 5 +- .../com/wrq/rearranger/entry/ClassEntry.java | 71 ++++++++++--------- .../com/wrq/rearranger/entry/RangeEntry.java | 3 +- .../rearrangement/GenericRearranger.java | 11 +-- .../wrq/rearranger/rearrangement/Spacer.java | 46 ++++++------ .../atomicAttributes/AndNotAttribute.java | 4 +- .../InitToAnonClassAttribute.java | 4 +- .../attributeGroups/CommonAttributes.java | 4 ++ .../com/wrq/rearranger/RearrangerTest.groovy | 51 ++++++------- .../wrq/rearranger/RearrangementResult4.java | 1 - 10 files changed, 96 insertions(+), 104 deletions(-) diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/ClassContentsEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassContentsEntry.java index f5130853b1e5..cbde789e0a10 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/ClassContentsEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassContentsEntry.java @@ -34,10 +34,7 @@ import javax.swing.tree.DefaultMutableTreeNode; * Describes the fields, methods, and inner class declarations of a class. This information is used to reorder * these declarations within an outer class. */ -public abstract class ClassContentsEntry - extends RangeEntry - implements FilePopupEntry -{ +public abstract class ClassContentsEntry extends RangeEntry implements FilePopupEntry { public ClassContentsEntry(@Nullable final PsiElement start, @Nullable final PsiElement end, final int modifiers, diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/ClassEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassEntry.java index e6254a69ee88..1afbc42ddb12 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/ClassEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/ClassEntry.java @@ -237,7 +237,7 @@ public class ClassEntry extends ClassContentsEntry implements FilePopupEntry { * @param clazz * @return starting element index for the portion of the enumeration class following its enum declarations. */ - private int findLastEnumTerminator(PsiClass clazz) { + private static int findLastEnumTerminator(PsiClass clazz) { int startElementIndex = 0; // go until we hit RBrace (non-inclusive), or semicolon (inclusive) boolean foundLBrace = false; @@ -263,25 +263,31 @@ public class ClassEntry extends ClassContentsEntry implements FilePopupEntry { return startElementIndex; } - private int parseField(PsiElement child, MemberAttributes attributes, int i, final PsiClass psiClass) { + private static int parseField(PsiElement child, MemberAttributes attributes, int i, final PsiClass psiClass) { attributes.field = (PsiField)child; LOG.debug("enter parseField: child=" + (child == null ? "null" : child.toString())); attributes.name = attributes.field.getName(); - if (attributes.field.getTypeElement() == null) { - attributes.type = attributes.field.getContainingClass().getName(); // if enum, use class as type + final PsiClass containingClass = attributes.field.getContainingClass(); + final PsiTypeElement typeElement = attributes.field.getTypeElement(); + if (typeElement == null && containingClass != null) { + attributes.type = containingClass.getName(); // if enum, use class as type } - else { - attributes.type = attributes.field.getTypeElement().getText(); + else if (typeElement != null) { + attributes.type = typeElement.getText(); + } + final PsiModifierList modifierList = attributes.field.getModifierList(); + if (modifierList != null) { + attributes.modifierString = modifierList.getText(); } - attributes.modifierString = attributes.field.getModifierList().getText(); attributes.modifiers = ModifierUtils.getModifierMask(attributes.modifierString); - if (attributes.field.getContainingClass().isInterface()) { + if (containingClass != null && containingClass.isInterface()) { // all fields in an interface are constants, hence "public static final" attributes.modifiers |= Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL; } - if (attributes.field.getInitializer() instanceof PsiNewExpression) { - final PsiElement lc = attributes.field.getInitializer().getLastChild(); + final PsiExpression initializer = attributes.field.getInitializer(); + if (initializer instanceof PsiNewExpression) { + final PsiElement lc = initializer.getLastChild(); if (lc instanceof PsiAnonymousClass) { attributes.modifiers |= ModifierConstants.INIT_TO_ANON_CLASS; } @@ -335,19 +341,21 @@ public class ClassEntry extends ClassContentsEntry implements FilePopupEntry { return i; } - private void parseMethod(PsiElement child, MemberAttributes attributes, final PsiSearchHelper psh) { + private static void parseMethod(PsiElement child, MemberAttributes attributes, final PsiSearchHelper psh) { attributes.method = (PsiMethod)child; attributes.name = attributes.method.getName(); - if (attributes.method.getReturnTypeElement() == null) { + final PsiTypeElement returnTypeElement = attributes.method.getReturnTypeElement(); + if (returnTypeElement == null) { attributes.type = "null"; } else { - attributes.type = attributes.method.getReturnTypeElement().getText(); + attributes.type = returnTypeElement.getText(); } attributes.modifierString = attributes.method.getModifierList().getText(); attributes.modifiers = ModifierUtils.getModifierMask(attributes.modifierString); attributes.nParameters = attributes.method.getParameterList().getParameters().length; - if (attributes.method.getContainingClass().isInterface()) { + final PsiClass containingClass = attributes.method.getContainingClass(); + if (containingClass != null && containingClass.isInterface()) { // methods in an interface are always considered public attributes.modifiers |= Modifier.PUBLIC; } @@ -379,12 +387,12 @@ public class ClassEntry extends ClassContentsEntry implements FilePopupEntry { attributes.modifiers |= ModifierConstants.OVERRIDDEN; } } - // determine if this method overrides another. + // Determine if this method overrides another. final PsiMethod[] superMethods = attributes.method.findSuperMethods(false); LOG.debug("method " + attributes.method.toString() + " has " + superMethods.length + " supermethods"); dumpMethodNames(superMethods); if (superMethods.length > 0) { - // determine if supermethod is abstract or interface; if so, assign IMPLEMENTING attribute. + // Determine if supermethod is abstract or interface; if so, assign IMPLEMENTING attribute. PsiMethod superMethod = superMethods[0]; boolean abztract = superMethod.getModifierList().hasModifierProperty(PsiModifier.ABSTRACT); PsiClass superclass = superMethod.getContainingClass(); @@ -400,9 +408,8 @@ public class ClassEntry extends ClassContentsEntry implements FilePopupEntry { if (attributes.method.isConstructor()) { attributes.modifiers |= ModifierConstants.CONSTRUCTOR; } - /** getter/setter cannot be determined here because definition of what a getter/setter - * is can vary from rule to rule. Do it at the time of rule matching. - */ + // Getter/setter cannot be determined here because definition of what a getter/setter + // is can vary from rule to rule. Do it at the time of rule matching. else if ((attributes.modifiers & ModifierConstants.CANONICAL) == 0) { attributes.modifiers |= ModifierConstants.OTHER_METHOD; } @@ -414,7 +421,7 @@ public class ClassEntry extends ClassContentsEntry implements FilePopupEntry { ); } - private int isCanonicalOrInterface(PsiMethod method, MemberAttributes attributes) { + private static int isCanonicalOrInterface(PsiMethod method, MemberAttributes attributes) { PsiElement methodParent = method.getParent(); LOG.debug("checking to see if " + method.getName() + " of " + methodParent + " is canonical"); PsiMethod[] superMethods = method.findSuperMethods(); @@ -458,7 +465,7 @@ public class ClassEntry extends ClassContentsEntry implements FilePopupEntry { return 0; } - private void dumpMethodNames(PsiMethod[] methods) { + private static void dumpMethodNames(PsiMethod[] methods) { for (int j = 0; j < methods.length; j++) { LOG.debug( j + @@ -487,17 +494,19 @@ public class ClassEntry extends ClassContentsEntry implements FilePopupEntry { } } - private void parseClassInitializer(PsiElement child, MemberAttributes attributes) { + private static void parseClassInitializer(PsiElement child, MemberAttributes attributes) { attributes.classInitializer = (PsiClassInitializer)child; - attributes.classInitializer.getModifierList(); attributes.name = ""; - attributes.modifierString = attributes.classInitializer.getModifierList().getText(); + final PsiModifierList modifierList = attributes.classInitializer.getModifierList(); + if (modifierList != null) { + attributes.modifierString = modifierList.getText(); + } attributes.modifiers = ModifierUtils.getModifierMask(attributes.modifierString) | ModifierConstants.INITIALIZER; } public void emit(Emitter emitter) { - // first emit the text up to and including the left brace. + // First emit the text up to and including the left brace. super.emit(emitter); // now emit all children. emitter.emitRuleInstances(getResultRuleInstances()); @@ -514,7 +523,7 @@ public class ClassEntry extends ClassContentsEntry implements FilePopupEntry { return result; } - /** rearranges the contents of this PsiClass according to supplied rules. */ + /** Rearranges the contents of this PsiClass according to supplied rules. */ public void rearrangeContents() { buildMethodCallGraph(); @@ -530,14 +539,10 @@ public class ClassEntry extends ClassContentsEntry implements FilePopupEntry { ((RelatableEntry)contentsEntry).determineExtractedMethod(mySettings.getExtractedMethodsSettings()); } } - /** - * remove any cycles in the related method graph. - */ + // Remove any cycles in the related method graph. MethodEntry.eliminateCycles(getContents()); - /** - * check for overloaded extracted methods; if configured to be kept together, attach subsequent - * methods to the first and remove them from consideration for other alignment. - */ + // Check for overloaded extracted methods; if configured to be kept together, attach subsequent + // methods to the first and remove them from consideration for other alignment. MethodEntry.handleOverloadedMethods(getContents(), mySettings); final GenericRearranger classContentsRearranger = new GenericRearranger(mySettings.getItemOrderAttributeList(), diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/RangeEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/RangeEntry.java index 55dd4fa91665..18b525ad3ded 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/RangeEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/RangeEntry.java @@ -42,6 +42,7 @@ import java.util.regex.Matcher; * flags and special flags to mark any miscellaneous text or comments that precede or follow the item. */ abstract public class RangeEntry implements PopupTreeRangeEntry { + // ------------------------------ FIELDS ------------------------------ private static final Logger LOG = Logger.getInstance("#" + RangeEntry.class.getName()); @@ -267,7 +268,7 @@ abstract public class RangeEntry implements PopupTreeRangeEntry { curr = curr.getNextSibling(); } } - if (curr == myEnd) { + if (curr == myEnd && myEnd != null) { emitElement(myEnd, buffer, document); } } diff --git a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/GenericRearranger.java b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/GenericRearranger.java index 34d7d42ee334..0fe9f582a692 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/GenericRearranger.java +++ b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/GenericRearranger.java @@ -24,12 +24,13 @@ package com.wrq.rearranger.rearrangement; import com.intellij.openapi.diagnostic.Logger; import com.wrq.rearranger.entry.ClassContentsEntry; import com.wrq.rearranger.entry.ClassEntry; -import com.wrq.rearranger.entry.RelatableEntry; import com.wrq.rearranger.entry.RangeEntry; +import com.wrq.rearranger.entry.RelatableEntry; import com.wrq.rearranger.ruleinstance.CommentRuleInstance; import com.wrq.rearranger.ruleinstance.RuleInstance; import com.wrq.rearranger.settings.RearrangerSettings; import com.wrq.rearranger.settings.attributeGroups.*; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -51,7 +52,7 @@ public abstract class GenericRearranger { final List outerClasses, final int nestingLevel, final RearrangerSettings settings) { - this.myRules = rules; + myRules = rules; myEntries = outerClasses; this.myNestingLevel = nestingLevel; this.mySettings = settings; @@ -121,7 +122,7 @@ public abstract class GenericRearranger { * @param prioritizedRules prioritized list of rules */ @SuppressWarnings({"StringContatenationInLoop"}) - private void matchPrioritizedRules(List prioritizedRules) { + private void matchPrioritizedRules(@NotNull List prioritizedRules) { for (RuleInstance ruleInstance : prioritizedRules) { final Rule rule = ruleInstance.getRule(); final ListIterator entryIterator = myEntries.listIterator(); @@ -174,11 +175,11 @@ public abstract class GenericRearranger { prioritizedRuleInstances.add(0, instance); } } - // now add a default rule to pick up all unmatched items. + // Now add a default rule to pick up all unmatched items. RuleInstance defaultRuleInstance = new DefaultRule().createRuleInstance(); myResultRuleInstances.add(defaultRuleInstance); prioritizedRuleInstances.add(defaultRuleInstance); - // finally, add a TrailerRuleInstance to pick up any leftover text. + // Finally, add a TrailerRuleInstance to pick up any leftover text. RuleInstance tri = new TrailerRule().createRuleInstance(); myResultRuleInstances.add(tri); prioritizedRuleInstances.add(tri); diff --git a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Spacer.java b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Spacer.java index ad04c62930f6..acbb698009a0 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Spacer.java +++ b/plugins/rearranger/src/com/wrq/rearranger/rearrangement/Spacer.java @@ -74,22 +74,22 @@ public class Spacer { myBuffer = new StringBuilder(maxSize); } - private class AbortRespacing extends RuntimeException { + private static class AbortRespacingException extends RuntimeException { } - private class BadPsiElement extends Exception { - BadPsiElement(String string) { + private static class BadPsiElementException extends Exception { + BadPsiElementException(String string) { super(string); } } - private void handleBadPsiElementException(String desc, PsiElement element) - throws AbortRespacing + private static void handleBadPsiElementException(String desc, PsiElement element) + throws AbortRespacingException { JOptionPane.showMessageDialog(null, "Spacing could not be performed due to a syntax error:\n" + desc + element.getText(), "Spacing Error", JOptionPane.ERROR_MESSAGE); - throw new AbortRespacing(); + throw new AbortRespacingException(); } public boolean respace() { @@ -132,7 +132,7 @@ public class Spacer { bias ); } - catch (BadPsiElement badPsiElement) { + catch (BadPsiElementException badPsiElement) { handleBadPsiElementException("class " + psiClass.getName() + " missing left brace. Body follows:", psiClass); } log(mySettings.getAfterClassLBrace(), psiClass.getName(), oldbias, bias); @@ -146,7 +146,7 @@ public class Spacer { bias ); } - catch (BadPsiElement badPsiElement) { + catch (BadPsiElementException badPsiElement) { handleBadPsiElementException("class " + psiClass.getName() + " missing right brace. Body follows:", psiClass); } log(mySettings.getBeforeClassRBrace(), psiClass.getName(), oldbias, bias); @@ -173,7 +173,7 @@ public class Spacer { bias ); } - catch (BadPsiElement badPsiElement) { + catch (BadPsiElementException badPsiElement) { handleBadPsiElementException("class " + psiClass.getName() + " missing left brace. Body follows:", psiClass); } log(mySettings.getAfterClassRBrace(), psiClass.getName(), oldbias, bias); @@ -231,7 +231,7 @@ public class Spacer { bias ); } - catch (BadPsiElement badPsiElement) { + catch (BadPsiElementException badPsiElement) { handleBadPsiElementException("body of method " + psiMethod.getName() + " missing left brace. Body follows:", psiMethod); } log(mySettings.getAfterMethodLBrace(), psiMethod.getName(), oldbias, bias); @@ -245,7 +245,7 @@ public class Spacer { bias ); } - catch (BadPsiElement badPsiElement) { + catch (BadPsiElementException badPsiElement) { handleBadPsiElementException("body of method " + psiMethod.getName() + " missing right brace. Body follows:", psiMethod); } log(mySettings.getBeforeMethodRBrace(), psiMethod.getName(), oldbias, bias); @@ -276,7 +276,7 @@ public class Spacer { bias ); } - catch (BadPsiElement badPsiElement) { + catch (BadPsiElementException badPsiElement) { handleBadPsiElementException("body of method " + psiMethod.getName() + " missing right brace. Body follows:", psiMethod); } log(mySettings.getAfterMethodRBrace(), psiMethod.getName(), oldbias, bias); @@ -300,7 +300,7 @@ public class Spacer { bias += adjustSpacing(psiCodeBlock.getLBrace(), psiCodeBlock.getRBrace(), false, 0, bias); } - catch (BadPsiElement badPsiElement) { + catch (BadPsiElementException badPsiElement) { handleBadPsiElementException("code block missing left brace. Content follows:\n", psiCodeBlock); } log("code block left brace", oldbias, bias); @@ -313,7 +313,7 @@ public class Spacer { try { bias += adjustSpacing(psiCodeBlock.getRBrace(), psiCodeBlock.getLBrace(), true, 0, bias); } - catch (BadPsiElement badPsiElement) { + catch (BadPsiElementException badPsiElement) { handleBadPsiElementException("code block missing right brace. Content follows:\n", psiCodeBlock); } log("code block right brace", oldbias, bias); @@ -323,7 +323,7 @@ public class Spacer { try { myFile.accept(visitor); } - catch (AbortRespacing ar) { + catch (AbortRespacingException ar) { return false; } if (myChangesMade) { @@ -348,7 +348,7 @@ public class Spacer { * @return true if the psiElement is the last syntactic item (i.e., not including comments and whitespace) * of the owner. */ - private boolean isLastMeaningfulElement(PsiElement owner, PsiElement psiElement) { + private static boolean isLastMeaningfulElement(PsiElement owner, PsiElement psiElement) { boolean lastMethod; // class is immediate parent PsiElement[] elements = owner.getChildren(); @@ -372,7 +372,7 @@ public class Spacer { return lastMethod; } - private void log(ForceBlankLineSetting fbls, String name, int oldbias, int bias) { + private static void log(ForceBlankLineSetting fbls, String name, int oldbias, int bias) { if (oldbias != bias) { LOG.debug( fbls.getObjectName() + @@ -386,7 +386,7 @@ public class Spacer { } } - private void log(String name, int oldbias, int bias) { + private static void log(String name, int oldbias, int bias) { if (oldbias != bias) { LOG.debug( name + @@ -397,7 +397,7 @@ public class Spacer { } private int adjustSpacing(PsiElement brace, PsiElement matchingBrace, ForceBlankLineSetting fbls, int bias) - throws BadPsiElement + throws BadPsiElementException { if (fbls.isForce()) { return adjustSpacing(brace, matchingBrace, fbls.isBefore(), fbls.getnBlankLines(), bias); @@ -446,11 +446,11 @@ public class Spacer { * @return bias adjustment corresponding to number of newlines inserted or deleted */ private int adjustSpacing(PsiElement brace, PsiElement matchingBrace, boolean before, int nBlankLines, int bias) - throws BadPsiElement + throws BadPsiElementException { int result = 0; if (brace == null) { - throw new BadPsiElement( + throw new BadPsiElementException( "adjustSpacing: illegal syntax (mismatched braces); PsiElement for brace is null" ); } @@ -495,9 +495,7 @@ public class Spacer { return result; } } - while (whiteSpace != null && - (!(whiteSpace instanceof PsiWhiteSpace) || - whiteSpace.getText().indexOf('\n') < 0)); + while (whiteSpace != null && (!(whiteSpace instanceof PsiWhiteSpace) || whiteSpace.getText().indexOf('\n') < 0)); VirtualElement virtualWhiteSpace = null; if (whiteSpace != null) { diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/AndNotAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/AndNotAttribute.java index f3180b76f6a9..28c033e05725 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/AndNotAttribute.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/AndNotAttribute.java @@ -31,9 +31,7 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** Base class for all boolean attributes. */ -abstract public class AndNotAttribute - extends AtomicAttribute -{ +abstract public class AndNotAttribute extends AtomicAttribute { // ------------------------------ FIELDS ------------------------------ boolean value; diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/InitToAnonClassAttribute.java b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/InitToAnonClassAttribute.java index e3cbef25990b..a13ada7458ea 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/InitToAnonClassAttribute.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/atomicAttributes/InitToAnonClassAttribute.java @@ -24,9 +24,7 @@ package com.wrq.rearranger.settings.atomicAttributes; import com.wrq.rearranger.ModifierConstants; import org.jdom.Element; -public final class InitToAnonClassAttribute - extends AndNotAttribute -{ +public final class InitToAnonClassAttribute extends AndNotAttribute { // -------------------------- STATIC METHODS -------------------------- diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/CommonAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/CommonAttributes.java index 6cc94c03a37e..ad8c6c1a64e6 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/CommonAttributes.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/CommonAttributes.java @@ -72,10 +72,12 @@ public abstract class CommonAttributes implements AttributeGroup, PrioritizedRul // --------------------- GETTER / SETTER METHODS --------------------- + @NotNull public final NameAttribute getNameAttribute() { return myNameAttribute; } + @NotNull final public ProtectionLevelAttributes getProtectionLevelAttributes() { return myProtectionLevelAttributes; } @@ -88,10 +90,12 @@ public abstract class CommonAttributes implements AttributeGroup, PrioritizedRul this.myPriority = priority; } + @NotNull final public StaticAttribute getStaticAttribute() { return myStaticAttribute; } + @NotNull public SortOptions getSortOptions() { return mySortOptions; } diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy b/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy index 13553851cfd5..0e8e62c9cd12 100644 --- a/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy +++ b/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy @@ -25,9 +25,10 @@ package com.wrq.rearranger; import com.intellij.openapi.application.ApplicationManager import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import com.wrq.rearranger.settings.RearrangerSettings +import com.wrq.rearranger.settings.attributeGroups.FieldAttributes +import com.wrq.rearranger.settings.attributeGroups.MethodAttributes import org.jetbrains.annotations.NotNull import org.jetbrains.annotations.Nullable -import com.wrq.rearranger.settings.attributeGroups.FieldAttributes /** JUnit tests for the rearranger plugin. */ class RearrangerTest extends LightCodeInsightFixtureTestCase { @@ -62,35 +63,25 @@ class RearrangerTest extends LightCodeInsightFixtureTestCase { } } -// public final void testNotPublicFieldRearrangement() throws Exception { -// configureByFile("/com/wrq/rearranger/RearrangementTest.java"); -// final PsiFile file = getFile(); -// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); -// final FieldAttributes fa; -// fa = new FieldAttributes(); -// fa.getPlAttr().setPlPublic(true); -// fa.getPlAttr().setInvertProtectionLevel(true); -// rs.addItem(fa, 0); -// final RearrangerActionHandler rah = new RearrangerActionHandler(); -// rah.rearrangeDocument(getProject(), file, rs, doc); -// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult3.java"); -// } -// -// public final void testConstructorRearrangement() throws Exception { -// configureByFile("/com/wrq/rearranger/RearrangementTest.java"); -// final PsiFile file = getFile(); -// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); -// final MethodAttributes ma; -// ma = new MethodAttributes(); -// ma.getPlAttr().setPlPackage(true); -// ma.getPlAttr().setPlPublic(true); -// ma.setConstructorMethodType(true); -// rs.addItem(ma, 0); -// final RearrangerActionHandler rah = new RearrangerActionHandler(); -// rah.rearrangeDocument(getProject(), file, rs, doc); -// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult4.java"); -// } -// + public final void testNotPublicFieldRearrangement() throws Exception { + doTest('RearrangementTest', 'RearrangementResult3') { + def attributes = new FieldAttributes() + attributes.protectionLevelAttributes.plPublic = true + attributes.protectionLevelAttributes.invertProtectionLevel = true + mySettings.addItem(attributes, 0) + } + } + + public final void testConstructorRearrangement() throws Exception { + doTest('RearrangementTest', 'RearrangementResult4') { + def attributes = new MethodAttributes() + attributes.protectionLevelAttributes.plPackage = true + attributes.protectionLevelAttributes.plPublic = true + attributes.constructorMethodType = true + mySettings.addItem(attributes, 0) + } + } + // public final void testClassRearrangement() throws Exception { // configureByFile("/com/wrq/rearranger/RearrangementTest.java"); // final PsiFile file = getFile(); diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult4.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult4.java index 12b241aa0be4..014128616905 100644 --- a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult4.java +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult4.java @@ -9,7 +9,6 @@ public class RearrangementTest { NoRearrangementTest() { // constructor body } - /** field 1. */ private int field1; private int field2; From e95772d51b5c5b81fbac9f63c3cb186b876d9ddf Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 16 May 2012 09:41:55 +0400 Subject: [PATCH 51/61] Symlink tests aren't yet ready --- .../com/intellij/openapi/vfs/local/FileWatcherTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java index e06a7aed76b5..fed864a1432f 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java @@ -16,7 +16,6 @@ package com.intellij.openapi.vfs.local; import com.intellij.execution.configurations.GeneralCommandLine; -import com.intellij.idea.Bombed; import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.Disposer; @@ -271,7 +270,7 @@ public class FileWatcherTest extends PlatformLangTestCase { } } - @Bombed(user = "roman.shevchenko", year = 2012, month = Calendar.MAY, day = 15) +/* public void testSymlinkAboveWatchRoot() throws Exception { final File topDir = FileUtil.createTempDirectory("top.", null); final File topLink = SymlinkHandlingTest.createTempLink(topDir.getAbsolutePath(), "link"); @@ -299,7 +298,6 @@ public class FileWatcherTest extends PlatformLangTestCase { } } - @Bombed(user = "roman.shevchenko", year = 2012, month = Calendar.MAY, day = 15) public void testSymlinkBelowWatchRoot() throws Exception { final File targetDir = FileUtil.createTempDirectory("top.", null); final File file = FileUtil.createTempFile(targetDir, "test.", ".txt", true, false); @@ -327,6 +325,7 @@ public class FileWatcherTest extends PlatformLangTestCase { delete(targetDir); } } +*/ public void testSubst() throws Exception { if (!SystemInfo.isWindows) { From a752411c88e27a844aedf3ad710a7bd1044f4f22 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Wed, 16 May 2012 09:54:24 +0400 Subject: [PATCH 52/61] IDEA-85100 Deleting wrapped lines with Ctrl+Y doen't work properly with "soft wrapped" lines More tests have been checked and added --- .../attributeGroups/FieldAttributes.java | 4 +- .../com/wrq/rearranger/RearrangerTest.groovy | 45 ++++++++----------- .../wrq/rearranger/RearrangementResult6.java | 6 +-- .../wrq/rearranger/RearrangementTest2.java | 4 +- 4 files changed, 24 insertions(+), 35 deletions(-) diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/FieldAttributes.java b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/FieldAttributes.java index 53c46a3a3ecb..c85fd2cc842a 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/FieldAttributes.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/attributeGroups/FieldAttributes.java @@ -36,9 +36,7 @@ import javax.swing.border.Border; import java.awt.*; /** Routines to handle field attributes not covered by CommonAttributes. */ -public final class FieldAttributes - extends ItemAttributes -{ +public final class FieldAttributes extends ItemAttributes { // ------------------------------ FIELDS ------------------------------ diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy b/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy index 0e8e62c9cd12..66d7b516f84f 100644 --- a/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy +++ b/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy @@ -25,6 +25,7 @@ package com.wrq.rearranger; import com.intellij.openapi.application.ApplicationManager import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import com.wrq.rearranger.settings.RearrangerSettings +import com.wrq.rearranger.settings.attributeGroups.ClassAttributes import com.wrq.rearranger.settings.attributeGroups.FieldAttributes import com.wrq.rearranger.settings.attributeGroups.MethodAttributes import org.jetbrains.annotations.NotNull @@ -82,33 +83,23 @@ class RearrangerTest extends LightCodeInsightFixtureTestCase { } } -// public final void testClassRearrangement() throws Exception { -// configureByFile("/com/wrq/rearranger/RearrangementTest.java"); -// final PsiFile file = getFile(); -// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); -// final ClassAttributes ca = new ClassAttributes(); -// ca.getPlAttr().setPlPackage(true); -// rs.addClass(ca, 0); -// final RearrangerActionHandler rah = new RearrangerActionHandler(); -// rah.rearrangeDocument(getProject(), file, rs, doc); -// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult5.java"); -// } -// -// public final void testPSFRearrangement() throws Exception { -// configureByFile("/com/wrq/rearranger/RearrangementTest2.java"); -// final PsiFile file = getFile(); -// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); -// final FieldAttributes fa; -// fa = new FieldAttributes(); -// fa.getPlAttr().setPlPublic(true); -// fa.getfAttr().setValue(true); -// fa.getStAttr().setValue(true); -// rs.addItem(fa, 0); -// final RearrangerActionHandler rah = new RearrangerActionHandler(); -// rah.rearrangeDocument(getProject(), file, rs, doc); -// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult6.java"); -// } -// + public final void testClassRearrangement() throws Exception { + doTest('RearrangementTest', 'RearrangementResult5') { + def attributes = new ClassAttributes() + attributes.protectionLevelAttributes.plPackage = true + mySettings.addClass(attributes, 0) + } + } + + public final void testPSFRearrangement() throws Exception { + doTest('RearrangementTest2', 'RearrangementResult6') { + def attributes = new FieldAttributes() + attributes.finalAttribute.value = true + attributes.staticAttribute.value = true + mySettings.addItem(attributes, 0) + } + } + // public final void testAnonClassInit() throws Exception { // configureByFile("/com/wrq/rearranger/RearrangementTest7.java"); // final PsiFile file = getFile(); diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult6.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult6.java index 84252bc72ceb..ad906364d310 100644 --- a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult6.java +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult6.java @@ -1,8 +1,8 @@ public class Test { public static final String sillyField = ""; public static final String sillyField2 = ""; - private String wibble; - protected String wobble; - public String hitandmiss; + private String wibble; + protected String wobble; + public String hitandmiss; public static int hithere; } diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest2.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest2.java index c94e9d4546f9..3a4ccb580857 100644 --- a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest2.java +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementTest2.java @@ -1,8 +1,8 @@ public class Test { private String wibble; protected String wobble; - public static final String sillyField = ""; - public String hitandmiss; + public static final String sillyField = ""; + public String hitandmiss; public static int hithere; public static final String sillyField2 = ""; } From 90f45748a9375abad8adba4a7523067f338d0246 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Mon, 14 May 2012 15:14:11 +0400 Subject: [PATCH 53/61] fix JavaStylePropertiesInvocation --- .../style/JavaStylePropertiesInvocationIntention.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/JavaStylePropertiesInvocationIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/JavaStylePropertiesInvocationIntention.java index 711886e11677..b2cb97656628 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/JavaStylePropertiesInvocationIntention.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/JavaStylePropertiesInvocationIntention.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -114,9 +114,10 @@ public class JavaStylePropertiesInvocationIntention extends Intention { else { method = call.resolveMethod(); if (!isSimplePropertySetter(method)) return false; + LOG.assertTrue(method != null); } - if (!GroovyNamesUtil.isValidReference(getPropertyNameByGetterName(method.getName(), true), + if (!GroovyNamesUtil.isValidReference(getPropertyNameBySetterName(method.getName()), ((GrReferenceExpression)expr).getQualifier() != null, call.getProject())) { return false; @@ -143,7 +144,7 @@ public class JavaStylePropertiesInvocationIntention extends Intention { PsiMethod method = call.resolveMethod(); if (!isSimplePropertyGetter(method)) return false; - + LOG.assertTrue(method != null); if (!GroovyNamesUtil.isValidReference(getPropertyNameByGetterName(method.getName(), true), ((GrReferenceExpression)expr).getQualifier() != null, call.getProject())) { From 4c0992bcabf6ec186d89e672092ab99e3f56e676 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Mon, 14 May 2012 15:15:13 +0400 Subject: [PATCH 54/61] suppress UnusedProperty in GroovyIntentionsBundle.properties --- .../groovy/intentions/GroovyIntentionsBundle.properties | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties index 00d90c07f79d..73d248fb114b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties @@ -1,3 +1,4 @@ +# suppress inspection "UnusedProperty" for whole file intention.category.groovy=Groovy intention.category.conversions=Expression conversions intention.category.closures=Closures @@ -84,8 +85,8 @@ convert.parameter.to.map.entry.intention.family.name=Convert method or closure p convert.parameter.to.map.entry.intention.name=Convert parameter to map entry find.method.ro.closure.usages.0=Searching for usages of enclosing {0} in project files conversion.not.allowed.in.non.groovy.files=Refactoring is not allowed for {0}s which have occurrences in non-Groovy files: \n -wrong.first.parameter.type={0} ''{1}'' is used with named arguments, but its first parameter ''{2}'' does not conform to Map type. -create.first.new=&Create new parameter for named arguments +wrong.first.parameter.type={0} ''{1}'' is used with named arguments, but its first parameter ''{2}'' does not conform to Map type. +create.first.new=&Create new parameter for named arguments do.not.create.first.new=Use &existing first parameter as map for named arguments convert.cannot.itself=Refactoring is not available for map parameter itself perform.refactoring=Performing refactoring From e2ed85b95d40d419e5705988f44f03f3f05e36c4 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Mon, 14 May 2012 15:23:56 +0400 Subject: [PATCH 55/61] correct name for intention category --- .../plugins/groovy/intentions/GroovyIntentionsBundle.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties index 73d248fb114b..f10fee212f67 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties @@ -5,6 +5,7 @@ intention.category.closures=Closures intention.category.comments=Comments intention.category.groovy.style=Groovy-style intention.category.control.flow=Control Flow +intention.category.groovy.declaration=Declaration demorgans.law.intention.family.name=DeMorgan's Law demorgans.intention.name1=Replace ''\\&\\&'' with ''||'' demorgans.intention.name2=Replace ''||'' with ''\\&\\&'' From a6b7faa32e555591e42b26d0509164569d9dbbf6 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Tue, 15 May 2012 14:59:37 +0400 Subject: [PATCH 56/61] create groovy method from usage in java file --- .../impl/quickfix/CreateFromUsageUtils.java | 31 +++-- .../quickfix/CreateMethodFromUsageFix.java | 80 ++++++++---- .../com/intellij/psi/JVMElementFactory.java | 9 +- .../psi/impl/PsiElementFactoryImpl.java | 30 ++++- .../parameters/ParameterDeclaration.java | 11 +- .../psi/impl/GroovyPsiElementFactoryImpl.java | 31 ++++- .../groovy/lang/psi/impl/PsiImplUtil.java | 15 ++- .../impl/statements/GrVariableBaseImpl.java | 4 +- .../typedef/GrTypeDefinitionImpl.java | 2 +- .../typedef/members/GrMethodBaseImpl.java | 4 +- .../typedef/members/GrMethodImpl.java | 14 +- .../synthetic/GrSyntheticTypeElement.java | 123 ++++++++++++++++++ .../impl/types/GrTypeParameterListImpl.java | 34 ++++- .../DefaultInitializerInJava_after.groovy | 17 ++- 14 files changed, 360 insertions(+), 45 deletions(-) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrSyntheticTypeElement.java diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java index 402fbc3fde63..bd80039efab6 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,8 @@ package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.*; import com.intellij.codeInsight.completion.proc.VariablesProcessor; import com.intellij.codeInsight.daemon.QuickFixBundle; +import com.intellij.codeInsight.generation.OverrideImplementUtil; +import com.intellij.codeInsight.generation.PsiGenerationInfo; import com.intellij.codeInsight.intention.impl.CreateClassDialog; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; @@ -129,7 +131,7 @@ public class CreateFromUsageUtils { returnType = PsiType.VOID; } - PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory(); + JVMElementFactory factory = JVMElementFactories.getFactory(aClass.getLanguage(), aClass.getProject()); LOG.assertTrue(!aClass.isInterface(), "Interface bodies should be already set up"); @@ -190,7 +192,7 @@ public class CreateFromUsageUtils { PsiElement r = PsiTreeUtil.skipSiblingsBackward(body.getRBrace(), PsiWhiteSpace.class); if (l != null && r != null) { int start = l.getTextRange().getStartOffset(); - int end = r.getTextRange().getEndOffset(); + int end = r.getTextRange().getEndOffset(); newEditor.getCaretModel().moveToOffset(Math.max(start, end)); if (end < start) { newEditor.getCaretModel().moveToOffset(end + 1); @@ -200,8 +202,11 @@ public class CreateFromUsageUtils { PsiDocumentManager manager = PsiDocumentManager.getInstance(method.getProject()); manager.doPostponedOperationsAndUnblockDocument(manager.getDocument(containingFile)); EditorModificationUtil.insertStringAtCaret(newEditor, lineIndent); - } else { - newEditor.getSelectionModel().setSelection(Math.min(start, end), Math.max(start, end)); + } + else { + //correct position caret for groovy and java methods + final PsiGenerationInfo info = OverrideImplementUtil.createGenerationInfo(method); + info.positionCaret(newEditor, true); } newEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); } @@ -225,13 +230,13 @@ public class CreateFromUsageUtils { final PsiSubstitutor substitutor, final List> arguments) throws IncorrectOperationException { PsiManager psiManager = method.getManager(); - PsiElementFactory factory = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory(); + JVMElementFactory factory = JVMElementFactories.getFactory(method.getLanguage(), method.getProject()); PsiParameterList parameterList = method.getParameterList(); GlobalSearchScope resolveScope = method.getResolveScope(); - GuessTypeParameters guesser = new GuessTypeParameters(factory); + GuessTypeParameters guesser = new GuessTypeParameters(JavaPsiFacade.getElementFactory(method.getProject())); final PsiClass containingClass = method.getContainingClass(); final boolean isInterface = containingClass != null && containingClass.isInterface(); @@ -943,6 +948,7 @@ public class CreateFromUsageUtils { @Nullable private static String getQualifiedName(final PsiClass aClass) { return ApplicationManager.getApplication().runReadAction(new Computable() { + @Nullable @Override public String compute() { return aClass.getQualifiedName(); @@ -993,7 +999,16 @@ public class CreateFromUsageUtils { assert file != null; PsiElement elementAt = file.findElementAt(offset); PsiParameterList parameterList = PsiTreeUtil.getParentOfType(elementAt, PsiParameterList.class); - if (parameterList == null) return LookupElement.EMPTY_ARRAY; + if (parameterList == null) { + if (elementAt == null) return LookupElement.EMPTY_ARRAY; + final PsiElement parent = elementAt.getParent(); + if (parent instanceof PsiMethod) { + parameterList = ((PsiMethod)parent).getParameterList(); + } + else { + return LookupElement.EMPTY_ARRAY; + } + } PsiParameter parameter = PsiTreeUtil.getParentOfType(elementAt, PsiParameter.class); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java index 98c10eb8ad7a..fb13632e2224 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -142,7 +142,10 @@ public class CreateMethodFromUsageFix extends CreateFromUsageBaseFix { String methodName = ref.getReferenceName(); LOG.assertTrue(methodName != null); - PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory(); + JVMElementFactory factory = JVMElementFactories.getFactory(targetClass.getLanguage(), project); + if (factory == null) { + return; + } PsiMethod method = factory.createMethod(methodName, PsiType.VOID); @@ -251,7 +254,13 @@ public class CreateMethodFromUsageFix extends CreateFromUsageBaseFix { if (typeParameters.length > 0) { for (PsiTypeParameter typeParameter : typeParameters) { if (checkTypeParam( method, typeParameter)) { - method.getTypeParameterList().add(typeParameter); + final JVMElementFactory factory = JVMElementFactories.getFactory(method.getLanguage(), method.getProject()); + PsiTypeParameterList list = method.getTypeParameterList(); + if (list == null) { + PsiTypeParameterList newList = factory.createTypeParameterList(); + list = (PsiTypeParameterList)method.addAfter(newList, method.getModifierList()); + } + list.add(factory.createTypeParameter(typeParameter.getName(),typeParameter.getExtendsList().getReferencedTypes())); } } } @@ -276,32 +285,59 @@ public class CreateMethodFromUsageFix extends CreateFromUsageBaseFix { } } - private static boolean checkTypeParam(final PsiElement typeElement, - final PsiTypeParameter typeParameter) { + private static boolean checkTypeParam(final PsiMethod method, final PsiTypeParameter typeParameter) { final String typeParameterName = typeParameter.getName(); - final boolean[] found = new boolean[] {false}; - typeElement.accept(new JavaRecursiveElementWalkingVisitor(){ + final PsiTypeVisitor visitor = new PsiTypeVisitor() { @Override - public void visitElement(PsiElement element) { - if (found[0]) return; - super.visitElement(element); - } - - @Override - public void visitTypeElement(PsiTypeElement type) { - super.visitTypeElement(type); - final PsiClass psiClass = PsiUtil.resolveClassInType(type.getType()); + public Boolean visitClassType(PsiClassType classType) { + final PsiClass psiClass = classType.resolve(); if (psiClass instanceof PsiTypeParameter && - PsiTreeUtil.isAncestor(((PsiTypeParameter)psiClass).getOwner(), typeElement, true)) { - return; + PsiTreeUtil.isAncestor(((PsiTypeParameter)psiClass).getOwner(), method, true)) { + return false; } - if (Comparing.strEqual(typeParameterName, type.getText())) { - found[0] = true; + if (Comparing.strEqual(typeParameterName, classType.getCanonicalText())) { + return true; } + for (PsiType p : classType.getParameters()) { + if (p.accept(this)) return true; + } + return false; } - }); - return found[0]; + + @Override + public Boolean visitPrimitiveType(PsiPrimitiveType primitiveType) { + return false; + } + + @Override + public Boolean visitArrayType(PsiArrayType arrayType) { + return arrayType.getComponentType().accept(this); + } + + @Override + public Boolean visitWildcardType(PsiWildcardType wildcardType) { + final PsiType bound = wildcardType.getBound(); + if (bound != null) { + return bound.accept(this); + } + return false; + } + }; + + final PsiTypeElement rElement = method.getReturnTypeElement(); + if (rElement != null) { + if (rElement.getType().accept(visitor)) return true; + } + + + for (PsiParameter parameter : method.getParameterList().getParameters()) { + final PsiTypeElement element = parameter.getTypeElement(); + if (element != null) { + if (element.getType().accept(visitor)) return true; + } + } + return false; } protected boolean shouldBeAbstract(PsiClass targetClass) { diff --git a/java/java-psi-api/src/com/intellij/psi/JVMElementFactory.java b/java/java-psi-api/src/com/intellij/psi/JVMElementFactory.java index 293be8bd1943..3e6487879d67 100644 --- a/java/java-psi-api/src/com/intellij/psi/JVMElementFactory.java +++ b/java/java-psi-api/src/com/intellij/psi/JVMElementFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -128,5 +128,12 @@ public interface JVMElementFactory { @NotNull PsiElement createExpressionFromText(@NotNull @NonNls String text, @Nullable PsiElement context) throws IncorrectOperationException; + @NotNull PsiElement createReferenceElementByType(PsiClassType type); + + @NotNull + PsiTypeParameterList createTypeParameterList(); + + @NotNull + PsiTypeParameter createTypeParameter(String name, PsiClassType[] superTypes); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java index 30e8d38b7624..5c876fb79274 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -169,6 +169,34 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps return new LightClassReference(myManager, type.getPresentableText(), refClass, resolveResult.getSubstitutor()); } + @NotNull + @Override + public PsiTypeParameterList createTypeParameterList() { + return createMethodFromText("void foo()", null).getTypeParameterList(); + } + + @NotNull + @Override + public PsiTypeParameter createTypeParameter(String name, PsiClassType[] superTypes) { + StringBuilder builder = new StringBuilder(); + builder.append("public <").append(name); + if (superTypes.length > 0) { + builder.append(" extends "); + for (PsiClassType type : superTypes) { + builder.append(type.getCanonicalText()).append(','); + } + + builder.delete(builder.length() - 1, builder.length()); + } + builder.append("> void foo(){}"); + try { + return createMethodFromText(builder.toString(), null).getTypeParameters()[0]; + } + catch (RuntimeException e) { + throw new IncorrectOperationException("type parameter text: " + builder.toString()); + } + } + @NotNull @Override public PsiField createField(@NotNull final String name, @NotNull final PsiType type) throws IncorrectOperationException { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/parameters/ParameterDeclaration.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/parameters/ParameterDeclaration.java index 17c6dea2ca3b..379274b22dcc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/parameters/ParameterDeclaration.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/parameters/ParameterDeclaration.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -85,12 +85,17 @@ public class ParameterDeclaration implements GroovyElementTypes { PsiBuilder.Marker rb = builder.mark(); - TypeSpec.parseStrict(builder); + final ReferenceElement.ReferenceElementResult result = TypeSpec.parseStrict(builder); if (mIDENT.equals(builder.getTokenType()) || (mTRIPLE_DOT.equals(builder.getTokenType()))) { rb.drop(); } - else { + else if (result == ReferenceElement.ReferenceElementResult.mustBeType) { + rb.drop(); + pdMarker.error(GroovyBundle.message("identifier.expected")); + return true; + } + else { rb.rollbackTo(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java index dabda0feaf5e..eb22d3caf49b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -158,6 +158,7 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { return (GrExpression) topStatements[0]; } + @NotNull @Override public GrCodeReferenceElement createReferenceElementByType(PsiClassType type) { if (type instanceof GrClassReferenceType) { @@ -173,6 +174,34 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { return createCodeReferenceElementFromText(type.getPresentableText()); } + @NotNull + @Override + public PsiTypeParameterList createTypeParameterList() { + return createMethodFromText("def <> void foo(){}").getTypeParameterList(); + } + + @NotNull + @Override + public PsiTypeParameter createTypeParameter(String name, PsiClassType[] superTypes) { + StringBuilder builder = new StringBuilder(); + builder.append("def <").append(name); + if (superTypes.length > 0) { + builder.append(" extends "); + for (PsiClassType type : superTypes) { + builder.append(type.getCanonicalText()).append(','); + } + + builder.delete(builder.length() - 1, builder.length()); + } + builder.append("> void foo(){}"); + try { + return createMethodFromText(builder.toString()).getTypeParameters()[0]; + } + catch (RuntimeException e) { + throw new IncorrectOperationException("type parameter text: " + builder.toString()); + } + } + public GrVariableDeclaration createVariableDeclaration(@Nullable String[] modifiers, @Nullable GrExpression initializer, @Nullable PsiType type, diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java index 6b81544df17a..2a9739930282 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -73,6 +73,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithme import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithmetic.GrMultiplicativeExpressionImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithmetic.GrRangeExpressionImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrSyntheticCodeBlock; +import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrSyntheticTypeElement; import org.jetbrains.plugins.groovy.lang.psi.util.GdkMethodUtil; import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; @@ -90,6 +91,7 @@ public class PsiImplUtil { private static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil"); private static final String MAIN_METHOD = "main"; public static final Key> PSI_CODE_BLOCK = Key.create("Psi_code_block"); + public static final Key> PSI_TYPE_ELEMENT = Key.create("psi.type.element"); private PsiImplUtil() { } @@ -535,6 +537,17 @@ public class PsiImplUtil { return newBody; } + public static PsiTypeElement getOrCreateTypeElement(@Nullable GrTypeElement typeElement) { + if (typeElement==null) return null; + + final SoftReference ref = typeElement.getUserData(PSI_TYPE_ELEMENT); + final PsiTypeElement element = ref == null ? null : ref.get(); + if (element != null) return element; + final GrSyntheticTypeElement newTypeElement = new GrSyntheticTypeElement(typeElement); + typeElement.putUserData(PSI_TYPE_ELEMENT, new SoftReference(newTypeElement)); + return newTypeElement; + } + public static T replaceBody(T newBody, GrStatement body, ASTNode node, Project project) { if (body == null || newBody == null) { throw new IncorrectOperationException(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableBaseImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableBaseImpl.java index 334b19bceb9d..6f8e7c9c1397 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableBaseImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableBaseImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -77,7 +77,7 @@ public abstract class GrVariableBaseImpl extends GrStubEl @Nullable public PsiTypeElement getTypeElement() { - return null; + return PsiImplUtil.getOrCreateTypeElement(getTypeElementGroovy()); } @Nullable diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java index d4f7b4cf2567..b62f4ef64866 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java index 1d8b1d0ec8af..9a02f6bc73fd 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -292,7 +292,7 @@ public abstract class GrMethodBaseImpl extends GrStubElementBase i @Nullable public PsiTypeElement getReturnTypeElement() { - return null; + return PsiImplUtil.getOrCreateTypeElement(getReturnTypeElementGroovy()); } @NotNull diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodImpl.java index 6bc7c5348f43..ffc55d2e3a73 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,9 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.members; import com.intellij.lang.ASTNode; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameterList; import org.jetbrains.plugins.groovy.lang.psi.stubs.GrMethodStub; /** @@ -36,6 +38,16 @@ public class GrMethodImpl extends GrMethodBaseImpl implements GrMethod { super(stub, GroovyElementTypes.METHOD_DEFINITION); } + @Override + public ASTNode addInternal(ASTNode first, ASTNode last, ASTNode anchor, Boolean before) { + if (first == last && first.getPsi() instanceof GrTypeParameterList) { + if (!getModifierList().hasExplicitVisibilityModifiers()) { + getModifierList().setModifierProperty(GrModifier.DEF, true); + } + } + return super.addInternal(first, last, anchor, before); + } + public String toString() { return "Method"; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrSyntheticTypeElement.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrSyntheticTypeElement.java new file mode 100644 index 000000000000..f144f4a06026 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrSyntheticTypeElement.java @@ -0,0 +1,123 @@ +/* + * 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 org.jetbrains.plugins.groovy.lang.psi.impl.synthetic; + +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.intellij.psi.impl.light.LightElement; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; +import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; + +/** + * @author Max Medvedev + */ +public class GrSyntheticTypeElement extends LightElement implements PsiTypeElement { + @NotNull private final GrTypeElement myElement; + + public GrSyntheticTypeElement(@NotNull GrTypeElement element) { + super(element.getManager(), element.getLanguage()); + + myElement = element; + } + + @NotNull + @Override + public PsiType getType() { + return myElement.getType(); + } + + @Override + public PsiJavaCodeReferenceElement getInnermostComponentReferenceElement() { + return null; + } + + @Override + public PsiAnnotationOwner getOwner(PsiAnnotation annotation) { + return null; + } + + @Override + public PsiType getTypeNoResolve(@NotNull PsiElement context) { + return myElement.getType(); + } + + @NotNull + @Override + public PsiAnnotation[] getAnnotations() { + return PsiAnnotation.EMPTY_ARRAY; + } + + @NotNull + @Override + public PsiAnnotation[] getApplicableAnnotations() { + return PsiAnnotation.EMPTY_ARRAY; + } + + @Override + public PsiAnnotation findAnnotation(@NotNull @NonNls String qualifiedName) { + return null; + } + + @NotNull + @Override + public PsiAnnotation addAnnotation(@NotNull @NonNls String qualifiedName) { + throw new UnsupportedOperationException(); + } + + @Override + public String toString() { + return "Synthetic PsiTypeElement"; + } + + @Override + public TextRange getTextRange() { + return myElement.getTextRange(); + } + + @Override + public int getTextOffset() { + return myElement.getTextOffset(); + } + + @Override + public String getText() { + return myElement.getText(); + } + + @Override + public boolean isValid() { + return myElement.isValid(); + } + + @Override + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JavaElementVisitor) { + ((JavaElementVisitor)visitor).visitTypeElement(this); + } + } + + @Override + public void acceptChildren(@NotNull PsiElementVisitor visitor) { + final PsiElement[] children = myElement.getChildren(); + for (PsiElement child : children) { + if (child instanceof GrTypeElement) { + PsiImplUtil.getOrCreateTypeElement((GrTypeElement)child).accept(visitor); + } + } + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrTypeParameterListImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrTypeParameterListImpl.java index 197534082d94..f089d1a9f252 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrTypeParameterListImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrTypeParameterListImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ import com.intellij.psi.StubBasedPsiElement; import com.intellij.psi.stubs.EmptyStub; import com.intellij.util.ArrayFactory; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameter; @@ -74,4 +75,35 @@ public class GrTypeParameterListImpl extends GrStubElementBase implem public void accept(GroovyElementVisitor visitor) { visitor.visitTypeParameterList(this); } + + @Override + public ASTNode addInternal(ASTNode first, ASTNode last, ASTNode anchor, Boolean before) { + if (first == last && first.getPsi() instanceof GrTypeParameter) { + boolean hasParams = getTypeParameters().length > 0; + + final ASTNode _anchor; + + if (anchor == null) { + if (before.booleanValue()) { + _anchor = getLastChild().getNode(); + } + else { + _anchor = getFirstChild().getNode(); + } + } + else { + _anchor = anchor; + } + + + final ASTNode node = super.addInternal(first, last, _anchor, before); + if (hasParams) { + getNode().addLeaf(GroovyTokenTypes.mCOMMA, ",", anchor != null ? anchor : node); + } + return node; + } + else { + return super.addInternal(first, last, anchor, before); + } + } } diff --git a/plugins/groovy/testdata/refactoring/changeSignature/DefaultInitializerInJava_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/DefaultInitializerInJava_after.groovy index a96448e49cf8..1af7c4e5372c 100644 --- a/plugins/groovy/testdata/refactoring/changeSignature/DefaultInitializerInJava_after.groovy +++ b/plugins/groovy/testdata/refactoring/changeSignature/DefaultInitializerInJava_after.groovy @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ class GClass { - public test(def p = 1) {} + public void test(def p = 1) {} } \ No newline at end of file From e5b412d4c3b1787c02697cb478ff6e5c796d2b90 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Tue, 15 May 2012 19:04:46 +0400 Subject: [PATCH 57/61] 'create groovy method from usage' position caret at the beginning of selection --- .../quickFix/addMethodBody/after1.java | 18 +++++++++++++++++- .../quickFix/addMethodBody/after2.java | 18 +++++++++++++++++- .../quickFix/addMethodBody/after3.java | 18 +++++++++++++++++- .../quickFix/addMethodBody/after4.java | 18 +++++++++++++++++- .../createConstructorFromCall/afterAnon.java | 18 +++++++++++++++++- .../quickFix/createMethodFromUsage/after1.java | 18 +++++++++++++++++- .../quickFix/createMethodFromUsage/after3.java | 18 +++++++++++++++++- .../quickFix/createMethodFromUsage/after4.java | 18 +++++++++++++++++- .../quickFix/createMethodFromUsage/after5.java | 18 +++++++++++++++++- .../createMethodFromUsage/afterGenerics1.java | 18 +++++++++++++++++- .../createMethodFromUsage/afterIDEA2327.java | 18 +++++++++++++++++- .../afterMultipleTypes.java | 18 +++++++++++++++++- .../createMethodFromUsage/afterSCR6758.java | 18 +++++++++++++++++- .../createMethodFromUsage/afterSCR6826.java | 18 +++++++++++++++++- .../createMethodFromUsage/afterThisCall.java | 18 +++++++++++++++++- .../genericCreateFromUsage/after2.java | 18 +++++++++++++++++- .../genericCreateFromUsage/after3.java | 18 +++++++++++++++++- .../genericCreateFromUsage/after4.java | 18 +++++++++++++++++- 18 files changed, 306 insertions(+), 18 deletions(-) diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after1.java index f14d2102e2a0..c7eaf9f58723 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after1.java @@ -1,7 +1,23 @@ +/* + * 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. + */ + // "Add Method Body" "true" class a { void f() { - //To change body of created methods use File | Settings | File Templates. + //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after2.java index 36cbcd775bd5..26ea2b53ffef 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after2.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after2.java @@ -1,7 +1,23 @@ +/* + * 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. + */ + // "Add Method Body" "true" class a { String f() { - return null; //To change body of created methods use File | Settings | File Templates. + return null; //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after3.java index 93d757e462dc..113fa9f7c9a1 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after3.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after3.java @@ -1,7 +1,23 @@ +/* + * 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. + */ + // "Add Method Body" "true" class a { a() { - //To change body of created methods use File | Settings | File Templates. + //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after4.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after4.java index 36cbcd775bd5..26ea2b53ffef 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after4.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after4.java @@ -1,7 +1,23 @@ +/* + * 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. + */ + // "Add Method Body" "true" class a { String f() { - return null; //To change body of created methods use File | Settings | File Templates. + return null; //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorFromCall/afterAnon.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorFromCall/afterAnon.java index 38d6440e5fc3..4bfaa1117dd2 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorFromCall/afterAnon.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorFromCall/afterAnon.java @@ -1,3 +1,19 @@ +/* + * 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. + */ + // "Create Constructor" "true" class Test { @@ -7,7 +23,7 @@ class Test { class Inner { public Inner(String a) { - //To change body of created methods use File | Settings | File Templates. + //To change body of created methods use File | Settings | File Templates. } } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after1.java index 06dcc5d95612..8fb40a7e1033 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after1.java @@ -1,3 +1,19 @@ +/* + * 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. + */ + // "Create Method 'test'" "true" public class Test { public Test() { @@ -5,6 +21,6 @@ public class Test { } private void test() { - //To change body of created methods use File | Settings | File Templates. + //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after3.java index 06dcc5d95612..8fb40a7e1033 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after3.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after3.java @@ -1,3 +1,19 @@ +/* + * 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. + */ + // "Create Method 'test'" "true" public class Test { public Test() { @@ -5,6 +21,6 @@ public class Test { } private void test() { - //To change body of created methods use File | Settings | File Templates. + //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after4.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after4.java index 06dcc5d95612..8fb40a7e1033 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after4.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after4.java @@ -1,3 +1,19 @@ +/* + * 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. + */ + // "Create Method 'test'" "true" public class Test { public Test() { @@ -5,6 +21,6 @@ public class Test { } private void test() { - //To change body of created methods use File | Settings | File Templates. + //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after5.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after5.java index 4fa03f9052c9..fa9eab2ad8b4 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after5.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after5.java @@ -1,3 +1,19 @@ +/* + * 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. + */ + // "Create Method 'test'" "true" public class Test { static void test(int i) {} @@ -6,6 +22,6 @@ public class Test { } private void test() { - //To change body of created methods use File | Settings | File Templates. + //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterGenerics1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterGenerics1.java index a795db622a21..f68068daca60 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterGenerics1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterGenerics1.java @@ -1,3 +1,19 @@ +/* + * 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. + */ + // "Create Method 'bar'" "true" public class Test { void foo (T t1, T t2) { @@ -5,6 +21,6 @@ public class Test { } private void bar(T t1, T t2) { - //To change body of created methods use File | Settings | File Templates. + //To change body of created methods use File | Settings | File Templates. } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterIDEA2327.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterIDEA2327.java index b8ae9abff9a1..e3ddff59e351 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterIDEA2327.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterIDEA2327.java @@ -1,3 +1,19 @@ +/* + * 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. + */ + // "Create Method 'test'" "true" public class Test { public Test() { @@ -5,6 +21,6 @@ public class Test { } private boolean test() { - return false; //To change body of created methods use File | Settings | File Templates. + return false; //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterMultipleTypes.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterMultipleTypes.java index 721f359ff734..d1c2fddbb8fd 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterMultipleTypes.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterMultipleTypes.java @@ -1,3 +1,19 @@ +/* + * 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. + */ + // "Create Method 'bar'" "true" class A { public void foo() { @@ -6,6 +22,6 @@ class A { } private String bar() { - return null; //To change body of created methods use File | Settings | File Templates. + return null; //To change body of created methods use File | Settings | File Templates. } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6758.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6758.java index 6c031ec0864d..ce16c9bdb494 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6758.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6758.java @@ -1,3 +1,19 @@ +/* + * 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. + */ + // "Create Method 'someMethod'" "true" public class Test { @@ -8,7 +24,7 @@ public class Test { } private boolean someMethod(Object o) { - return false; //To change body of created methods use File | Settings | File Templates. + return false; //To change body of created methods use File | Settings | File Templates. } }; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6826.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6826.java index 4c8e7720ee23..dd66e450b591 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6826.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6826.java @@ -1,3 +1,19 @@ +/* + * 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. + */ + // "Create Method 'f'" "true" class A { { @@ -10,6 +26,6 @@ class A { } class B { public static void f(Runnable runnable) { - //To change body of created methods use File | Settings | File Templates. + //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterThisCall.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterThisCall.java index 9df64fc0ad6a..dfc4902afd44 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterThisCall.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterThisCall.java @@ -1,3 +1,19 @@ +/* + * 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. + */ + // "Create Method 'f'" "true" public class A { public A() { @@ -5,7 +21,7 @@ public class A { } private static int f() { - return 0; //To change body of created methods use File | Settings | File Templates. + return 0; //To change body of created methods use File | Settings | File Templates. } public A(int i) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after2.java index fe993f4a50ad..9dacd82a6301 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after2.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after2.java @@ -1,7 +1,23 @@ +/* + * 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. + */ + // "Create Method 'get'" "true" class Generic { public T get() { - return null; //To change body of created methods use File | Settings | File Templates. + return null; //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after3.java index 1834689ef58d..b373fd4b3cdb 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after3.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after3.java @@ -1,10 +1,26 @@ +/* + * 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. + */ + // "Create Method 'foo'" "true" interface Int { } class A1 implements Int { public void foo(Int c) { - //To change body of created methods use File | Settings | File Templates. + //To change body of created methods use File | Settings | File Templates. } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after4.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after4.java index 990d292d8d3a..ceb8f27192a9 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after4.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after4.java @@ -1,3 +1,19 @@ +/* + * 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. + */ + // "Create Method 'foo'" "true" interface Comparable { } @@ -8,7 +24,7 @@ class R implements Comparable { class A1 { public T foo() { - return null; //To change body of created methods use File | Settings | File Templates. + return null; //To change body of created methods use File | Settings | File Templates. } } From c140ff201f91b2a6ef0b7145a1ea425109bc41d6 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Wed, 16 May 2012 10:10:00 +0400 Subject: [PATCH 58/61] copyright in testdata --- .../DefaultInitializerInJava.groovy | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/plugins/groovy/testdata/refactoring/changeSignature/DefaultInitializerInJava.groovy b/plugins/groovy/testdata/refactoring/changeSignature/DefaultInitializerInJava.groovy index 7ae2a99dca0b..1ec30ed5cc8e 100644 --- a/plugins/groovy/testdata/refactoring/changeSignature/DefaultInitializerInJava.groovy +++ b/plugins/groovy/testdata/refactoring/changeSignature/DefaultInitializerInJava.groovy @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ class GClass { public void test() {} } \ No newline at end of file From 861efe85adeb8a0a32cdbb4047ec938e929469d8 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Wed, 16 May 2012 10:37:48 +0400 Subject: [PATCH 59/61] create groovy method from usage by groovy ref --- .../impl/quickfix/CreateFromUsageUtils.java | 1 + .../quickfix/CreateMethodFromUsageFix.java | 2 +- .../template/impl/JavaTemplateUtil.java | 8 +- .../groovy/annotator/GroovyAnnotator.java | 8 +- .../annotator/intentions/CreateClassFix.java | 6 +- .../intentions/CreateMethodFromUsageFix.java | 65 +++++++------- .../intentions/base/IntentionUtils.java | 90 ++++++++++++++----- .../expressions/ChooseTypeExpression.java | 10 ++- 8 files changed, 125 insertions(+), 65 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java index bd80039efab6..d966cb14d7a7 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java @@ -202,6 +202,7 @@ public class CreateFromUsageUtils { PsiDocumentManager manager = PsiDocumentManager.getInstance(method.getProject()); manager.doPostponedOperationsAndUnblockDocument(manager.getDocument(containingFile)); EditorModificationUtil.insertStringAtCaret(newEditor, lineIndent); + EditorModificationUtil.insertStringAtCaret(newEditor, "\n", false, false); } else { //correct position caret for groovy and java methods diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java index fb13632e2224..8117897e5965 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateMethodFromUsageFix.java @@ -285,7 +285,7 @@ public class CreateMethodFromUsageFix extends CreateFromUsageBaseFix { } } - private static boolean checkTypeParam(final PsiMethod method, final PsiTypeParameter typeParameter) { + public static boolean checkTypeParam(final PsiMethod method, final PsiTypeParameter typeParameter) { final String typeParameterName = typeParameter.getName(); final PsiTypeVisitor visitor = new PsiTypeVisitor() { diff --git a/java/java-impl/src/com/intellij/codeInsight/template/impl/JavaTemplateUtil.java b/java/java-impl/src/com/intellij/codeInsight/template/impl/JavaTemplateUtil.java index 8768820d289b..f21854b70a23 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/impl/JavaTemplateUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/impl/JavaTemplateUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -54,11 +54,15 @@ public class JavaTemplateUtil { PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class); if (method != null) { PsiTypeParameterList paramList = method.getTypeParameterList(); - PsiTypeParameter[] params = paramList.getTypeParameters(); + PsiTypeParameter[] params = paramList != null ? paramList.getTypeParameters() : PsiTypeParameter.EMPTY_ARRAY; for (PsiTypeParameter param : params) { if (param.getName().equals(aClass.getName())) return; } try { + if (paramList == null) { + final PsiTypeParameterList newList = JVMElementFactories.getFactory(method.getLanguage(), project).createTypeParameterList(); + paramList = (PsiTypeParameterList)method.addAfter(newList, method.getModifierList()); + } paramList.add(aClass.copy()); PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index d0f4e3966024..1d0368b1bfff 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -1785,13 +1785,15 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { if (targetClass == null) return; addDynamicAnnotation(annotation, refExpr); - if (targetClass instanceof GrMemberOwner && targetClass.isWritable()) { + if (targetClass.isWritable()) { if (!(targetClass instanceof GroovyScriptClass)) { - annotation.registerFix(new CreateFieldFromUsageFix(refExpr, (GrMemberOwner)targetClass)); + if (targetClass instanceof GrMemberOwner) { + annotation.registerFix(new CreateFieldFromUsageFix(refExpr, (GrMemberOwner)targetClass)); + } } if (refExpr.getParent() instanceof GrCall && refExpr.getParent() instanceof GrExpression) { - annotation.registerFix(new CreateMethodFromUsageFix(refExpr, (GrMemberOwner)targetClass)); + annotation.registerFix(new CreateMethodFromUsageFix(refExpr, targetClass)); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java index 277c4cd30a1b..dcc285a8e05b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -84,7 +85,8 @@ public abstract class CreateClassFix { GrMethod method = GroovyPsiElementFactory.getInstance(project).createConstructorFromText(name, paramTypes, paramNames, "{\n}"); method = targetClass.addMemberDeclaration(method, null); - IntentionUtils.createTemplateForMethod(argTypes, paramTypesExpressions, method, targetClass, new TypeConstraint[0], true); + final PsiNameIdentifierOwner context = PsiTreeUtil.getParentOfType(myRefElement, PsiMethod.class, PsiClass.class); + IntentionUtils.createTemplateForMethod(argTypes, paramTypesExpressions, method, targetClass, new TypeConstraint[0], true, context); } else { putCursor(project, targetClass.getContainingFile(), targetClass); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateMethodFromUsageFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateMethodFromUsageFix.java index e051436b712f..8b02cc79bd6b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateMethodFromUsageFix.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateMethodFromUsageFix.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,9 +18,7 @@ package org.jetbrains.plugins.groovy.annotator.intentions; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiType; +import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; @@ -28,12 +26,8 @@ import org.jetbrains.plugins.groovy.GroovyBundle; import org.jetbrains.plugins.groovy.intentions.base.IntentionUtils; import org.jetbrains.plugins.groovy.lang.editor.template.expressions.ChooseTypeExpression; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; -import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SupertypeConstraint; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint; @@ -45,10 +39,10 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; * @author ven */ public class CreateMethodFromUsageFix implements IntentionAction { - private final GrMemberOwner myTargetClass; + private final PsiClass myTargetClass; private final GrReferenceExpression myRefExpression; - public CreateMethodFromUsageFix(GrReferenceExpression refExpression, GrMemberOwner targetClass) { + public CreateMethodFromUsageFix(GrReferenceExpression refExpression, PsiClass targetClass) { myRefExpression = refExpression; myTargetClass = targetClass; } @@ -68,27 +62,21 @@ public class CreateMethodFromUsageFix implements IntentionAction { } public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - StringBuilder methodBuffer = new StringBuilder(); - if (PsiUtil.isInStaticContext(myRefExpression, myTargetClass)) methodBuffer.append("static "); - methodBuffer.append("Object ").append(myRefExpression.getReferenceName()).append(" ("); + final JVMElementFactory factory = JVMElementFactories.getFactory(myTargetClass.getLanguage(), project); + PsiMethod method = factory.createMethod(myRefExpression.getReferenceName(), PsiType.VOID); + if (PsiUtil.isInStaticContext(myRefExpression, myTargetClass)) { + method.getModifierList().setModifierProperty(PsiModifier.STATIC, true); + } + PsiType[] argTypes = PsiUtil.getArgumentTypes(myRefExpression, false); assert argTypes != null; - ChooseTypeExpression[] paramTypesExpressions = new ChooseTypeExpression[argTypes.length]; - for (int i = 0; i < argTypes.length; i++) { - PsiType argType = argTypes[i]; - if (argType == null) argType = TypesUtil.getJavaLangObject(myRefExpression); - if (i > 0) methodBuffer.append(", "); - methodBuffer.append("Object o").append(i); - paramTypesExpressions[i] = - new ChooseTypeExpression(new TypeConstraint[]{SupertypeConstraint.create(argType)}, myRefExpression.getManager()); - } - methodBuffer.append(") {\n}"); - GrMethod method = GroovyPsiElementFactory.getInstance(project).createMethodFromText(methodBuffer.toString()); - GrMemberOwner owner = myTargetClass; + + ChooseTypeExpression[] paramTypesExpressions = setupParams(method, argTypes, factory); + TypeConstraint[] constraints = GroovyExpectedTypesProvider.calculateTypeConstraints((GrExpression)myRefExpression.getParent()); - PsiElement parent = myTargetClass instanceof GrTypeDefinition - ? ((GrTypeDefinition)myTargetClass).getBody() - : ((GroovyScriptClass)myTargetClass).getContainingFile(); + PsiElement parent = myTargetClass instanceof GroovyScriptClass + ? ((GroovyScriptClass)myTargetClass).getContainingFile() + : myTargetClass; if (PsiTreeUtil.isAncestor(parent, myRefExpression, false)) { PsiElement prevParent = PsiTreeUtil.findPrevParent(parent, myRefExpression); PsiElement sibling = PsiUtil.skipWhitespaces(prevParent.getNextSibling(), true); @@ -98,13 +86,28 @@ public class CreateMethodFromUsageFix implements IntentionAction { else { sibling = prevParent.getNextSibling(); } - method = owner.addMemberDeclaration(method, sibling); + method = (PsiMethod)myTargetClass.addAfter(method, sibling); } else { - method = owner.addMemberDeclaration(method, null); + method = (PsiMethod)myTargetClass.add(method); } - IntentionUtils.createTemplateForMethod(argTypes, paramTypesExpressions, method, owner, constraints, false); + final PsiElement context = PsiTreeUtil.getParentOfType(myRefExpression, PsiClass.class, PsiMethod.class); + IntentionUtils.createTemplateForMethod(argTypes, paramTypesExpressions, method, myTargetClass, constraints, false, context); + } + + private ChooseTypeExpression[] setupParams(PsiMethod method, PsiType[] argTypes, JVMElementFactory factory) { + final PsiParameterList parameterList = method.getParameterList(); + + ChooseTypeExpression[] paramTypesExpressions = new ChooseTypeExpression[argTypes.length]; + for (int i = 0; i < argTypes.length; i++) { + PsiType argType = TypesUtil.unboxPrimitiveTypeWrapper(argTypes[i]); + if (argType == null) argType = TypesUtil.getJavaLangObject(myRefExpression); + final PsiParameter p = factory.createParameter("o", argType); + parameterList.add(p); + paramTypesExpressions[i] = new ChooseTypeExpression(new TypeConstraint[]{SupertypeConstraint.create(argType)}, myRefExpression.getManager()); + } + return paramTypesExpressions; } public boolean startInWriteAction() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java index eefcae38a423..5b25841fc6dd 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/IntentionUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,15 +16,16 @@ package org.jetbrains.plugins.groovy.intentions.base; import com.intellij.codeInsight.CodeInsightUtilBase; -import com.intellij.codeInsight.template.Template; -import com.intellij.codeInsight.template.TemplateBuilderImpl; -import com.intellij.codeInsight.template.TemplateManager; +import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils; +import com.intellij.codeInsight.daemon.impl.quickfix.CreateMethodFromUsageFix; +import com.intellij.codeInsight.template.*; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiManager; -import com.intellij.psi.PsiType; +import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -33,12 +34,7 @@ import org.jetbrains.plugins.groovy.lang.editor.template.expressions.ChooseTypeE import org.jetbrains.plugins.groovy.lang.editor.template.expressions.ParameterNameExpression; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; -import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint; /** @@ -47,6 +43,8 @@ import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint; */ public class IntentionUtils { + private static final Logger LOG = Logger.getInstance(IntentionUtils.class); + public static void replaceExpression(@NotNull String newExpression, @NotNull GrExpression expression) throws IncorrectOperationException { final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(expression.getProject()); final GrExpression newCall = factory.createExpressionFromText(newExpression); @@ -62,27 +60,29 @@ public class IntentionUtils { public static void createTemplateForMethod(PsiType[] argTypes, ChooseTypeExpression[] paramTypesExpressions, - GrMethod method, - GrMemberOwner owner, - TypeConstraint[] constraints, boolean isConstructor) { + PsiMethod method, + PsiClass owner, + TypeConstraint[] constraints, + boolean isConstructor, + final PsiElement context) { - Project project = owner.getProject(); - GrTypeElement typeElement = method.getReturnTypeElementGroovy(); + final Project project = owner.getProject(); + PsiTypeElement typeElement = method.getReturnTypeElement(); ChooseTypeExpression expr = new ChooseTypeExpression(constraints, PsiManager.getInstance(project)); TemplateBuilderImpl builder = new TemplateBuilderImpl(method); if (!isConstructor) { assert typeElement != null; builder.replaceElement(typeElement, expr); } - GrParameter[] parameters = method.getParameterList().getParameters(); + PsiParameter[] parameters = method.getParameterList().getParameters(); assert parameters.length == argTypes.length; for (int i = 0; i < parameters.length; i++) { - GrParameter parameter = parameters[i]; - GrTypeElement parameterTypeElement = parameter.getTypeElementGroovy(); + PsiParameter parameter = parameters[i]; + PsiTypeElement parameterTypeElement = parameter.getTypeElement(); builder.replaceElement(parameterTypeElement, paramTypesExpressions[i]); - builder.replaceElement(parameter.getNameIdentifierGroovy(), new ParameterNameExpression()); + builder.replaceElement(parameter.getNameIdentifier(), new ParameterNameExpression()); } - GrOpenBlock body = method.getBlock(); + PsiCodeBlock body = method.getBody(); assert body != null; PsiElement lbrace = body.getLBrace(); assert lbrace != null; @@ -91,11 +91,53 @@ public class IntentionUtils { method = CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(method); Template template = builder.buildTemplate(); - Editor newEditor = QuickfixUtil.positionCursor(project, owner.getContainingFile(), method); + final PsiFile targetFile = owner.getContainingFile(); + final Editor newEditor = QuickfixUtil.positionCursor(project, targetFile, method); TextRange range = method.getTextRange(); newEditor.getDocument().deleteString(range.getStartOffset(), range.getEndOffset()); TemplateManager manager = TemplateManager.getInstance(project); - manager.startTemplate(newEditor, template); + + + TemplateEditingListener templateListener = new TemplateEditingAdapter() { + @Override + public void templateFinished(Template template, boolean brokenOff) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + PsiDocumentManager.getInstance(project).commitDocument(newEditor.getDocument()); + final int offset = newEditor.getCaretModel().getOffset(); + PsiMethod method = PsiTreeUtil.findElementOfClassAtOffset(targetFile, offset - 1, PsiMethod.class, false); + if (context instanceof PsiMethod) { + final PsiTypeParameter[] typeParameters = ((PsiMethod)context).getTypeParameters(); + if (typeParameters.length > 0) { + for (PsiTypeParameter typeParameter : typeParameters) { + if (CreateMethodFromUsageFix.checkTypeParam(method, typeParameter)) { + final JVMElementFactory factory = JVMElementFactories.getFactory(method.getLanguage(), method.getProject()); + PsiTypeParameterList list = method.getTypeParameterList(); + if (list == null) { + PsiTypeParameterList newList = factory.createTypeParameterList(); + list = (PsiTypeParameterList)method.addAfter(newList, method.getModifierList()); + } + list.add(factory.createTypeParameter(typeParameter.getName(), typeParameter.getExtendsList().getReferencedTypes())); + } + } + } + } + if (method != null) { + try { + CreateFromUsageUtils.setupMethodBody(method); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + + CreateFromUsageUtils.setupEditor(method, newEditor); + } + } + }); + } + }; + manager.startTemplate(newEditor, template, templateListener); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/template/expressions/ChooseTypeExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/template/expressions/ChooseTypeExpression.java index b2cc84051433..d5e4a2dd2cbc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/template/expressions/ChooseTypeExpression.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/template/expressions/ChooseTypeExpression.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ import com.intellij.codeInsight.template.Expression; import com.intellij.codeInsight.template.ExpressionContext; import com.intellij.codeInsight.template.PsiTypeResult; import com.intellij.codeInsight.template.Result; +import com.intellij.openapi.editor.Document; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTypesUtil; @@ -86,7 +87,12 @@ public class ChooseTypeExpression extends Expression { PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments(); PsiType type = myTypePointer.getType(); if (type != null) { - return new PsiTypeResult(type, context.getProject()); + return new PsiTypeResult(type, context.getProject()) { + @Override + public void handleRecalc(PsiFile psiFile, Document document, int segmentStart, int segmentEnd) { + if (myItems.length <= 1) super.handleRecalc(psiFile, document, segmentStart, segmentEnd); + } + }; } return null; From 764a7bd65cab9a1c2fc3181a1eb26d4c4036c388 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Wed, 16 May 2012 12:20:46 +0400 Subject: [PATCH 60/61] copyright in testdata --- .../quickFix/addMethodBody/after1.java | 16 ------- .../quickFix/addMethodBody/after2.java | 16 ------- .../quickFix/addMethodBody/after3.java | 16 ------- .../quickFix/addMethodBody/after4.java | 16 ------- .../createConstructorFromCall/afterAnon.java | 16 ------- .../createMethodFromUsage/after1.java | 16 ------- .../createMethodFromUsage/after3.java | 16 ------- .../createMethodFromUsage/after4.java | 16 ------- .../createMethodFromUsage/after5.java | 16 ------- .../createMethodFromUsage/afterGenerics1.java | 16 ------- .../createMethodFromUsage/afterIDEA2327.java | 16 ------- .../afterMultipleTypes.java | 16 ------- .../createMethodFromUsage/afterSCR6758.java | 16 ------- .../createMethodFromUsage/afterSCR6826.java | 16 ------- .../createMethodFromUsage/afterThisCall.java | 16 ------- .../genericCreateFromUsage/after2.java | 16 ------- .../genericCreateFromUsage/after3.java | 16 ------- .../genericCreateFromUsage/after4.java | 16 ------- .../groovy/formatter/AlignmentProvider.java | 47 ++++++++++++++----- .../formatter/GroovyBlockGenerator.java | 4 +- 20 files changed, 38 insertions(+), 301 deletions(-) diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after1.java index c7eaf9f58723..5bbdb484f3c6 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after1.java @@ -1,19 +1,3 @@ -/* - * 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. - */ - // "Add Method Body" "true" class a { void f() { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after2.java index 26ea2b53ffef..844bc3b1b2ba 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after2.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after2.java @@ -1,19 +1,3 @@ -/* - * 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. - */ - // "Add Method Body" "true" class a { String f() { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after3.java index 113fa9f7c9a1..6cd2bdc785c6 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after3.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after3.java @@ -1,19 +1,3 @@ -/* - * 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. - */ - // "Add Method Body" "true" class a { a() { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after4.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after4.java index 26ea2b53ffef..844bc3b1b2ba 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after4.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addMethodBody/after4.java @@ -1,19 +1,3 @@ -/* - * 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. - */ - // "Add Method Body" "true" class a { String f() { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorFromCall/afterAnon.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorFromCall/afterAnon.java index 4bfaa1117dd2..709c0645ae5b 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorFromCall/afterAnon.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorFromCall/afterAnon.java @@ -1,19 +1,3 @@ -/* - * 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. - */ - // "Create Constructor" "true" class Test { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after1.java index 8fb40a7e1033..8a94eda2675e 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after1.java @@ -1,19 +1,3 @@ -/* - * 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. - */ - // "Create Method 'test'" "true" public class Test { public Test() { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after3.java index 8fb40a7e1033..8a94eda2675e 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after3.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after3.java @@ -1,19 +1,3 @@ -/* - * 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. - */ - // "Create Method 'test'" "true" public class Test { public Test() { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after4.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after4.java index 8fb40a7e1033..8a94eda2675e 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after4.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after4.java @@ -1,19 +1,3 @@ -/* - * 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. - */ - // "Create Method 'test'" "true" public class Test { public Test() { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after5.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after5.java index fa9eab2ad8b4..16607155d34b 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after5.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/after5.java @@ -1,19 +1,3 @@ -/* - * 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. - */ - // "Create Method 'test'" "true" public class Test { static void test(int i) {} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterGenerics1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterGenerics1.java index f68068daca60..ed3f5ed75de0 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterGenerics1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterGenerics1.java @@ -1,19 +1,3 @@ -/* - * 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. - */ - // "Create Method 'bar'" "true" public class Test { void foo (T t1, T t2) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterIDEA2327.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterIDEA2327.java index e3ddff59e351..0500941b771e 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterIDEA2327.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterIDEA2327.java @@ -1,19 +1,3 @@ -/* - * 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. - */ - // "Create Method 'test'" "true" public class Test { public Test() { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterMultipleTypes.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterMultipleTypes.java index d1c2fddbb8fd..adbac37a0b03 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterMultipleTypes.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterMultipleTypes.java @@ -1,19 +1,3 @@ -/* - * 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. - */ - // "Create Method 'bar'" "true" class A { public void foo() { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6758.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6758.java index ce16c9bdb494..785fac52e671 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6758.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6758.java @@ -1,19 +1,3 @@ -/* - * 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. - */ - // "Create Method 'someMethod'" "true" public class Test { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6826.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6826.java index dd66e450b591..603006986104 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6826.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterSCR6826.java @@ -1,19 +1,3 @@ -/* - * 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. - */ - // "Create Method 'f'" "true" class A { { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterThisCall.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterThisCall.java index dfc4902afd44..750224836f10 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterThisCall.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createMethodFromUsage/afterThisCall.java @@ -1,19 +1,3 @@ -/* - * 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. - */ - // "Create Method 'f'" "true" public class A { public A() { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after2.java index 9dacd82a6301..163161258c36 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after2.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after2.java @@ -1,19 +1,3 @@ -/* - * 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. - */ - // "Create Method 'get'" "true" class Generic { public T get() { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after3.java index b373fd4b3cdb..138b06a54542 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after3.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after3.java @@ -1,19 +1,3 @@ -/* - * 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. - */ - // "Create Method 'foo'" "true" interface Int { } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after4.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after4.java index ceb8f27192a9..dd4899a82635 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after4.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after4.java @@ -1,19 +1,3 @@ -/* - * 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. - */ - // "Create Method 'foo'" "true" interface Comparable { } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java index d1df472da142..1f42e7afa4ce 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java @@ -20,6 +20,7 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.PsiElement; import com.intellij.util.containers.hash.HashSet; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.HashMap; @@ -36,8 +37,13 @@ class AlignmentProvider { private final Map> myTree = new HashMap>(); private final Map, Alignment> myAlignments = new HashMap, Alignment>(); private final Map, Boolean> myAllowBackwardShift = new HashMap, Boolean>(); + private final Map, Alignment.Anchor> myAnchor = new HashMap, Alignment.Anchor>(); public void addPair(PsiElement e1, PsiElement e2, Boolean allowBackwardShift) { + addPair(e1, e2, allowBackwardShift, null); + } + + public void addPair(PsiElement e1, PsiElement e2, @Nullable Boolean allowBackwardShift, @Nullable Alignment.Anchor anchor) { LOG.assertTrue(e1 != e2); final Set set1 = myTree.get(e1); @@ -46,9 +52,14 @@ class AlignmentProvider { if (set1 != null && set2 != null) { LOG.assertTrue(!myAlignments.containsKey(set1) || !myAlignments.containsKey(set2)); LOG.assertTrue(myAllowBackwardShift.get(set1).booleanValue() == myAllowBackwardShift.get(set2).booleanValue()); + LOG.assertTrue(myAnchor.get(set1) == myAnchor.get(set2)); if (allowBackwardShift != null) { LOG.assertTrue(myAllowBackwardShift.get(set1).booleanValue() == allowBackwardShift.booleanValue()); } + if (anchor != null) { + LOG.assertTrue(myAnchor.get(set1) == anchor); + } + if (myAlignments.containsKey(set2)) { for (Iterator iterator = set1.iterator(); iterator.hasNext(); ) { PsiElement element = iterator.next(); @@ -71,12 +82,18 @@ class AlignmentProvider { if (allowBackwardShift != null) { LOG.assertTrue(myAllowBackwardShift.get(set1).booleanValue() == allowBackwardShift.booleanValue()); } + if (anchor != null) { + LOG.assertTrue(myAnchor.get(set1) == anchor); + } addInternal(set1, e2); } else if (set2 != null) { if (allowBackwardShift != null) { LOG.assertTrue(myAllowBackwardShift.get(set2).booleanValue() == allowBackwardShift.booleanValue()); } + if (anchor != null) { + LOG.assertTrue(myAnchor.get(set2) == anchor); + } addInternal(set2, e1); } else { @@ -84,7 +101,7 @@ class AlignmentProvider { addInternal(set, e1); addInternal(set, e2); myAllowBackwardShift.put(set, allowBackwardShift); - + myAnchor.put(set, anchor); } } @@ -109,12 +126,17 @@ class AlignmentProvider { } private void add(PsiElement element, boolean allowBackwardShift) { + add(element, allowBackwardShift, Alignment.Anchor.LEFT); + } + + private void add(PsiElement element, boolean allowBackwardShift, @NotNull Alignment.Anchor anchor) { if (myTree.get(element) != null) return; final HashSet set = createHashSet(); set.add(element); myTree.put(element, set); myAllowBackwardShift.put(set, allowBackwardShift); + myAnchor.put(set, anchor); } @Nullable @@ -127,19 +149,19 @@ class AlignmentProvider { Alignment alignment = myAlignments.get(set); if (alignment != null) return alignment; - alignment = Alignment.createAlignment(myAllowBackwardShift.get(set)); + alignment = Alignment.createAlignment(myAllowBackwardShift.get(set), myAnchor.get(set)); myAlignments.put(set, alignment); return alignment; } - public Aligner createAligner(PsiElement expression, boolean allowBackwardShift) { - Aligner aligner = new Aligner(allowBackwardShift); - aligner.append(expression); - return aligner; + public Aligner createAligner(boolean allowBackwardShift) { + return new Aligner(allowBackwardShift, Alignment.Anchor.LEFT); } - public Aligner createAligner(boolean allowBackwardShift) { - return new Aligner(allowBackwardShift); + public Aligner createAligner(PsiElement element, boolean allowBackwardShift, Alignment.Anchor anchor) { + final Aligner aligner = new Aligner(allowBackwardShift, anchor); + aligner.append(element); + return aligner; } /** @@ -151,9 +173,12 @@ class AlignmentProvider { class Aligner { private PsiElement myRef = null; private boolean allowBackwardShift = true; + @NotNull + private final Alignment.Anchor myAnchor; - Aligner(boolean allowBackwardShift) { + Aligner(boolean allowBackwardShift, @NotNull Alignment.Anchor anchor) { this.allowBackwardShift = allowBackwardShift; + myAnchor = anchor; } void append(@Nullable PsiElement element) { @@ -161,10 +186,10 @@ class AlignmentProvider { if (myRef == null) { myRef = element; - add(element, allowBackwardShift); + add(element, allowBackwardShift, myAnchor); } else { - addPair(myRef, element, allowBackwardShift); + addPair(myRef, element, allowBackwardShift, myAnchor); } } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlockGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlockGenerator.java index 80aabd5f05a9..1629934f5f81 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlockGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlockGenerator.java @@ -228,7 +228,7 @@ public class GroovyBlockGenerator implements GroovyElementTypes { else { currentGroup = new ArrayList(); for (LeafPsiElement expression : table) { - currentGroup.add(myAlignmentProvider.createAligner(expression, true)); + currentGroup.add(myAlignmentProvider.createAligner(expression, true, Alignment.Anchor.RIGHT)); } } } @@ -294,7 +294,7 @@ public class GroovyBlockGenerator implements GroovyElementTypes { } private static boolean isTablePart(PsiElement psi) { - return psi instanceof GrBinaryExpression && mBOR == ((GrBinaryExpression)psi).getOperationTokenType(); + return psi instanceof GrBinaryExpression && (mBOR == ((GrBinaryExpression)psi).getOperationTokenType() || mLOR == ((GrBinaryExpression)psi).getOperationTokenType()); } private static List visibleChildren(ASTNode node) { From 3980ba7a394e910f3be0157364e6714ff30de191 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Wed, 16 May 2012 12:46:42 +0400 Subject: [PATCH 61/61] IDEA-85974 Support double pipe (||) symbol in Spock data tables --- .../plugins/groovy/formatter/AlignmentProvider.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java index 1f42e7afa4ce..e484fcc94712 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java @@ -149,7 +149,12 @@ class AlignmentProvider { Alignment alignment = myAlignments.get(set); if (alignment != null) return alignment; - alignment = Alignment.createAlignment(myAllowBackwardShift.get(set), myAnchor.get(set)); + Alignment.Anchor anchor = myAnchor.get(set); + if (anchor == null) { + myAnchor.put(set, Alignment.Anchor.LEFT); + anchor = Alignment.Anchor.LEFT; + } + alignment = Alignment.createAlignment(myAllowBackwardShift.get(set), anchor); myAlignments.put(set, alignment); return alignment; }