diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseCompilerConfigurable.form b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseCompilerConfigurable.form index 8f01321975db..e1aa6ed463f5 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseCompilerConfigurable.form +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseCompilerConfigurable.form @@ -1,9 +1,9 @@
- + - + @@ -80,9 +80,17 @@ + + + + + + + +
diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/javac/JavacOptionsPanel.form b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/javac/JavacOptionsPanel.form index 1adbb30fd6c0..d6963cf3ed6d 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/javac/JavacOptionsPanel.form +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/javac/JavacOptionsPanel.form @@ -1,9 +1,9 @@
- + - + @@ -79,9 +79,17 @@ + + + + + + + +
diff --git a/java/compiler/impl/src/com/intellij/compiler/options/AnnotationProcessorsConfigurable.java b/java/compiler/impl/src/com/intellij/compiler/options/AnnotationProcessorsConfigurable.java index b81be012044c..defcbf8f8401 100644 --- a/java/compiler/impl/src/com/intellij/compiler/options/AnnotationProcessorsConfigurable.java +++ b/java/compiler/impl/src/com/intellij/compiler/options/AnnotationProcessorsConfigurable.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.compiler.options; import com.intellij.compiler.CompilerConfiguration; @@ -197,7 +212,7 @@ public class AnnotationProcessorsConfigurable implements SearchableConfigurable if (header != null) { header.repaint(); } - myModulesTable.setEnabled(enabled); + myModulesTable.getComponent().setEnabled(enabled); } public boolean isModified() { diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SourcePathsStep.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SourcePathsStep.java index 2bbfb08db1b0..bb1790313f2b 100644 --- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SourcePathsStep.java +++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SourcePathsStep.java @@ -254,7 +254,7 @@ public class SourcePathsStep extends AbstractStepWithProgress myPathEditors = new HashMap(); + private final Map myPathEditors = new HashMap(); private TextFieldWithBrowseButton myHomeComponent; private final Map myAdditionalDataConfigurables = new HashMap(); @@ -131,7 +131,7 @@ public class SdkEditor implements Configurable, Place.Navigator { myTabbedPane = new TabbedPaneWrapper(myDisposable); for (OrderRootType type : OrderRootType.getAllTypes()) { if (mySdk == null || showTabForType(type)) { - final PathEditor pathEditor = OrderRootTypeUIFactory.FACTORY.getByKey(type).createPathEditor(mySdk); + final SdkPathEditor pathEditor = OrderRootTypeUIFactory.FACTORY.getByKey(type).createPathEditor(mySdk); if (pathEditor != null) { myTabbedPane.addTab(pathEditor.getDisplayName(), pathEditor.createComponent()); myPathEditors.put(type, pathEditor); @@ -201,7 +201,7 @@ public class SdkEditor implements Configurable, Place.Navigator { myInitialPath = mySdk.getHomePath(); final SdkModificator sdkModificator = mySdk.getSdkModificator(); sdkModificator.setHomePath(getHomeValue().replace(File.separatorChar, '/')); - for (PathEditor pathEditor : myPathEditors.values()) { + for (SdkPathEditor pathEditor : myPathEditors.values()) { pathEditor.apply(sdkModificator); } ApplicationManager.getApplication().runWriteAction(new Runnable() { // fix SCR #29193 @@ -219,7 +219,7 @@ public class SdkEditor implements Configurable, Place.Navigator { public void reset(){ if (mySdk == null){ setHomePathValue(""); - for (PathEditor pathEditor : myPathEditors.values()) { + for (SdkPathEditor pathEditor : myPathEditors.values()) { pathEditor.reset(null); } } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/AnnotationsOrderRootTypeUIFactory.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/AnnotationsOrderRootTypeUIFactory.java index 6d6daa4b2f69..77948135226c 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/AnnotationsOrderRootTypeUIFactory.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/AnnotationsOrderRootTypeUIFactory.java @@ -23,7 +23,7 @@ package com.intellij.openapi.roots.ui.configuration.libraryEditor; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.projectRoots.ui.PathEditor; +import com.intellij.openapi.projectRoots.ui.SdkPathEditor; import com.intellij.openapi.roots.AnnotationOrderRootType; import com.intellij.openapi.roots.ui.OrderRootTypeUIFactory; import com.intellij.openapi.util.IconLoader; @@ -43,8 +43,8 @@ public class AnnotationsOrderRootTypeUIFactory implements OrderRootTypeUIFactory return ProjectBundle.message("sdk.configure.annotations.tab"); } - public PathEditor createPathEditor(Sdk sdk) { - return new PathEditor(ProjectBundle.message("sdk.configure.annotations.tab"), AnnotationOrderRootType.getInstance(), + public SdkPathEditor createPathEditor(Sdk sdk) { + return new SdkPathEditor(ProjectBundle.message("sdk.configure.annotations.tab"), AnnotationOrderRootType.getInstance(), FileChooserDescriptorFactory.createSingleFolderDescriptor()); } } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ClassesOrderRootTypeUIFactory.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ClassesOrderRootTypeUIFactory.java index 5670ef01b81f..8ec292373297 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ClassesOrderRootTypeUIFactory.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ClassesOrderRootTypeUIFactory.java @@ -23,7 +23,7 @@ package com.intellij.openapi.roots.ui.configuration.libraryEditor; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.projectRoots.ui.PathEditor; +import com.intellij.openapi.projectRoots.ui.SdkPathEditor; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.ui.OrderRootTypeUIFactory; import com.intellij.openapi.util.IconLoader; @@ -33,8 +33,8 @@ import javax.swing.*; public class ClassesOrderRootTypeUIFactory implements OrderRootTypeUIFactory { private static final Icon ICON = IconLoader.getIcon("/nodes/compiledClassesFolder.png"); - public PathEditor createPathEditor(Sdk sdk) { - return new PathEditor(ProjectBundle.message("sdk.configure.classpath.tab"), OrderRootType.CLASSES, new FileChooserDescriptor(true, true, true, false, true, true)); + public SdkPathEditor createPathEditor(Sdk sdk) { + return new SdkPathEditor(ProjectBundle.message("sdk.configure.classpath.tab"), OrderRootType.CLASSES, new FileChooserDescriptor(true, true, true, false, true, true)); } @Override diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/CreateNewLibraryAction.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/CreateNewLibraryAction.java index 81443e2e8329..198b7d0a2e62 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/CreateNewLibraryAction.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/CreateNewLibraryAction.java @@ -28,6 +28,7 @@ import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryType; import com.intellij.openapi.roots.libraries.ui.LibraryRootsComponentDescriptor; import com.intellij.openapi.roots.libraries.ui.OrderRoot; +import com.intellij.openapi.roots.libraries.ui.RootDetector; import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable; import com.intellij.openapi.roots.ui.configuration.libraries.LibraryEditingUtil; import com.intellij.openapi.roots.ui.configuration.projectRoot.BaseLibrariesConfigurable; @@ -72,17 +73,25 @@ public class CreateNewLibraryAction extends DumbAwareAction { if (componentDescriptor == null) { componentDescriptor = new DefaultLibraryRootsComponentDescriptor(); } - final FileChooserDescriptor chooserDescriptor = componentDescriptor.createAttachFilesChooserDescriptor(); - chooserDescriptor.setTitle("Select Library Files"); - final VirtualFile[] rootCandidates = FileChooser.chooseFiles(myLibrariesConfigurable.getTree(), chooserDescriptor, myProject.getBaseDir()); - if (rootCandidates.length == 0) { - return; - } + final List rootDetectors = componentDescriptor.getRootDetectors(); + final List roots; + if (!rootDetectors.isEmpty()) { + final FileChooserDescriptor chooserDescriptor = componentDescriptor.createAttachFilesChooserDescriptor(); + chooserDescriptor.setTitle("Select Library Files"); + final VirtualFile[] rootCandidates = FileChooser.chooseFiles(myLibrariesConfigurable.getTree(), chooserDescriptor, + myProject.getBaseDir()); + if (rootCandidates.length == 0) { + return; + } - final List roots = RootDetectionUtil - .detectRoots(Arrays.asList(rootCandidates), myLibrariesConfigurable.getTree(), myProject, componentDescriptor.getRootDetectors(), - true); - if (roots.isEmpty()) return; + roots = RootDetectionUtil + .detectRoots(Arrays.asList(rootCandidates), myLibrariesConfigurable.getTree(), myProject, rootDetectors, + true); + if (roots.isEmpty()) return; + } + else { + roots = Collections.emptyList(); + } final LibrariesModifiableModel modifiableModel = myLibrariesConfigurable.getModelProvider().getModifiableModel(); final Library library = modifiableModel.createLibrary(LibraryEditingUtil.suggestNewLibraryName(modifiableModel, roots), myType); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/JavadocOrderRootTypeUIFactory.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/JavadocOrderRootTypeUIFactory.java index 1ce1106df716..803ea45c1ae3 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/JavadocOrderRootTypeUIFactory.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/JavadocOrderRootTypeUIFactory.java @@ -20,13 +20,12 @@ */ package com.intellij.openapi.roots.ui.configuration.libraryEditor; -import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.projectRoots.JavaSdk; import com.intellij.openapi.projectRoots.JavaSdkVersion; import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.projectRoots.ui.PathEditor; +import com.intellij.openapi.projectRoots.ui.SdkPathEditor; import com.intellij.openapi.projectRoots.ui.Util; import com.intellij.openapi.roots.JavadocOrderRootType; import com.intellij.openapi.roots.ui.OrderRootTypeUIFactory; @@ -38,7 +37,7 @@ import javax.swing.*; public class JavadocOrderRootTypeUIFactory implements OrderRootTypeUIFactory { private static final Icon ICON = IconLoader.getIcon("/nodes/javaDocFolder.png"); - public PathEditor createPathEditor(Sdk sdk) { + public SdkPathEditor createPathEditor(Sdk sdk) { return new JavadocPathsEditor(sdk); } @@ -52,7 +51,7 @@ public class JavadocOrderRootTypeUIFactory implements OrderRootTypeUIFactory { return ProjectBundle.message("library.javadocs.node"); } - static class JavadocPathsEditor extends PathEditor { + static class JavadocPathsEditor extends SdkPathEditor { private final Sdk mySdk; public JavadocPathsEditor(Sdk sdk) { diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/RootDetectionUtil.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/RootDetectionUtil.java index 70a5440e8ab2..bcab5f29a5e7 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/RootDetectionUtil.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/RootDetectionUtil.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.roots.ui.configuration.libraryEditor; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; @@ -37,6 +38,8 @@ import java.util.List; * @author nik */ public class RootDetectionUtil { + private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.ui.configuration.libraryEditor.RootDetectionUtil"); + private RootDetectionUtil() { } @@ -45,6 +48,7 @@ public class RootDetectionUtil { @Nullable Project project, @NotNull final List detectors, boolean allowUserToSelectRootTypeIfNothingIsDetected) { + LOG.assertTrue(!detectors.isEmpty()); final List result = new ArrayList(); final List suggestedRoots = new ArrayList(); new Task.Modal(project, "Scanning for Roots", true) { @@ -69,14 +73,15 @@ public class RootDetectionUtil { if (!suggestedRoots.isEmpty()) { final DetectedRootsChooserDialog dialog = parentComponent != null - ? new DetectedRootsChooserDialog(parentComponent, suggestedRoots) - : new DetectedRootsChooserDialog(project, suggestedRoots); + ? new DetectedRootsChooserDialog(parentComponent, suggestedRoots) + : new DetectedRootsChooserDialog(project, suggestedRoots); dialog.show(); if (!dialog.isOK()) { return Collections.emptyList(); } for (SuggestedChildRootInfo rootInfo : dialog.getChosenRoots()) { - result.add(new OrderRoot(rootInfo.getSuggestedRoot(), rootInfo.getDetector().getRootType(), rootInfo.getDetector().isJarDirectory())); + result + .add(new OrderRoot(rootInfo.getSuggestedRoot(), rootInfo.getDetector().getRootType(), rootInfo.getDetector().isJarDirectory())); } } @@ -86,7 +91,7 @@ public class RootDetectionUtil { names.add(detector.getPresentableRootTypeName()); } final int i = Messages.showChooseDialog("Choose category for selected files:", "Attach Files", - ArrayUtil.toStringArray(names), names.get(0), null); + ArrayUtil.toStringArray(names), names.get(0), null); if (i != -1) { final RootDetector detector = detectors.get(i); for (VirtualFile candidate : rootCandidates) { diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/SourcesOrderRootTypeUIFactory.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/SourcesOrderRootTypeUIFactory.java index a0f58c5ac57e..4edc0f1a2ee8 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/SourcesOrderRootTypeUIFactory.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/SourcesOrderRootTypeUIFactory.java @@ -23,9 +23,9 @@ package com.intellij.openapi.roots.ui.configuration.libraryEditor; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.roots.ui.OrderRootTypeUIFactory; -import com.intellij.openapi.projectRoots.ui.PathEditor; +import com.intellij.openapi.projectRoots.ui.SdkPathEditor; import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.ui.OrderRootTypeUIFactory; import com.intellij.openapi.roots.ui.configuration.PathUIUtils; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.vfs.VirtualFile; @@ -36,8 +36,8 @@ import java.awt.*; public class SourcesOrderRootTypeUIFactory implements OrderRootTypeUIFactory { private static final Icon ICON = IconLoader.getIcon("/nodes/sourceFolder.png"); - public PathEditor createPathEditor(Sdk sdk) { - return new PathEditor(ProjectBundle.message("sdk.configure.sourcepath.tab"), OrderRootType.SOURCES, new FileChooserDescriptor(true, true, true, false, true, true)) { + public SdkPathEditor createPathEditor(Sdk sdk) { + return new SdkPathEditor(ProjectBundle.message("sdk.configure.sourcepath.tab"), OrderRootType.SOURCES, new FileChooserDescriptor(true, true, true, false, true, true)) { @Override protected VirtualFile[] adjustAddedFileSet(final Component component, final VirtualFile[] files) { return PathUIUtils.scanAndSelectDetectedJavaSourceRoots(component, files); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java index 44e8c539c5aa..362e722002bc 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java @@ -26,6 +26,7 @@ import com.intellij.patterns.ElementPattern; import com.intellij.patterns.PsiElementPattern; import com.intellij.patterns.PsiJavaElementPattern; import com.intellij.patterns.PsiJavaPatterns; +import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.filters.*; import com.intellij.psi.filters.classes.EnumOrAnnotationTypeFilter; @@ -38,6 +39,7 @@ import com.intellij.psi.impl.source.jsp.jspJava.JspClassLevelDeclarationStatemen import com.intellij.psi.jsp.JspElementType; import com.intellij.psi.templateLanguages.OuterLanguageElement; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; import com.intellij.util.Consumer; import com.intellij.util.ProcessingContext; import org.jetbrains.annotations.NonNls; @@ -441,9 +443,12 @@ public class JavaCompletionData extends JavaAwareCompletionData{ variant.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.TRY), TailType.createSimpleTailType('{'))); variant.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.THROW), TailType.SPACE)); variant.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.NEW), TailType.SPACE)); - variant.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.ASSERT), TailType.SPACE)); variant.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.SYNCHRONIZED), TailTypes.SYNCHRONIZED_LPARENTH)); + if (PsiUtil.getLanguageLevel(position).isAtLeast(LanguageLevel.JDK_1_4)) { + variant.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.ASSERT), TailType.SPACE)); + } + TailType returnTail = getReturnTail(position); LookupElement ret = createKeyword(position, PsiKeyword.RETURN); if (returnTail != TailType.NONE) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveClassToSeparateFileFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveClassToSeparateFileFix.java index eefa502100d4..f265112a60f4 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveClassToSeparateFileFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MoveClassToSeparateFileFix.java @@ -27,6 +27,7 @@ import com.intellij.psi.JavaDirectoryService; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; +import com.intellij.psi.impl.file.JavaDirectoryServiceImpl; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; @@ -55,13 +56,7 @@ public class MoveClassToSeparateFileFix implements IntentionAction { PsiDirectory dir = file.getContainingDirectory(); if (dir == null) return false; try { - String name = myClass.getName(); - if (myClass.isInterface()) { - JavaDirectoryService.getInstance().checkCreateInterface(dir, name); - } - else { - JavaDirectoryService.getInstance().checkCreateClass(dir, name); - } + JavaDirectoryServiceImpl.checkCreateClassOrInterface(dir, myClass.getName()); } catch (IncorrectOperationException e) { return false; diff --git a/java/java-impl/src/com/intellij/codeInsight/template/JavaCodeContextType.java b/java/java-impl/src/com/intellij/codeInsight/template/JavaCodeContextType.java index 916236a74e64..b8e75a2b021b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/JavaCodeContextType.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/JavaCodeContextType.java @@ -24,6 +24,7 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.SyntaxHighlighter; import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtilBase; import com.intellij.util.ProcessingContext; import org.jetbrains.annotations.NonNls; @@ -103,8 +104,8 @@ public abstract class JavaCodeContextType extends TemplateContextType { return false; } - PsiElement parent = element.getParent().getParent(); - return parent instanceof PsiExpressionStatement || parent instanceof PsiTypeElement && parent.getParent() instanceof PsiVariable; + PsiStatement statement = PsiTreeUtil.getParentOfType(element, PsiStatement.class); + return statement != null && statement.getTextRange().getStartOffset() == element.getTextRange().getStartOffset(); } } public static class Expression extends JavaCodeContextType { diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java index 5f7256e13009..3e0381d52e60 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java @@ -1434,7 +1434,7 @@ class ControlFlowAnalyzer extends JavaElementVisitor { if (dfaValue instanceof DfaVariableValue) { DfaVariableValue dfaVariable = (DfaVariableValue)dfaValue; PsiVariable psiVariable = dfaVariable.getPsiVariable(); - if (psiVariable instanceof PsiField && !psiVariable.hasModifierProperty(PsiModifier.FINAL)) { + if (psiVariable instanceof PsiField) { addField(dfaVariable); } } diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java index df3d7af8225b..c48867c0b0da 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java @@ -286,6 +286,7 @@ public class DataFlowInspection extends BaseLocalInspectionTool { PsiField field = (PsiField)resolved; if (!field.hasModifierProperty(PsiModifier.FINAL)) return false; + if (!field.hasModifierProperty(PsiModifier.STATIC)) return false; PsiElement parent = element.getParent(); if (parent instanceof PsiPrefixExpression && ((PsiPrefixExpression)parent).getOperationTokenType() == JavaTokenType.EXCL) { diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java index 3e27932031b3..9395f50f13c4 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java @@ -229,7 +229,9 @@ public class DataFlowRunner { @Override public DfaInstructionState[] visitMethodCall(MethodCallInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) { if (myNewExpression == instruction.getCallExpression()) { - myClosureStates.add(memState.createCopy()); + DfaMemoryState copy = memState.createCopy(); + copy.flushFields(runner); + myClosureStates.add(copy); } return super.visitMethodCall(instruction, runner, memState); } diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java index ec33cc801cc1..d6667d0fda54 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java @@ -28,6 +28,7 @@ import com.intellij.codeInspection.dataFlow.value.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; import com.intellij.psi.JavaTokenType; +import com.intellij.psi.PsiModifier; import com.intellij.psi.PsiType; import com.intellij.psi.PsiVariable; import com.intellij.psi.util.TypeConversionUtil; @@ -678,6 +679,10 @@ public class DfaMemoryStateImpl implements DfaMemoryState { } public void flushVariable(@NotNull DfaVariableValue variable) { + if (variable.getPsiVariable().hasModifierProperty(PsiModifier.FINAL)) { + return; + } + final int id = variable.getID(); int size = myEqClasses.size(); int interruptCount = 0; diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java index 6f06b9521fa9..6f1bacebce4b 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/value/DfaValueFactory.java @@ -78,7 +78,7 @@ public class DfaValueFactory { PsiExpression initializer = variable.getInitializer(); if (initializer instanceof PsiPolyadicExpression && variable.hasModifierProperty(PsiModifier.FINAL)) { PsiType type = initializer.getType(); - if (type != null && type.equalsToText("java.lang.String")) { + if (type != null && type.equalsToText(CommonClassNames.JAVA_LANG_STRING)) { return getNotNullFactory().create(type); } } diff --git a/java/java-impl/src/com/intellij/ide/fileTemplates/JavaCreateFromTemplateHandler.java b/java/java-impl/src/com/intellij/ide/fileTemplates/JavaCreateFromTemplateHandler.java index b6034b3bb5b4..56556548f0e4 100644 --- a/java/java-impl/src/com/intellij/ide/fileTemplates/JavaCreateFromTemplateHandler.java +++ b/java/java-impl/src/com/intellij/ide/fileTemplates/JavaCreateFromTemplateHandler.java @@ -22,6 +22,7 @@ import com.intellij.openapi.project.Project; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.impl.file.JavaDirectoryServiceImpl; import com.intellij.util.IncorrectOperationException; import java.util.Properties; @@ -50,13 +51,7 @@ public class JavaCreateFromTemplateHandler implements CreateFromTemplateHandler CodeStyleManager.getInstance(project).reformat(psiJavaFile); } String className = createdClass.getName(); - String fileName = className + "." + extension; - if(createdClass.isInterface()){ - JavaDirectoryService.getInstance().checkCreateInterface(directory, className); - } - else{ - JavaDirectoryService.getInstance().checkCreateClass(directory, className); - } + JavaDirectoryServiceImpl.checkCreateClassOrInterface(directory, className); final LanguageLevel ll = JavaDirectoryService.getInstance().getLanguageLevel(directory); if (ll.compareTo(LanguageLevel.JDK_1_5) < 0) { @@ -69,7 +64,7 @@ public class JavaCreateFromTemplateHandler implements CreateFromTemplateHandler } } - psiJavaFile = (PsiJavaFile)psiJavaFile.setName(fileName); + psiJavaFile = (PsiJavaFile)psiJavaFile.setName(className + "." + extension); PsiElement addedElement = directory.add(psiJavaFile); if (addedElement instanceof PsiJavaFile) { psiJavaFile = (PsiJavaFile)addedElement; diff --git a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java index 328ff6a4a9c2..1df1bf6eeb5b 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java @@ -74,10 +74,10 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext return generateClassInfo((PsiClass)element); } else if (element instanceof PsiMethod) { - return generateMethodInfo((PsiMethod)element); + return generateMethodInfo((PsiMethod)element, calcSubstitutor(originalElement)); } else if (element instanceof PsiField) { - return generateFieldInfo((PsiField)element); + return generateFieldInfo((PsiField)element, calcSubstitutor(originalElement)); } else if (element instanceof PsiVariable) { return generateVariableInfo((PsiVariable)element); @@ -86,11 +86,19 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext return generatePackageInfo((PsiPackage)element); } else if (element instanceof BeanPropertyElement) { - return generateMethodInfo(((BeanPropertyElement) element).getMethod()); + return generateMethodInfo(((BeanPropertyElement) element).getMethod(), PsiSubstitutor.EMPTY); } return null; } + private static PsiSubstitutor calcSubstitutor(PsiElement originalElement) { + PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; + if (originalElement instanceof PsiReferenceExpression) { + substitutor = ((PsiReferenceExpression)originalElement).advancedResolve(true).getSubstitutor(); + } + return substitutor; + } + public List getUrlFor(final PsiElement element, final PsiElement originalElement) { return getExternalJavaDocUrl(element); } @@ -245,7 +253,7 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext } @SuppressWarnings({"HardCodedStringLiteral"}) - public static String generateMethodInfo(PsiMethod method) { + public static String generateMethodInfo(PsiMethod method, PsiSubstitutor substitutor) { StringBuilder buffer = new StringBuilder(); PsiClass parentClass = method.getContainingClass(); @@ -288,7 +296,7 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext } if (method.getReturnType() != null) { - JavaDocInfoGenerator.generateType(buffer, method.getReturnType(), method, false); + JavaDocInfoGenerator.generateType(buffer, substitutor.substitute(method.getReturnType()), method, false); buffer.append(" "); } @@ -298,7 +306,7 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext PsiParameter[] parms = method.getParameterList().getParameters(); for (int i = 0; i < parms.length; i++) { PsiParameter parm = parms[i]; - JavaDocInfoGenerator.generateType(buffer, parm.getType(), method, false); + JavaDocInfoGenerator.generateType(buffer, substitutor.substitute(parm.getType()), method, false); buffer.append(" "); if (parm.getName() != null) { buffer.append(parm.getName()); @@ -333,7 +341,7 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext return buffer.toString(); } - private static String generateFieldInfo(PsiField field) { + private static String generateFieldInfo(PsiField field, PsiSubstitutor substitutor) { StringBuilder buffer = new StringBuilder(); PsiClass parentClass = field.getContainingClass(); @@ -344,7 +352,7 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext generateModifiers(buffer, field); - JavaDocInfoGenerator.generateType(buffer, field.getType(), field, false); + JavaDocInfoGenerator.generateType(buffer, substitutor.substitute(field.getType()), field, false); buffer.append(" "); buffer.append(field.getName()); diff --git a/java/java-impl/src/com/intellij/psi/impl/file/JavaDirectoryServiceImpl.java b/java/java-impl/src/com/intellij/psi/impl/file/JavaDirectoryServiceImpl.java index 8b90ac321c85..06157ae16c76 100644 --- a/java/java-impl/src/com/intellij/psi/impl/file/JavaDirectoryServiceImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/file/JavaDirectoryServiceImpl.java @@ -170,13 +170,6 @@ public class JavaDirectoryServiceImpl extends JavaDirectoryService { checkCreateClassOrInterface(dir, name); } - public void checkCreateInterface(@NotNull PsiDirectory dir, @NotNull String name) throws IncorrectOperationException { - checkCreateClassOrInterface(dir, name); - } - - /** - * @not_implemented - */ public static void checkCreateClassOrInterface(@NotNull PsiDirectory directory, String name) throws IncorrectOperationException { PsiUtil.checkIsIdentifier(directory.getManager(), name); diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java index d6bcabd0b824..f4ef291bd8ae 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java @@ -63,6 +63,7 @@ import javax.swing.table.TableColumn; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -243,13 +244,19 @@ public class JavaChangeSignatureDialog extends ChangeSignatureDialogBase item) { return new JBTableRowEditor() { private EditorTextField myTypeEditor; private EditorTextField myNameEditor; - private EditorTextField myDefaultValueEditor; + private EditorTextField myDefaultValueEditor; private JCheckBox myAnyVar; @Override @@ -321,7 +328,11 @@ public class JavaChangeSignatureDialog extends ChangeSignatureDialogBase myLibraryButtons = new ArrayList(); private ComboBox myLanguageCombo; - private JTextField myTargetClassNameField; + private EditorTextField myTargetClassNameField; private ReferenceEditorWithBrowseButton mySuperClassField; private ReferenceEditorComboWithBrowseButton myTargetPackageField; private JCheckBox myGenerateBeforeBox; @@ -181,10 +183,10 @@ public class CreateTestDialog extends DialogWrapper { } } - myTargetClassNameField = new JTextField(targetClass.getName() + "Test"); - setPreferredSize(myTargetClassNameField); + myTargetClassNameField = new EditorTextField(targetClass.getName() + "Test"); myTargetClassNameField.getDocument().addDocumentListener(new DocumentAdapter() { - protected void textChanged(DocumentEvent e) { + @Override + public void documentChanged(com.intellij.openapi.editor.event.DocumentEvent e) { getOKAction().setEnabled(JavaPsiFacade.getInstance(myProject).getNameHelper().isIdentifier(getClassName())); } }); @@ -227,13 +229,6 @@ public class CreateTestDialog extends DialogWrapper { mySelectedFramework = descriptor; } - private void setPreferredSize(JTextField field) { - Dimension size = field.getPreferredSize(); - FontMetrics fontMetrics = field.getFontMetrics(field.getFont()); - size.width = fontMetrics.charWidth('a') * 40; - field.setPreferredSize(size); - } - private void updateMethodsTable() { List methods = TestIntegrationUtils.extractClassMethods( myTargetClass, myShowInheritedMethodsBox.isSelected()); diff --git a/java/java-psi-api/src/com/intellij/psi/JavaDirectoryService.java b/java/java-psi-api/src/com/intellij/psi/JavaDirectoryService.java index e36baea4222a..098d60d49896 100644 --- a/java/java-psi-api/src/com/intellij/psi/JavaDirectoryService.java +++ b/java/java-psi-api/src/com/intellij/psi/JavaDirectoryService.java @@ -95,16 +95,6 @@ public abstract class JavaDirectoryService { @NotNull public abstract PsiClass createInterface(@NotNull PsiDirectory dir, @NotNull String name) throws IncorrectOperationException; - /** - * Checks if it's possible to create an interface with the specified name in the directory, - * and throws an exception if the creation is not possible. Does not actually modify - * anything. - * - * @param name the name of the interface to check creation possibility (not including the file extension). - * @throws IncorrectOperationException if the creation is not possible. - */ - public abstract void checkCreateInterface(@NotNull PsiDirectory dir, @NotNull String name) throws IncorrectOperationException; - /** * Creates an enumeration class with the specified name in the directory. * diff --git a/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java b/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java index 2dfb175207b6..39c052bd18ac 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java @@ -51,7 +51,7 @@ public class MethodSignatureUtil { result += 37 * parameterTypes.length; PsiType firstParamType = parameterTypes.length == 0 ? null : parameterTypes[0]; if (firstParamType != null) { - firstParamType = TypeConversionUtil.erasure(firstParamType); + firstParamType = TypeConversionUtil.erasure(firstParamType, signature.getSubstitutor()); result = 31*result + firstParamType.hashCode(); } return result; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java index a71a149a14aa..a11cc46a533b 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java @@ -298,7 +298,9 @@ public class PsiSubstitutorImpl implements PsiSubstitutor { PsiType substitutedBoundType = boundType.accept(mySimpleSubstitutionVisitor); PsiWildcardType wildcardType = (PsiWildcardType)substituted; if (substitutedBoundType != null && !(substitutedBoundType instanceof PsiWildcardType) && !substitutedBoundType.equalsToText("java.lang.Object")) { - if (originalBound == null || !TypeConversionUtil.erasure(substitutedBoundType).isAssignableFrom(TypeConversionUtil.erasure(originalBound))) { //erasure is essential to avoid infinite recursion + if (originalBound == null || + (!TypeConversionUtil.erasure(substitutedBoundType).isAssignableFrom(TypeConversionUtil.erasure(originalBound)) && + !TypeConversionUtil.erasure(substitutedBoundType).isAssignableFrom(originalBound))) { //erasure is essential to avoid infinite recursion if (wildcardType.isExtends()) { final PsiType glb = GenericsUtil.getGreatestLowerBound(wildcardType.getBound(), substitutedBoundType); if (glb != null) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/MethodSignatureEquality.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/MethodSignatureEquality.java index 2473989a5dc7..54d29e778927 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/MethodSignatureEquality.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/MethodSignatureEquality.java @@ -87,7 +87,7 @@ abstract class RunConfigurationExtension { class F extends RunConfigurationExtension { - @Override + @Override protected

SettingsEditor

createEditor(P configuration) { return null; } diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/FieldInAnonymous.java b/java/java-tests/testData/inspection/dataFlow/fixture/FieldInAnonymous.java new file mode 100644 index 000000000000..92d4a5deb496 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/FieldInAnonymous.java @@ -0,0 +1,36 @@ +class Zoo2 { + private boolean condition; + private final boolean condition2; + + Zoo2(boolean condition2) { + this.condition2 = condition2; + } + + Runnable foo() { + if (!condition) { + return new Runnable() { + + public void run() { + if (condition) { + System.out.println("aaa"); + } + } + }; + } + if (!condition2) { + return new Runnable() { + + public void run() { + if (condition2) { + System.out.println("aaa"); + } + } + }; + } + return null; + } + + public void setCondition(boolean condition) { + this.condition = condition; + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/JavaDocumentationTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/JavaDocumentationTest.groovy new file mode 100644 index 000000000000..18a0a5f70b3d --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/JavaDocumentationTest.groovy @@ -0,0 +1,52 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight + +import com.intellij.codeInsight.navigation.CtrlMouseHandler +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase + +/** + * @author peter + */ +class JavaDocumentationTest extends LightCodeInsightFixtureTestCase { + + public void testGenericMethod() { + myFixture.configureByText 'a.java', ''' +class Bar { java.util.List foo(T param); } + +class Foo {{ + new Bar().foo(); +}} +''' + def ref = myFixture.file.findReferenceAt(myFixture.editor.caretModel.offset) + assert CtrlMouseHandler.getInfo(ref.resolve(), ref.element) == """Bar + java.util.List<java.lang.String> foo (java.lang.String param)""" + } + + public void testGenericField() { + myFixture.configureByText 'a.java', ''' +class Bar { T field; } + +class Foo {{ + new Bar().field +}} +''' + def ref = myFixture.file.findReferenceAt(myFixture.editor.caretModel.offset) + assert CtrlMouseHandler.getInfo(ref.resolve(), ref.element) == """Bar + java.lang.Integer field""" + } + +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index 0152cba901a3..b76c67c7e4b6 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -1115,4 +1115,36 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase { myFixture.type '*\n' myFixture.checkResult "import java.lang.*" } + + public void testIntersectionTypesSOE() { + myFixture.configureByText("a.java", """ + import java.util.*; + import java.io.*; + class SOE { + public boolean setLocation(Iterable path) { + return true; + } + + public void compile(List classpath) { + setLocation(); + } + } + """) + myFixture.completeBasic() + myFixture.type '*\n' + myFixture.checkResult """ + import java.util.*; + import java.io.*; + class SOE { + public boolean setLocation(Iterable path) { + return true; + } + + public void compile(List classpath) { + setLocation(classpath); + } + } + """ + } + } diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java index 4c356e81fe65..af8d11f9b962 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java @@ -32,4 +32,6 @@ public class DataFlowInspectionFixtureTest extends JavaCodeInsightFixtureTestCas public void testNullableAnonymousVolatile() throws Throwable { doTest(); } public void testNullableAnonymousVolatileNotNull() throws Throwable { doTest(); } + public void testFieldInAnonymous() throws Throwable { doTest(); } + } diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java index 866e5eedaf28..db9ce9b6a192 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java @@ -881,16 +881,6 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest { "}"); } - public void testSpacesInsideEmptyParentheses() throws Exception { - final CommonCodeStyleSettings settings = getSettings(); - settings.SPACE_WITHIN_METHOD_PARENTHESES = true; - settings.SPACE_WITHIN_METHOD_CALL_PARENTHESES = true; - - doTextTest("public class Foo {\n" + " public void foo( ) {\n" + " foo( );\n" + " }\n" + "}", - "public class Foo {\n" + " public void foo() {\n" + " foo();\n" + " }\n" + "}"); - - } - public void testElseOnNewLine() throws Exception { doTextTest("class Foo{\n" + "void foo() {\n" + "if (a)\n" + "return;\n" + "else\n" + "return;\n" + "}\n" + "}", "class Foo {\n" + " void foo() {\n" + diff --git a/platform/core-impl/src/com/intellij/openapi/vfs/ex/VirtualFileManagerEx.java b/platform/core-impl/src/com/intellij/openapi/vfs/ex/VirtualFileManagerEx.java index 174f859f487f..c373cd784842 100644 --- a/platform/core-impl/src/com/intellij/openapi/vfs/ex/VirtualFileManagerEx.java +++ b/platform/core-impl/src/com/intellij/openapi/vfs/ex/VirtualFileManagerEx.java @@ -1,24 +1,24 @@ - /* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +* Copyright 2000-2009 JetBrains s.r.o. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ package com.intellij.openapi.vfs.ex; import com.intellij.openapi.vfs.VirtualFileManager; public abstract class VirtualFileManagerEx extends VirtualFileManager { public abstract void fireBeforeRefreshStart(boolean asynchronous); + public abstract void fireAfterRefreshFinish(boolean asynchronous); } diff --git a/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFileManagerImpl.java b/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFileManagerImpl.java index 4b35483ed32e..d3bcf602bfae 100644 --- a/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFileManagerImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFileManagerImpl.java @@ -24,7 +24,9 @@ import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.KeyedExtensionCollector; import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.ex.VirtualFileManagerEx; -import com.intellij.openapi.vfs.newvfs.*; +import com.intellij.openapi.vfs.newvfs.BulkFileListener; +import com.intellij.openapi.vfs.newvfs.CachingVirtualFileSystem; +import com.intellij.openapi.vfs.newvfs.FileSystemPersistence; import com.intellij.openapi.vfs.newvfs.events.VFilePropertyChangeEvent; import com.intellij.util.EventDispatcher; import com.intellij.util.containers.ContainerUtil; @@ -193,10 +195,10 @@ public class VirtualFileManagerImpl extends VirtualFileManagerEx { @Override public void notifyPropertyChanged(final VirtualFile virtualFile, final String property, final Object oldValue, final Object newValue) { final Application application = ApplicationManager.getApplication(); - application.invokeLater(new Runnable() { + final Runnable runnable = new Runnable() { public void run() { if (virtualFile.isValid() && !application.isDisposed()) { - application.runWriteAction(new Runnable(){ + application.runWriteAction(new Runnable() { public void run() { List events = Collections .singletonList(new VFilePropertyChangeEvent(this, virtualFile, property, oldValue, newValue, false)); @@ -207,7 +209,8 @@ public class VirtualFileManagerImpl extends VirtualFileManagerEx { }); } } - }, ModalityState.NON_MODAL); + }; + application.invokeLater(runnable, ModalityState.NON_MODAL); } public void fireBeforeRefreshStart(boolean asynchronous) { diff --git a/platform/icons/src/ide/shadow/bottom-left.png b/platform/icons/src/ide/shadow/bottom-left.png index 3b5d8b05581a..2777f1547e02 100644 Binary files a/platform/icons/src/ide/shadow/bottom-left.png and b/platform/icons/src/ide/shadow/bottom-left.png differ diff --git a/platform/icons/src/ide/shadow/bottom-right.png b/platform/icons/src/ide/shadow/bottom-right.png index d19173d1fc3b..1e84e87938d5 100644 Binary files a/platform/icons/src/ide/shadow/bottom-right.png and b/platform/icons/src/ide/shadow/bottom-right.png differ diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/PathEditor.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/PathEditor.java index 3dbd72a2b024..8d8e1174b486 100644 --- a/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/PathEditor.java +++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/PathEditor.java @@ -15,7 +15,6 @@ */ package com.intellij.openapi.projectRoots.ui; -import com.google.common.collect.Lists; import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.CommonShortcuts; import com.intellij.openapi.actionSystem.PlatformDataKeys; @@ -28,8 +27,6 @@ import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectBundle; -import com.intellij.openapi.projectRoots.SdkModificator; -import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.vfs.JarFileSystem; @@ -45,7 +42,6 @@ import com.intellij.util.containers.HashSet; import com.intellij.util.ui.UIUtil; import gnu.trove.TIntArrayList; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.ListSelectionEvent; @@ -77,21 +73,14 @@ public class PathEditor { private boolean myEnabled = false; private static final Icon ICON_INVALID = IconLoader.getIcon("/nodes/ppInvalid.png"); private static final Icon ICON_EMPTY = IconLoader.getIcon("/nodes/emptyNode.png"); - private final String myDisplayName; - private final OrderRootType myOrderRootType; private final FileChooserDescriptor myDescriptor; - public PathEditor(final String displayName, - final OrderRootType orderRootType, - final FileChooserDescriptor descriptor) { - myDisplayName = displayName; - myOrderRootType = orderRootType; + public PathEditor(final FileChooserDescriptor descriptor) { myDescriptor = descriptor; myDescriptor.putUserData(FileChooserDialog.PREFER_LAST_OVER_TO_SELECT, Boolean.TRUE); myModel = createListModel(); } - protected void setEnabled(boolean enabled) { myEnabled = enabled; } @@ -103,10 +92,6 @@ public class PathEditor { protected void onSpecifyUrlButtonClicked() { } - public String getDisplayName() { - return myDisplayName; - } - protected void setModified(boolean modified) { myModified = modified; } @@ -115,20 +100,6 @@ public class PathEditor { return myModified; } - public OrderRootType getOrderRootType() { - return myOrderRootType; - } - - public void apply(SdkModificator sdkModificator) { - sdkModificator.removeRoots(myOrderRootType); - // add all items - for (int i = 0; i < getRowCount(); i++) { - sdkModificator.addRoot(getValueAt(i), myOrderRootType); - } - setModified(false); - updateButtons(); - } - public VirtualFile[] getRoots() { final int count = getRowCount(); if (count == 0) { @@ -152,15 +123,6 @@ public class PathEditor { updateButtons(); } - public void reset(@Nullable SdkModificator modificator) { - if (modificator != null) { - resetPath(Lists.newArrayList(modificator.getRoots(myOrderRootType))); - } - else { - setEnabled(false); - } - } - public JComponent createComponent() { myPanel = new JPanel(new GridBagLayout()); @@ -282,7 +244,7 @@ public class PathEditor { return files; } - protected void updateButtons() { + public void updateButtons() { Object[] values = getSelectedRoots(); myRemoveButton.setEnabled((values.length > 0) && myEnabled); myAddButton.setEnabled(myEnabled); @@ -389,11 +351,11 @@ public class PathEditor { return myList.getSelectedValues(); } - private int getRowCount() { + protected int getRowCount() { return getListModel().getSize(); } - private VirtualFile getValueAt(int row) { + protected VirtualFile getValueAt(int row) { return (VirtualFile)getListModel().get(row); } diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/SdkPathEditor.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/SdkPathEditor.java new file mode 100644 index 000000000000..09621f3c8fc5 --- /dev/null +++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/ui/SdkPathEditor.java @@ -0,0 +1,61 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.projectRoots.ui; + +import com.google.common.collect.Lists; +import com.intellij.openapi.fileChooser.FileChooserDescriptor; +import com.intellij.openapi.projectRoots.SdkModificator; +import com.intellij.openapi.roots.OrderRootType; +import org.jetbrains.annotations.Nullable; + +public class SdkPathEditor extends PathEditor { + private final String myDisplayName; + private final OrderRootType myOrderRootType; + + public SdkPathEditor(String displayName, OrderRootType orderRootType, FileChooserDescriptor descriptor) { + super(descriptor); + myDisplayName = displayName; + myOrderRootType = orderRootType; + } + + public String getDisplayName() { + return myDisplayName; + } + + public OrderRootType getOrderRootType() { + return myOrderRootType; + } + + public void apply(SdkModificator sdkModificator) { + sdkModificator.removeRoots(myOrderRootType); + // add all items + for (int i = 0; i < getRowCount(); i++) { + sdkModificator.addRoot(getValueAt(i), myOrderRootType); + } + setModified(false); + updateButtons(); + } + + public void reset(@Nullable SdkModificator modificator) { + if (modificator != null) { + resetPath(Lists.newArrayList(modificator.getRoots(myOrderRootType))); + } + else { + setEnabled(false); + } + } + +} diff --git a/platform/lang-api/src/com/intellij/openapi/roots/ui/OrderRootTypeUIFactory.java b/platform/lang-api/src/com/intellij/openapi/roots/ui/OrderRootTypeUIFactory.java index 11e8c96a4275..b86a37a89a37 100644 --- a/platform/lang-api/src/com/intellij/openapi/roots/ui/OrderRootTypeUIFactory.java +++ b/platform/lang-api/src/com/intellij/openapi/roots/ui/OrderRootTypeUIFactory.java @@ -22,6 +22,7 @@ package com.intellij.openapi.roots.ui; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.ui.PathEditor; +import com.intellij.openapi.projectRoots.ui.SdkPathEditor; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.util.KeyedExtensionFactory; @@ -34,7 +35,7 @@ public interface OrderRootTypeUIFactory { } }; - PathEditor createPathEditor(Sdk sdk); + SdkPathEditor createPathEditor(Sdk sdk); Icon getIcon(); diff --git a/platform/lang-api/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/DocumentationOrderRootTypeUIFactory.java b/platform/lang-api/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/DocumentationOrderRootTypeUIFactory.java index 8fb371be99b9..1c0ec6cf198d 100644 --- a/platform/lang-api/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/DocumentationOrderRootTypeUIFactory.java +++ b/platform/lang-api/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/DocumentationOrderRootTypeUIFactory.java @@ -17,7 +17,7 @@ package com.intellij.openapi.roots.ui.configuration.libraryEditor; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.projectRoots.ui.PathEditor; +import com.intellij.openapi.projectRoots.ui.SdkPathEditor; import com.intellij.openapi.roots.ui.OrderRootTypeUIFactory; import com.intellij.openapi.util.IconLoader; import org.jetbrains.annotations.Nullable; @@ -33,7 +33,7 @@ public class DocumentationOrderRootTypeUIFactory implements OrderRootTypeUIFacto @Override @Nullable - public PathEditor createPathEditor(Sdk sdk) { + public SdkPathEditor createPathEditor(Sdk sdk) { return null; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java index 663f64451494..1f1ef286c6d5 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java @@ -62,8 +62,10 @@ import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NotNull; import java.awt.*; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Set; public class BraceHighlightingHandler { private static final Key> BRACE_HIGHLIGHTERS_IN_EDITOR_VIEW_KEY = Key.create("BraceHighlighter.BRACE_HIGHLIGHTERS_IN_EDITOR_VIEW_KEY"); @@ -356,25 +358,25 @@ public class BraceHighlightingHandler { } private void highlightRightBrace(HighlighterIterator iterator, FileType fileType) { - int brace1End = iterator.getEnd(); + TextRange brace1 = TextRange.create(iterator.getStart(), iterator.getEnd()); boolean matched = BraceMatchingUtil.matchBrace(myDocument.getCharsSequence(), fileType, iterator, false); - int brace2Start = iterator.atEnd() ? -1 : iterator.getStart(); + TextRange brace2 = iterator.atEnd() ? null : TextRange.create(iterator.getStart(), iterator.getEnd()); - highlightBraces(brace2Start, brace1End - 1, matched, false, fileType); + highlightBraces(brace2, brace1, matched, false, fileType); } private void highlightLeftBrace(HighlighterIterator iterator, boolean scopeHighlighting, FileType fileType) { - int brace1Start = iterator.getStart(); + TextRange brace1Start = TextRange.create(iterator.getStart(), iterator.getEnd()); boolean matched = BraceMatchingUtil.matchBrace(myDocument.getCharsSequence(), fileType, iterator, true); - int brace2End = iterator.atEnd() ? -1 : iterator.getEnd() - 1; + TextRange brace2End = iterator.atEnd() ? null : TextRange.create(iterator.getStart(), iterator.getEnd()); highlightBraces(brace1Start, brace2End, matched, scopeHighlighting, fileType); } - private void highlightBraces(final int lBraceOffset, int rBraceOffset, boolean matched, boolean scopeHighlighting, FileType fileType) { + private void highlightBraces(final TextRange lBrace, TextRange rBrace, boolean matched, boolean scopeHighlighting, FileType fileType) { if (!matched && fileType == FileTypes.PLAIN_TEXT) { return; } @@ -384,21 +386,21 @@ public class BraceHighlightingHandler { matched ? scheme.getAttributes(CodeInsightColors.MATCHED_BRACE_ATTRIBUTES) : scheme.getAttributes(CodeInsightColors.UNMATCHED_BRACE_ATTRIBUTES); - if (rBraceOffset >= 0 && !scopeHighlighting) { - highlightBrace(rBraceOffset, matched); + if (rBrace != null && !scopeHighlighting) { + highlightBrace(rBrace, matched); } - if (lBraceOffset >= 0 && !scopeHighlighting) { - highlightBrace(lBraceOffset, matched); + if (lBrace != null && !scopeHighlighting) { + highlightBrace(lBrace, matched); } if (!myEditor.equals(FileEditorManager.getInstance(myProject).getSelectedTextEditor())) { return; } - if (lBraceOffset >= 0 && rBraceOffset >= 0) { - final int startLine = myEditor.offsetToLogicalPosition(lBraceOffset).line; - final int endLine = myEditor.offsetToLogicalPosition(rBraceOffset).line; + if (lBrace != null && rBrace !=null) { + final int startLine = myEditor.offsetToLogicalPosition(lBrace.getStartOffset()).line; + final int endLine = myEditor.offsetToLogicalPosition(rBrace.getEndOffset()).line; if (endLine - startLine > 0) { final Runnable runnable = new Runnable() { public void run() { @@ -424,7 +426,7 @@ public class BraceHighlightingHandler { } if (!scopeHighlighting) { - showScopeHint(lBraceOffset, lBraceOffset + 1); + showScopeHint(lBrace.getStartOffset(), lBrace.getEndOffset()); } } else { @@ -434,7 +436,7 @@ public class BraceHighlightingHandler { } } - private void highlightBrace(int rBraceOffset, boolean matched) { + private void highlightBrace(TextRange braceRange, boolean matched) { EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme(); final TextAttributes attributes = matched ? scheme.getAttributes(CodeInsightColors.MATCHED_BRACE_ATTRIBUTES) @@ -443,7 +445,7 @@ public class BraceHighlightingHandler { RangeHighlighter rbraceHighlighter = myEditor.getMarkupModel().addRangeHighlighter( - rBraceOffset, rBraceOffset + 1, HighlighterLayer.LAST + 1, attributes, HighlighterTargetArea.EXACT_RANGE); + braceRange.getStartOffset(), braceRange.getEndOffset(), HighlighterLayer.LAST + 1, attributes, HighlighterTargetArea.EXACT_RANGE); rbraceHighlighter.setGreedyToLeft(false); rbraceHighlighter.setGreedyToRight(false); registerHighlighter(rbraceHighlighter); diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarItem.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarItem.java index 76ac0b6d0cdd..4aee0656f421 100644 --- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarItem.java +++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarItem.java @@ -25,6 +25,7 @@ import com.intellij.util.ui.UIUtil; import javax.swing.*; import java.awt.*; +import java.awt.geom.Path2D; /** * @author Konstantin Bulenkov @@ -65,8 +66,12 @@ class NavBarItem extends SimpleColoredComponent implements Disposable { setOpaque(false); setFont(UIUtil.isUnderAquaLookAndFeel() ? UIUtil.getLabelFont().deriveFont(11.0f) : getFont()); - - setIpad(new Insets(1, 2, 1, 2)); + if (isPopupElement || !NavBarPanel.isDecorated()) { + setIpad(new Insets(1, 2, 1, 2)); + } else { + setMyBorder(null); + setBorder(null); + } update(); } @@ -100,7 +105,9 @@ class NavBarItem extends SimpleColoredComponent implements Disposable { final NavBarModel model = myPanel.getModel(); final boolean selected = isSelected(); - setPaintFocusBorder(selected && !isPopupElement && myPanel.isNodePopupActive()); + if (!NavBarPanel.isDecorated()) { + setPaintFocusBorder(selected && !isPopupElement && myPanel.isNodePopupActive()); + } setFocusBorderAroundIcon(false); setBackground(selected && focused @@ -119,6 +126,76 @@ class NavBarItem extends SimpleColoredComponent implements Disposable { repaint(); } + @Override + protected void doPaint(Graphics2D g) { + if (isPopupElement || !NavBarPanel.isDecorated()) { + super.doPaint(g); + } else { + doPaintDecorated(g); + } + } + + private void doPaintDecorated(Graphics2D g) { + setPaintFocusBorder(false); + setIpad(new Insets(0, 0, 0, 0)); + Icon icon = myIcon; + final Color bg = getBackground(); + g.setPaint(bg); + int w = getWidth(); + int h = getHeight(); + g.fillRect(0, 0, w, h); + icon.paintIcon(this, g, 3, (h - icon.getIconHeight()) / 2); + int x = doPaintText(g, icon.getIconWidth() + 6, false); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + Path2D.Double p = new Path2D.Double(); + g.translate(x, 0); + p.moveTo(0, 0); // + p.lineTo(10 , h / 2); // |\ + p.lineTo(0, h); // |/ + p.lineTo(0, 0); + g.setPaint(getBackground()); + g.fill(p); + + if (isLastElement()) { + Path2D.Double path = new Path2D.Double(); + path.moveTo(0, 0); + path.lineTo(10, h / 2); // ___ + path.lineTo(0, h); // \ | + path.lineTo(12, h); // /_| + path.lineTo(12, 0); + path.lineTo(0, 0); + g.setPaint(isNextSelected() ? UIUtil.getListSelectionBackground() : UIUtil.getListBackground()); + g.fill(path); + + path = new Path2D.Double(); + path.moveTo(0, 0); // + path.lineTo(10, h / 2); // \ + path.lineTo(0, h); // / + g.setPaint(Color.GRAY); + g.draw(path); + } + } + + private boolean isLastElement() { + return myIndex != myPanel.getModel().size() - 1; + } + + @Override + public Dimension getPreferredSize() { + final Dimension size = super.getPreferredSize(); + if (! isPopupElement && NavBarPanel.isDecorated()) { + size.width += 10 + 2*3; + size.height += 6; + } + return size; + } + + @Override + public Dimension getMinimumSize() { + return getPreferredSize(); + } + private boolean isFocused() { final Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); return isPopupElement || (focusOwner == myPanel && !myPanel.isNodePopupShowing()); @@ -168,4 +245,9 @@ class NavBarItem extends SimpleColoredComponent implements Disposable { @Override public void dispose() { } + + + private boolean isNextSelected() { + return myIndex == myPanel.getModel().getSelectedIndex() - 1; + } } diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPanel.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPanel.java index 6f3df03acc7c..324c53bfa8bb 100644 --- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPanel.java +++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPanel.java @@ -42,6 +42,7 @@ import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.AsyncResult; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -99,7 +100,7 @@ public class NavBarPanel extends JPanel implements DataProvider, PopupOwner, Dis private RelativePoint myLocationCache; public NavBarPanel(final Project project) { - super(new FlowLayout(FlowLayout.LEFT, 5, 0)); + super(new FlowLayout(FlowLayout.LEFT, isDecorated() ? 0 : 5, 0)); myProject = project; myModel = new NavBarModel(myProject); myIdeView = new NavBarIdeView(this); @@ -108,7 +109,9 @@ public class NavBarPanel extends JPanel implements DataProvider, PopupOwner, Dis PopupHandler.installPopupHandler(this, IdeActions.GROUP_NAVBAR_POPUP, ActionPlaces.NAVIGATION_BAR); - setBorder(new NavBarBorder(false, -1)); + if (!isDecorated()) { + setBorder(new NavBarBorder(false, -1)); + } setOpaque(false); myCopyPasteDelegator = new CopyPasteDelegator(myProject, NavBarPanel.this) { @@ -124,7 +127,9 @@ public class NavBarPanel extends JPanel implements DataProvider, PopupOwner, Dis Disposer.register(project, this); } - + public static boolean isDecorated() { + return Registry.is("navbar.is.decorated"); + } public boolean isNodePopupActive() { return myNodePopup != null && myNodePopup.isVisible(); diff --git a/platform/platform-api/src/com/intellij/openapi/roots/ui/util/CompositeAppearance.java b/platform/platform-api/src/com/intellij/openapi/roots/ui/util/CompositeAppearance.java index ec927b3894f6..197618b84a1b 100644 --- a/platform/platform-api/src/com/intellij/openapi/roots/ui/util/CompositeAppearance.java +++ b/platform/platform-api/src/com/intellij/openapi/roots/ui/util/CompositeAppearance.java @@ -55,7 +55,7 @@ public class CompositeAppearance implements ModifiableCellAppearanceEx, Modifiab final TextAttributes attributes = section.getTextAttributes(); renderer.append(section.getText(), SimpleTextAttributes.fromTextAttributes(attributes)); } - setIcon(myIcon); + renderer.setIcon(myIcon); } } diff --git a/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java b/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java index 33302fcd12b6..5b401dbbe92a 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ package com.intellij.openapi.ui; import com.intellij.openapi.ui.popup.*; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; @@ -40,10 +41,10 @@ import java.util.List; */ public class ComboBoxTableRenderer extends JLabel implements TableCellRenderer, TableCellEditor, JBPopupListener { private static final Icon ARROW_ICON = IconLoader.getIcon("/general/comboArrow.png"); + private final T[] myValues; private WeakReference myPopupRef; private ChangeEvent myChangeEvent = null; - private T myValue; protected EventListenerList myListenerList = new EventListenerList(); @@ -73,8 +74,6 @@ public class ComboBoxTableRenderer extends JLabel implements TableCellRendere return value.toString(); } - - protected Runnable onChosen(@NotNull final T value) { stopCellEditing(value); @@ -89,24 +88,30 @@ public class ComboBoxTableRenderer extends JLabel implements TableCellRendere protected void paintComponent(Graphics g) { super.paintComponent(g); - final Rectangle r = getBounds(); - final Insets i = getInsets(); - - if (getText() != null && getText().length() != 0) ARROW_ICON.paintIcon(this, g, r.width - i.right - ARROW_ICON.getIconWidth(), i.top); + if (!StringUtil.isEmpty(getText())) { + final Rectangle r = getBounds(); + final Insets i = getInsets(); + final int x = r.width - i.right - ARROW_ICON.getIconWidth(); + final int y = i.top + (r.height - i.top - i.bottom - ARROW_ICON.getIconHeight()) / 2; + ARROW_ICON.paintIcon(this, g, x, y); + } } public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - customizeComponent((T) value, isSelected); + @SuppressWarnings("unchecked") final T t = (T)value; + customizeComponent(t, table, isSelected); return this; } public Component getTableCellEditorComponent(JTable table, final Object value, boolean isSelected, final int row, final int column) { - myValue = (T) value; - customizeComponent((T) value, isSelected); + @SuppressWarnings("unchecked") final T t = (T)value; + myValue = t; + customizeComponent(t, table, isSelected); + //noinspection SSBasedInspection SwingUtilities.invokeLater(new Runnable() { public void run() { - showPopup((T) value, row); + showPopup(t, row); } }); @@ -159,6 +164,14 @@ public class ComboBoxTableRenderer extends JLabel implements TableCellRendere fireEditingCanceled(); } + protected void customizeComponent(final T value, final JTable table, final boolean isSelected) { + setOpaque(true); + setText(value == null ? "" : getTextFor(value)); + setBackground(isSelected ? table.getSelectionBackground() : table.getBackground()); + setForeground(isSelected ? table.getSelectionForeground() : table.getForeground()); + } + + /** @deprecated use {@linkplain #customizeComponent(Object, javax.swing.JTable, boolean)} (to remove in IDEA 12) */ protected void customizeComponent(T value, boolean isSelected) { setOpaque(true); setText(value == null ? "" : getTextFor(value)); @@ -172,7 +185,7 @@ public class ComboBoxTableRenderer extends JLabel implements TableCellRendere public boolean isCellEditable(EventObject event) { if (event instanceof MouseEvent) { - return ((MouseEvent)event).getClickCount() >= 2; + return ((MouseEvent)event).getClickCount() >= 2; } return true; @@ -199,33 +212,35 @@ public class ComboBoxTableRenderer extends JLabel implements TableCellRendere } protected void fireEditingStopped() { - // Guaranteed to return a non-null array - Object[] listeners = myListenerList.getListenerList(); - // Process the listeners last to first, notifying - // those that are interested in this event - for (int i = listeners.length-2; i>=0; i-=2) { - if (listeners[i]==CellEditorListener.class) { - // Lazily create the event: - if (myChangeEvent == null) - myChangeEvent = new ChangeEvent(this); - ((CellEditorListener)listeners[i+1]).editingStopped(myChangeEvent); - } + // Guaranteed to return a non-null array + Object[] listeners = myListenerList.getListenerList(); + // Process the listeners last to first, notifying + // those that are interested in this event + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == CellEditorListener.class) { + // Lazily create the event: + if (myChangeEvent == null) { + myChangeEvent = new ChangeEvent(this); + } + ((CellEditorListener)listeners[i + 1]).editingStopped(myChangeEvent); } + } } protected void fireEditingCanceled() { - // Guaranteed to return a non-null array - Object[] listeners = myListenerList.getListenerList(); - // Process the listeners last to first, notifying - // those that are interested in this event - for (int i = listeners.length-2; i>=0; i-=2) { - if (listeners[i]==CellEditorListener.class) { - // Lazily create the event: - if (myChangeEvent == null) - myChangeEvent = new ChangeEvent(this); - ((CellEditorListener)listeners[i+1]).editingCanceled(myChangeEvent); - } + // Guaranteed to return a non-null array + Object[] listeners = myListenerList.getListenerList(); + // Process the listeners last to first, notifying + // those that are interested in this event + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == CellEditorListener.class) { + // Lazily create the event: + if (myChangeEvent == null) { + myChangeEvent = new ChangeEvent(this); + } + ((CellEditorListener)listeners[i + 1]).editingCanceled(myChangeEvent); } + } } private void hidePopup() { 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 30c0343ed844..99cdbaa85326 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 @@ -20,11 +20,11 @@ import com.intellij.openapi.actionSystem.DataProvider; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Pair; -import com.intellij.openapi.wm.IdeFrame; -import com.intellij.openapi.wm.WindowManager; import com.intellij.ui.InplaceButton; import com.intellij.ui.ListScrollingUtil; +import com.intellij.ui.ScreenUtil; import com.intellij.ui.ScrollPaneFactory; +import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.components.JBViewport; import com.intellij.ui.speedSearch.ListWithFilter; @@ -251,7 +251,7 @@ public class PopupChooserBuilder { builder.setDimensionServiceKey(null, myDimensionServiceKey, false).setRequestFocus(myRequestFocus).setResizable(myForceResizable) .setMovable(myForceMovable).setTitle(myForceMovable ? myTitle : null).setCancelCallback(myCancelCallback).setAlpha(myAlpha) .setFocusOwners(myFocusOwners).setCancelKeyEnabled(myCancelKeyEnabled && !(myChooserComponent instanceof ListWithFilter)). - setAdText(myAd, myAdAlignment).setKeyboardActions(myKeyboardActions).setMayBeParent(myMayBeParent); + setAdText(myAd, myAdAlignment).setKeyboardActions(myKeyboardActions).setMayBeParent(myMayBeParent).setLocateWithinScreenBounds(true); if (myCommandButton != null) { builder.setCommandButton(myCommandButton); @@ -418,12 +418,13 @@ public class PopupChooserBuilder { if (size >= 0 && size <= 20) { return list.getPreferredSize(); } else { - final Dimension even = super.preferredLayoutSize(parent); - final IdeFrame ideFrame = WindowManager.getInstance().getIdeFrame(null); - final JComponent c = ideFrame.getComponent(); + final Dimension sz = super.preferredLayoutSize(parent); + final Point p = RelativePoint.getNorthWestOf(myList).getScreenPoint(); + final Rectangle screen = ScreenUtil.getScreenRectangle(p); + final int bordersEtc = 20; - final int maxWidth = c.getWidth() - SwingUtilities.convertPoint(myList, new Point(0, 0), c).x - 2 * bordersEtc; - return new Dimension(Math.min(maxWidth, even.width) + bordersEtc, even.height + list.getCellBounds(0, 0).height / 2); + final int maxWidth = Math.abs(screen.x + screen.width - p.x) - 2 * bordersEtc; + return new Dimension(Math.min(maxWidth, sz.width) + bordersEtc, sz.height + list.getCellBounds(0, 0).height / 2); } } }; diff --git a/platform/platform-api/src/com/intellij/ui/ListToolbarDecorator.java b/platform/platform-api/src/com/intellij/ui/ListToolbarDecorator.java index d5acf027f523..594243e07a71 100644 --- a/platform/platform-api/src/com/intellij/ui/ListToolbarDecorator.java +++ b/platform/platform-api/src/com/intellij/ui/ListToolbarDecorator.java @@ -18,6 +18,8 @@ package com.intellij.ui; import javax.swing.*; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; /** * @author Konstantin Bulenkov @@ -35,6 +37,12 @@ class ListToolbarDecorator extends ToolbarDecorator { updateButtons(); } }); + myList.addPropertyChangeListener("enabled", new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + updateButtons(); + } + }); } private void createActions() { @@ -58,7 +66,7 @@ class ListToolbarDecorator extends ToolbarDecorator { ListUtil.moveSelectedItemsDown(myList); updateButtons(); } - }; + }; } @Override @@ -69,21 +77,29 @@ class ListToolbarDecorator extends ToolbarDecorator { @Override protected void updateButtons() { final AddRemoveUpDownPanel p = getPanel(); - if (myList.isEnabled() && p != null) { - final int index = myList.getSelectedIndex(); - if (0 <= index && index < myList.getModel().getSize()) { - final boolean downEnable = myList.getMaxSelectionIndex() < myList.getModel().getSize() - 1; - final boolean upEnable = myList.getMinSelectionIndex() > 0; - p.setEnabled(AddRemoveUpDownPanel.Buttons.REMOVE, true); - p.setEnabled(AddRemoveUpDownPanel.Buttons.UP, upEnable); - p.setEnabled(AddRemoveUpDownPanel.Buttons.DOWN, downEnable); - } else { + if (p != null) { + if (myList.isEnabled()) { + final int index = myList.getSelectedIndex(); + if (0 <= index && index < myList.getModel().getSize()) { + final boolean downEnable = myList.getMaxSelectionIndex() < myList.getModel().getSize() - 1; + final boolean upEnable = myList.getMinSelectionIndex() > 0; + p.setEnabled(AddRemoveUpDownPanel.Buttons.REMOVE, true); + p.setEnabled(AddRemoveUpDownPanel.Buttons.UP, upEnable); + p.setEnabled(AddRemoveUpDownPanel.Buttons.DOWN, downEnable); + } + else { + p.setEnabled(AddRemoveUpDownPanel.Buttons.REMOVE, false); + p.setEnabled(AddRemoveUpDownPanel.Buttons.UP, false); + p.setEnabled(AddRemoveUpDownPanel.Buttons.DOWN, false); + } + p.setEnabled(AddRemoveUpDownPanel.Buttons.ADD, true); + } + else { + p.setEnabled(AddRemoveUpDownPanel.Buttons.ADD, false); p.setEnabled(AddRemoveUpDownPanel.Buttons.REMOVE, false); p.setEnabled(AddRemoveUpDownPanel.Buttons.UP, false); p.setEnabled(AddRemoveUpDownPanel.Buttons.DOWN, false); } - p.setEnabled(AddRemoveUpDownPanel.Buttons.ADD, true); } - } } diff --git a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java index b340f458c38e..c8e8ed97e9e5 100644 --- a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java +++ b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java @@ -43,6 +43,7 @@ import java.util.Map; * * @author Vladimir Kondratyev */ +@SuppressWarnings({"NonPrivateFieldAccessedInSynchronizedContext", "FieldAccessedSynchronizedAndUnsynchronized", "UnusedDeclaration"}) public class SimpleColoredComponent extends JComponent implements Accessible { private static final Logger LOG = Logger.getInstance("#com.intellij.ui.SimpleColoredComponent"); public static final Color STYLE_SEARCH_MATCH_BACKGROUND = new Color(250, 250, 250, 140); @@ -78,7 +79,7 @@ public class SimpleColoredComponent extends JComponent implements Accessible { * if the component represents a selected item in a focused JList. * Border can be null. */ - private MyBorder myBorder; + private Border myBorder; private int myMainTextLastIndex = -1; @@ -107,6 +108,8 @@ public class SimpleColoredComponent extends JComponent implements Accessible { /** * Appends string fragments to existing ones. Appended string * will have specified attributes. + * @param fragment text fragment + * @param attributes text attributes */ public final void append(@NotNull final String fragment, @NotNull final SimpleTextAttributes attributes) { append(fragment, attributes, myMainTextLastIndex < 0); @@ -115,17 +118,22 @@ public class SimpleColoredComponent extends JComponent implements Accessible { /** * Appends string fragments to existing ones. Appended string * will have specified attributes. + * @param fragment text fragment + * @param attributes text attributes + * @param isMainText main text of not */ public void append(@NotNull final String fragment, @NotNull final SimpleTextAttributes attributes, boolean isMainText) { - synchronized (this) { - myFragments.add(fragment); - myAttributes.add(attributes); - if (isMainText) { - myMainTextLastIndex = myFragments.size() - 1; - } - } + _append(fragment, attributes, isMainText); revalidateAndRepaint(); } + + private synchronized void _append(@NotNull final String fragment, @NotNull final SimpleTextAttributes attributes, boolean isMainText) { + myFragments.add(fragment); + myAttributes.add(attributes); + if (isMainText) { + myMainTextLastIndex = myFragments.size() - 1; + } + } private void revalidateAndRepaint() { if (myAutoInvalidate) { @@ -136,19 +144,21 @@ public class SimpleColoredComponent extends JComponent implements Accessible { } public void append(@NotNull final String fragment, @NotNull final SimpleTextAttributes attributes, Object tag) { - synchronized (this) { - append(fragment, attributes); - if (myFragmentTags == null) { - myFragmentTags = new ArrayList(); - } - while(myFragmentTags.size() < myFragments.size()-1) { - myFragmentTags.add(null); - } - myFragmentTags.add(tag); - } + _append(fragment, attributes, tag); revalidateAndRepaint(); } + private synchronized void _append(String fragment, SimpleTextAttributes attributes, Object tag) { + append(fragment, attributes); + if (myFragmentTags == null) { + myFragmentTags = new ArrayList(); + } + while(myFragmentTags.size() < myFragments.size()-1) { + myFragmentTags.add(null); + } + myFragmentTags.add(tag); + } + public synchronized void appendAlign(int alignWidth) { final int alignIndex = myFragments.size()-1; myAligns.put(alignIndex, alignWidth); @@ -159,18 +169,20 @@ public class SimpleColoredComponent extends JComponent implements Accessible { * They are icon, text fragments and their attributes, "paint focus border". */ public void clear() { - synchronized (this) { - myIcon = null; - myPaintFocusBorder = false; - myFragments.clear(); - myAttributes.clear(); - myFragmentTags = null; - myMainTextLastIndex = -1; - myAligns.clear(); - } + _clear(); revalidateAndRepaint(); } + private synchronized void _clear() { + myIcon = null; + myPaintFocusBorder = false; + myFragments.clear(); + myAttributes.clear(); + myFragmentTags = null; + myMainTextLastIndex = -1; + myAligns.clear(); + } + /** * @return component's icon. This method returns null * if there is no icon. @@ -181,6 +193,7 @@ public class SimpleColoredComponent extends JComponent implements Accessible { /** * Sets a new component icon + * @param icon icon */ public final void setIcon(final @Nullable Icon icon) { myIcon = icon; @@ -196,6 +209,7 @@ public class SimpleColoredComponent extends JComponent implements Accessible { /** * Sets specified internal paddings + * @param ipad insets */ public void setIpad(final Insets ipad) { myIpad = ipad; @@ -213,6 +227,7 @@ public class SimpleColoredComponent extends JComponent implements Accessible { /** * Sets a new gap between icon and text * + * @param iconTextGap the gap between text and icon * @throws java.lang.IllegalArgumentException * if the iconTextGap * has a negative value @@ -226,16 +241,17 @@ public class SimpleColoredComponent extends JComponent implements Accessible { revalidateAndRepaint(); } - public MyBorder getMyBorder() { + public Border getMyBorder() { return myBorder; } - public void setMyBorder(@Nullable MyBorder border) { + public void setMyBorder(@Nullable Border border) { myBorder = border; } /** * Sets whether focus border is painted or not + * @param paintFocusBorder true or false */ protected final void setPaintFocusBorder(final boolean paintFocusBorder) { myPaintFocusBorder = paintFocusBorder; @@ -246,6 +262,7 @@ public class SimpleColoredComponent extends JComponent implements Accessible { /** * Sets whether focus border extends to icon or not. If so then * component also extends the selection. + * @param focusBorderAroundIcon true or false */ protected final void setFocusBorderAroundIcon(final boolean focusBorderAroundIcon) { myFocusBorderAroundIcon = focusBorderAroundIcon; @@ -274,6 +291,7 @@ public class SimpleColoredComponent extends JComponent implements Accessible { return computePreferredSize(false); } + @Nullable public synchronized Object getFragmentTag(int index) { if (myFragmentTags != null && index < myFragmentTags.size()) { return myFragmentTags.get(index); @@ -368,7 +386,7 @@ public class SimpleColoredComponent extends JComponent implements Accessible { protected void paintComponent(final Graphics g) { try { - doPaint(g); + _doPaint(g); } catch (RuntimeException e) { LOG.error(logSwingPath(), e); @@ -376,55 +394,67 @@ public class SimpleColoredComponent extends JComponent implements Accessible { } } - protected synchronized void doPaint(final Graphics g) { + private synchronized void _doPaint(final Graphics g) { checkCanPaint(g); - int xOffset = 0; - - // Paint icon and its background - final Icon icon = myIcon; // guard against concurrent modification (IDEADEV-12635) + doPaint((Graphics2D)g); + } + + protected void doPaint(final Graphics2D g) { + int offset = 0; + final Icon icon = myIcon; // guard against concurrent modification (IDEADEV-12635) if (icon != null) { - final Container parent = getParent(); - Color iconBackgroundColor = null; - if (isOpaque() || isIconOpaque()) { - if (parent != null && !myFocusBorderAroundIcon && !UIUtil.isFullRowSelectionLAF()) { - iconBackgroundColor = parent.getBackground(); - } - else { - iconBackgroundColor = getBackground(); - } - } - - if (iconBackgroundColor != null) { - g.setColor(iconBackgroundColor); - g.fillRect(0, 0, icon.getIconWidth() + myIpad.left + myIconTextGap, getHeight()); - } - - paintIcon(g, icon); - - xOffset += myIpad.left + icon.getIconWidth() + myIconTextGap; + doPaintIcon(g, icon); + offset += myIpad.left + icon.getIconWidth() + myIconTextGap; } + doPaintTextBackground(g, offset); + doPaintText(g, offset, myFocusBorderAroundIcon || icon == null); + } + + + protected void doPaintTextBackground(Graphics2D g, int offset) { if (isOpaque() || shouldDrawBackground()) { - // Paint text background g.setColor(getBackground()); - g.fillRect(xOffset, 0, getWidth() - xOffset, getHeight()); + g.fillRect(offset, 0, getWidth() - offset, getHeight()); + } + } + + protected void doPaintIcon(Graphics2D g, Icon icon) { + final Container parent = getParent(); + Color iconBackgroundColor = null; + if (isOpaque() || isIconOpaque()) { + if (parent != null && !myFocusBorderAroundIcon && !UIUtil.isFullRowSelectionLAF()) { + iconBackgroundColor = parent.getBackground(); + } + else { + iconBackgroundColor = getBackground(); + } } + if (iconBackgroundColor != null) { + g.setColor(iconBackgroundColor); + g.fillRect(0, 0, icon.getIconWidth() + myIpad.left + myIconTextGap, getHeight()); + } + + paintIcon(g, icon); + } + + protected int doPaintText(Graphics2D g, int offset, boolean focusAroundIcon) { // If there is no icon, then we have to add left internal padding - if (xOffset == 0) { - xOffset = myIpad.left; + if (offset == 0) { + offset = myIpad.left; } - int textStart = xOffset; + int textStart = offset; if (myBorder != null) { - xOffset += myBorder.getBorderInsets(this).left; + offset += myBorder.getBorderInsets(this).left; } final List searchMatches = new ArrayList(); - - // Paint text + UIUtil.applyRenderingHints(g); applyAdditionalHints(g); + for (int i = 0; i < myFragments.size(); i++) { final SimpleTextAttributes attributes = myAttributes.get(i); Font font = g.getFont(); @@ -440,7 +470,7 @@ public class SimpleColoredComponent extends JComponent implements Accessible { final Color bgColor = attributes.getBgColor(); if (isOpaque() && bgColor != null) { g.setColor(bgColor); - g.fillRect(xOffset, 0, fragmentWidth, getHeight()); + g.fillRect(offset, 0, fragmentWidth, getHeight()); } Color color = attributes.getFgColor(); @@ -457,17 +487,17 @@ public class SimpleColoredComponent extends JComponent implements Accessible { if (!attributes.isSearchMatch()) { if (shouldDrawMacShadow()) { g.setColor(STYLE_SEARCH_MATCH_BACKGROUND); - g.drawString(fragment, xOffset, textBaseline + 1); + g.drawString(fragment, offset, textBaseline + 1); } - + g.setColor(color); - g.drawString(fragment, xOffset, textBaseline); + g.drawString(fragment, offset, textBaseline); } // 1. Strikeout effect if (attributes.isStrikeout()) { final int strikeOutAt = textBaseline + (metrics.getDescent() - metrics.getAscent()) / 2; - UIUtil.drawLine(g, xOffset, strikeOutAt, xOffset + fragmentWidth, strikeOutAt); + UIUtil.drawLine(g, offset, strikeOutAt, offset + fragmentWidth, strikeOutAt); } // 2. Waved effect if (attributes.isWaved()) { @@ -475,7 +505,7 @@ public class SimpleColoredComponent extends JComponent implements Accessible { g.setColor(attributes.getWaveColor()); } final int wavedAt = textBaseline + 1; - for (int x = xOffset; x <= xOffset + fragmentWidth; x += 4) { + for (int x = offset; x <= offset + fragmentWidth; x += 4) { UIUtil.drawLine(g, x, wavedAt, x + 2, wavedAt + 2); UIUtil.drawLine(g, x + 3, wavedAt + 1, x + 4, wavedAt); } @@ -483,41 +513,40 @@ public class SimpleColoredComponent extends JComponent implements Accessible { // 3. Underline if (attributes.isUnderline()) { final int underlineAt = textBaseline + 1; - UIUtil.drawLine(g, xOffset, underlineAt, xOffset + fragmentWidth, underlineAt); + UIUtil.drawLine(g, offset, underlineAt, offset + fragmentWidth, underlineAt); } // 4. Bold Dotted Line if (attributes.isBoldDottedLine()) { final int dottedAt = SystemInfo.isMac ? textBaseline : textBaseline + 1; final Color lineColor = attributes.getWaveColor(); - UIUtil.drawBoldDottedLine((Graphics2D)g, xOffset, xOffset + fragmentWidth, dottedAt, bgColor, lineColor, isOpaque()); + UIUtil.drawBoldDottedLine(g, offset, offset + fragmentWidth, dottedAt, bgColor, lineColor, isOpaque()); } if (attributes.isSearchMatch()) { - searchMatches.add(new Object[] {xOffset, xOffset + fragmentWidth, textBaseline, fragment, g.getFont()}); + searchMatches.add(new Object[] {offset, offset + fragmentWidth, textBaseline, fragment, g.getFont()}); } final Integer fixedWidth = myAligns.get(i); if (fixedWidth != null && fragmentWidth < fixedWidth.intValue()) { - //if (fixedWidth != null) { - xOffset += fixedWidth.intValue(); + //if (fixedWidth != null) { + offset += fixedWidth.intValue(); } else { - xOffset += fragmentWidth; + offset += fragmentWidth; } } // Paint focus border around the text and icon (if necessary) if (myPaintFocusBorder && myBorder != null) { - if (myFocusBorderAroundIcon || icon == null) { + if (focusAroundIcon) { myBorder.paintBorder(this, g, 0, 0, getWidth(), getHeight()); - } - else { + } else { myBorder.paintBorder(this, g, textStart, 0, getWidth() - textStart, getHeight()); } } // draw search matches after all for (final Object[] info: searchMatches) { - UIUtil.drawSearchMatch((Graphics2D)g, (Integer) info[0], (Integer) info[1], getHeight()); + UIUtil.drawSearchMatch(g, (Integer) info[0], (Integer) info[1], getHeight()); g.setFont((Font) info[4]); if (shouldDrawMacShadow()) { @@ -528,8 +557,9 @@ public class SimpleColoredComponent extends JComponent implements Accessible { g.setColor(new Color(50, 50, 50)); g.drawString((String) info[3], (Integer) info[0], (Integer) info[2]); } + return offset; } - + protected boolean shouldDrawMacShadow() { return false; } @@ -583,8 +613,8 @@ public class SimpleColoredComponent extends JComponent implements Accessible { } protected void setBorderInsets(Insets insets) { - if (myBorder != null) { - myBorder.setInsets(insets); + if (myBorder instanceof MyBorder) { + ((MyBorder)myBorder).setInsets(insets); } revalidateAndRepaint(); @@ -617,7 +647,7 @@ public class SimpleColoredComponent extends JComponent implements Accessible { @Override public String toString() { - StringBuffer result = new StringBuffer(); + final StringBuilder result = new StringBuilder(); for (String each : myFragments) { result.append(each); } @@ -662,6 +692,7 @@ public class SimpleColoredComponent extends JComponent implements Accessible { return 0; } + @Nullable @Override public Accessible getAccessibleChild(int i) { return null; diff --git a/platform/platform-api/src/com/intellij/ui/TableToolbarDecorator.java b/platform/platform-api/src/com/intellij/ui/TableToolbarDecorator.java index cb1fa2b1ab89..eea758f004fd 100644 --- a/platform/platform-api/src/com/intellij/ui/TableToolbarDecorator.java +++ b/platform/platform-api/src/com/intellij/ui/TableToolbarDecorator.java @@ -27,6 +27,8 @@ import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.TableModel; import java.awt.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; /** * @author Konstantin Bulenkov @@ -48,6 +50,12 @@ class TableToolbarDecorator extends ToolbarDecorator { updateButtons(); } }); + myTable.addPropertyChangeListener("enabled", new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + updateButtons(); + } + }); } @Override @@ -57,21 +65,30 @@ class TableToolbarDecorator extends ToolbarDecorator { protected void updateButtons() { final AddRemoveUpDownPanel p = getPanel(); - if (myTable.isEnabled() && p != null) { - final int index = myTable.getSelectedRow(); - final int size = myTableModel.getRowCount(); - if (0 <= index && index < size) { - final boolean downEnable = myTable.getSelectionModel().getMaxSelectionIndex() < size - 1; - final boolean upEnable = myTable.getSelectionModel().getMinSelectionIndex() > 0; - p.setEnabled(AddRemoveUpDownPanel.Buttons.REMOVE, true); - p.setEnabled(AddRemoveUpDownPanel.Buttons.UP, upEnable); - p.setEnabled(AddRemoveUpDownPanel.Buttons.DOWN, downEnable); - } else { + if (p != null) { + if (myTable.isEnabled()) { + final int index = myTable.getSelectedRow(); + final int size = myTableModel.getRowCount(); + if (0 <= index && index < size) { + final boolean downEnable = myTable.getSelectionModel().getMaxSelectionIndex() < size - 1; + final boolean upEnable = myTable.getSelectionModel().getMinSelectionIndex() > 0; + p.setEnabled(AddRemoveUpDownPanel.Buttons.REMOVE, true); + p.setEnabled(AddRemoveUpDownPanel.Buttons.UP, upEnable); + p.setEnabled(AddRemoveUpDownPanel.Buttons.DOWN, downEnable); + } + else { + p.setEnabled(AddRemoveUpDownPanel.Buttons.REMOVE, false); + p.setEnabled(AddRemoveUpDownPanel.Buttons.UP, false); + p.setEnabled(AddRemoveUpDownPanel.Buttons.DOWN, false); + } + p.setEnabled(AddRemoveUpDownPanel.Buttons.ADD, true); + } + else { + p.setEnabled(AddRemoveUpDownPanel.Buttons.ADD, false); p.setEnabled(AddRemoveUpDownPanel.Buttons.REMOVE, false); p.setEnabled(AddRemoveUpDownPanel.Buttons.UP, false); p.setEnabled(AddRemoveUpDownPanel.Buttons.DOWN, false); } - p.setEnabled(AddRemoveUpDownPanel.Buttons.ADD, true); } } diff --git a/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java b/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java index f8a0b34ca3c5..97a0e88be320 100644 --- a/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java +++ b/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java @@ -24,6 +24,7 @@ import com.intellij.util.ui.ElementProducer; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.Border; @@ -38,6 +39,18 @@ import java.util.List; */ @SuppressWarnings("UnusedDeclaration") public abstract class ToolbarDecorator implements DataProvider, AddRemoveUpDownPanel.ListenerFactory { + private static final Comparator ACTION_BUTTONS_SORTER = new Comparator() { + @Override + public int compare(AnAction a1, AnAction a2) { + if (a1 instanceof AnActionButton && a2 instanceof AnActionButton) { + final JComponent c1 = ((AnActionButton)a1).getContextComponent(); + final JComponent c2 = ((AnActionButton)a2).getContextComponent(); + return c1.hasFocus() ? -1 : c2.hasFocus() ? 1 : 0; + } + return 0; + } + }; + protected Border myToolbarBorder; protected boolean myAddActionEnabled; protected boolean myRemoveActionEnabled; @@ -57,26 +70,13 @@ public abstract class ToolbarDecorator implements DataProvider, AddRemoveUpDownP private Dimension myPreferredSize; private AddRemoveUpDownPanel myPanel; - public ToolbarDecorator() { - } - protected abstract JComponent getComponent(); + protected abstract void updateButtons(); final AddRemoveUpDownPanel getPanel() { return myPanel; } - private static final Comparator ACTION_BUTTONS_SORTER = new Comparator() { - @Override - public int compare(AnAction a1, AnAction a2) { - if (a1 instanceof AnActionButton && a2 instanceof AnActionButton) { - final JComponent c1 = ((AnActionButton)a1).getContextComponent(); - final JComponent c2 = ((AnActionButton)a2).getContextComponent(); - return c1.hasFocus() ? -1 : c2.hasFocus() ? 1 : 0; - } - return 0; - } - }; protected ToolbarDecorator initPositionAndBorder() { myToolbarPosition = SystemInfo.isMac ? ActionToolbarPosition.BOTTOM : ActionToolbarPosition.RIGHT; @@ -240,7 +240,6 @@ public abstract class ToolbarDecorator implements DataProvider, AddRemoveUpDownP return null; } - private Object getPlacement() { switch (myToolbarPosition) { case TOP: return BorderLayout.NORTH; @@ -300,23 +299,27 @@ public abstract class ToolbarDecorator implements DataProvider, AddRemoveUpDownP }; } + @Nullable public static AnActionButton findAddButton(@NotNull JComponent container) { return findButton(container, AddRemoveUpDownPanel.Buttons.ADD); } + @Nullable public static AnActionButton findRemoveButton(@NotNull JComponent container) { return findButton(container, AddRemoveUpDownPanel.Buttons.REMOVE); } + @Nullable public static AnActionButton findUpButton(@NotNull JComponent container) { return findButton(container, AddRemoveUpDownPanel.Buttons.UP); } + @Nullable public static AnActionButton findDownButton(@NotNull JComponent container) { return findButton(container, AddRemoveUpDownPanel.Buttons.DOWN); } - + @Nullable private static AnActionButton findButton(JComponent comp, AddRemoveUpDownPanel.Buttons type) { final AddRemoveUpDownPanel panel = UIUtil.findComponentOfType(comp, AddRemoveUpDownPanel.class); if (panel != null) { diff --git a/platform/platform-impl/src/com/intellij/ide/MacOSApplicationProvider.java b/platform/platform-impl/src/com/intellij/ide/MacOSApplicationProvider.java index 7b1c6dd05963..2520e4d57be5 100644 --- a/platform/platform-impl/src/com/intellij/ide/MacOSApplicationProvider.java +++ b/platform/platform-impl/src/com/intellij/ide/MacOSApplicationProvider.java @@ -149,8 +149,9 @@ public class MacOSApplicationProvider implements ApplicationComponent { Foundation.registerObjcClassPair(checkForUpdatesClass); ID checkForUpdates = Foundation.invoke("NSCheckForUpdates", "alloc"); - Foundation.invoke(checkForUpdates, Foundation.createSelector("initWithTitle:action:keyEquivalent:"), Foundation.cfString("Check for Updates..."), - Foundation.createSelector("checkForUpdates"), Foundation.cfString("")); + Foundation.invoke(checkForUpdates, Foundation.createSelector("initWithTitle:action:keyEquivalent:"), + Foundation.nsString("Check for Updates..."), + Foundation.createSelector("checkForUpdates"), Foundation.nsString("")); Foundation.invoke(checkForUpdates, Foundation.createSelector("setTarget:"), checkForUpdates); Foundation.invoke(appMenu, Foundation.createSelector("insertItem:atIndex:"), checkForUpdates, 1); 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 725afd14a85b..ed84b06df2db 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java @@ -18,21 +18,17 @@ package com.intellij.ide.plugins; import com.intellij.CommonBundle; import com.intellij.ide.IdeBundle; import com.intellij.ide.startup.StartupActionScriptManager; -import com.intellij.openapi.application.ApplicationInfo; import com.intellij.openapi.extensions.PluginId; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.updateSettings.impl.PluginDownloader; -import com.intellij.openapi.util.BuildNumber; import com.intellij.ui.GuiUtils; import com.intellij.util.ArrayUtil; -import org.jetbrains.annotations.NonNls; import javax.swing.*; import java.io.IOException; -import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; @@ -160,12 +156,7 @@ public class PluginInstaller { } synchronized (PluginManager.lock) { - final BuildNumber buildNumber = ApplicationInfo.getInstance().getBuild(); - final @NonNls String url = RepositoryHelper.DOWNLOAD_URL + - URLEncoder.encode(pluginNode.getPluginId().getIdString(), "UTF8") + - "&build=" + buildNumber.asString(); - final PluginDownloader downloader = - new PluginDownloader(pluginNode.getPluginId().getIdString(), url, null, null, pluginNode.getName()); + final PluginDownloader downloader = PluginDownloader.createDownloader(pluginNode); if (downloader.prepareToInstall(ProgressManager.getInstance().getProgressIndicator())) { downloader.install(); pluginNode.setStatus(PluginNode.STATUS_DOWNLOADED); diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java b/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java index f09f5f4e51ff..74dea1cf21b9 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java @@ -24,6 +24,7 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.net.HttpConfigurable; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.Nullable; import org.xml.sax.SAXException; import javax.swing.*; @@ -52,7 +53,7 @@ public class RepositoryHelper { @NonNls private static final String FILENAME = "filename="; @NonNls public static final String extPluginsFile = "availables.xml"; - public static ArrayList process(JLabel label) throws IOException, ParserConfigurationException, SAXException { + public static ArrayList process(@Nullable JLabel label) throws IOException, ParserConfigurationException, SAXException { ArrayList plugins = null; try { BuildNumber buildNumber = ApplicationInfo.getInstance().getBuild(); @@ -85,7 +86,8 @@ public class RepositoryHelper { return plugins; } - private static void setLabelText(final JLabel label, final String message) { + private static void setLabelText(@Nullable final JLabel label, final String message) { + if (label == null) return; UIUtil.invokeLaterIfNeeded(new Runnable() { public void run() { label.setText(message); diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/MacRestarter.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/MacRestarter.java index 10bf5ffa82a4..73b76980be65 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/MacRestarter.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/MacRestarter.java @@ -53,10 +53,10 @@ public class MacRestarter { final long processId = Foundation.invoke(app, Foundation.createSelector("processIdentifier")).longValue(); final ID args = Foundation.invoke(Foundation.getClass("NSArray"), Foundation.createSelector("arrayWithObjects:"), - new Object[]{Foundation.cfString(appPath), Foundation.cfString(String.valueOf(processId))}); + new Object[]{Foundation.nsString(appPath), Foundation.nsString(String.valueOf(processId))}); Foundation.invoke(Foundation.getClass("NSTask"), Foundation.createSelector("launchedTaskWithLaunchPath:arguments:"), - Foundation.cfString(relaunchPath), args); + Foundation.nsString(relaunchPath), args); } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java index 4779a17076b5..deaab11d67a2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ComplementaryFontsRegistry.java @@ -16,21 +16,23 @@ package com.intellij.openapi.editor.impl; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.SystemInfo; import gnu.trove.TIntHashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.awt.*; -import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedHashMap; +import java.util.*; +import java.util.List; /** * @author max */ public class ComplementaryFontsRegistry { private static final Object lock = new String("common lock"); - private static final ArrayList ourFontNames; + private static final List ourFontNames; + private static final Set ourStyledFontNames; private static final LinkedHashMap ourUsedFonts; private static FontKey ourSharedKeyInstance = new FontKey("", 0, 0); private static FontInfo ourSharedDefaultFont; @@ -72,11 +74,22 @@ public class ComplementaryFontsRegistry { @NonNls private static final String ITALIC_SUFFIX = ".italic"; static { + ourStyledFontNames = new HashSet(); ourFontNames = new ArrayList(); if (ApplicationManager.getApplication().isUnitTestMode()) { ourFontNames.add("Monospaced"); } else { GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment(); + if (SystemInfo.isMac) { + Font[] allFonts = graphicsEnvironment.getAllFonts(); + for (Font font : allFonts) { + String name = font.getName(); + if (name.endsWith("-Italic") || name.endsWith("-Bold") || name.endsWith("-BoldItalic")) { + ourStyledFontNames.add(font.getName()); + } + } + } + String[] fontNames = graphicsEnvironment.getAvailableFontFamilyNames(); for (final String fontName : fontNames) { if (!fontName.endsWith(BOLD_SUFFIX) && !fontName.endsWith(ITALIC_SUFFIX)) { @@ -87,12 +100,30 @@ public class ComplementaryFontsRegistry { ourUsedFonts = new LinkedHashMap(); } + private static Pair fontFamily(String familyName, int style) { + if (!SystemInfo.isMac || style == 0) return Pair.create(familyName, style); + + StringBuilder st = new StringBuilder(familyName).append('-'); + if ((style & Font.BOLD) == Font.BOLD) { + st.append("Bold"); + } + + if ((style & Font.ITALIC) == Font.ITALIC) { + st.append("Italic"); + } + + String styledFamilyName = st.toString(); + boolean found = ourStyledFontNames.contains(styledFamilyName); + return Pair.create(found ? styledFamilyName : familyName, found ? Font.PLAIN : style); + } + public static FontInfo getFontAbleToDisplay(char c, int size, int style, @NotNull String defaultFontFamily) { synchronized (lock) { + Pair p = fontFamily(defaultFontFamily, style); if (ourSharedKeyInstance.mySize == size && - ourSharedKeyInstance.myStyle == style && + ourSharedKeyInstance.myStyle == p.getSecond() && ourSharedKeyInstance.myFamilyName != null && - ourSharedKeyInstance.myFamilyName.equals(defaultFontFamily) && + ourSharedKeyInstance.myFamilyName.equals(p.getFirst()) && ourSharedDefaultFont != null && ( c < 128 || ourSharedDefaultFont.canDisplay(c) @@ -101,13 +132,13 @@ public class ComplementaryFontsRegistry { return ourSharedDefaultFont; } - ourSharedKeyInstance.myFamilyName = defaultFontFamily; + ourSharedKeyInstance.myFamilyName = p.getFirst(); ourSharedKeyInstance.mySize = size; - ourSharedKeyInstance.myStyle = style; + ourSharedKeyInstance.myStyle = p.getSecond(); FontInfo defaultFont = ourUsedFonts.get(ourSharedKeyInstance); if (defaultFont == null) { - defaultFont = new FontInfo(defaultFontFamily, size, style); + defaultFont = new FontInfo(p.getFirst(), size, p.getSecond()); ourUsedFonts.put(ourSharedKeyInstance, defaultFont); ourSharedKeyInstance = new FontKey("", 0, 0); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index dade4f28f702..93d205122d2e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -131,7 +131,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi private final EditorGutterComponentImpl myGutterComponent; static { - ComplementaryFontsRegistry.getFontAbleToDisplay(' ', 0,0,""); // load costly font info + ComplementaryFontsRegistry.getFontAbleToDisplay(' ', 0,0, UIManager.getFont("Label.font").getFamily()); // load costly font info } private final CommandProcessor myCommandProcessor; diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java index 63b731e50a13..13330ba4359e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java @@ -419,8 +419,7 @@ public class ProgressWindow extends BlockingProgressIndicator implements Disposa private void initDialog(boolean shouldShowBackground, String cancelText) { if (UIUtil.isUnderAquaLookAndFeel()) { - UIUtil.applyStyle(UIUtil.ComponentStyle.SMALL, myTextLabel); - UIUtil.applyStyle(UIUtil.ComponentStyle.MINI, myText2Label); + UIUtil.applyStyle(UIUtil.ComponentStyle.SMALL, myText2Label); } myProgressBar.setPreferredSize(new Dimension(UIUtil.isUnderAquaLookAndFeel() ? 350 : 450, -1)); diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/ShadowBorderPainter.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/ShadowBorderPainter.java index 8741f56dcfff..0a74d0322702 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/ShadowBorderPainter.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/ShadowBorderPainter.java @@ -59,7 +59,7 @@ public class ShadowBorderPainter { public static BufferedImage createShadow(final JComponent c, final int width, final int height, boolean isPopup) { final GraphicsConfiguration graphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment(). - getDefaultScreenDevice().getDefaultConfiguration(); + getDefaultScreenDevice().getDefaultConfiguration(); final BufferedImage image = graphicsConfiguration.createCompatibleImage(width, height, Transparency.TRANSLUCENT); final Graphics2D g = image.createGraphics(); @@ -77,24 +77,23 @@ public class ShadowBorderPainter { topLeft.paintIcon(c, g, 0, 0); - topRight.paintIcon(c, g, width - sideSize * 2, 0); + topRight.paintIcon(c, g, width - topRight.getIconWidth(), 0); + bottomRight.paintIcon(c, g, width - bottomRight.getIconWidth(), height - bottomRight.getIconHeight()); + bottomLeft.paintIcon(c, g, 0, height - bottomLeft.getIconHeight()); - for (int _x = sideSize * 2; _x < width - sideSize * 2; _x ++) { + for (int _x = topLeft.getIconWidth(); _x < width - topRight.getIconWidth(); _x++) { top.paintIcon(c, g, _x, 0); } - - for (int _x = bottomSize * 2; _x < width - bottomSize * 2; _x ++) { + for (int _x = bottomLeft.getIconWidth(); _x < width - bottomLeft.getIconWidth(); _x++) { bottom.paintIcon(c, g, _x, height - bottomSize); } - - for (int _y = sideSize * 2; _y < height - bottomSize * 2; _y ++) { + for (int _y = topLeft.getIconHeight(); _y < height - bottomLeft.getIconHeight(); _y++) { left.paintIcon(c, g, 0, _y); + } + for (int _y = topRight.getIconHeight(); _y < height - bottomRight.getIconHeight(); _y++) { right.paintIcon(c, g, width - sideSize, _y); } - bottomRight.paintIcon(c, g, width - bottomSize * 2, height - bottomSize * 2); - bottomLeft.paintIcon(c, g, 0, height - bottomSize * 2); - g.dispose(); return image; } @@ -111,7 +110,7 @@ public class ShadowBorderPainter { int size = shadowSize; final float w = source.getWidth(null); final float h = source.getHeight(null); - float ratio = w /h; + float ratio = w / h; float deltaX = size; float deltaY = size / ratio; @@ -157,5 +156,4 @@ public class ShadowBorderPainter { return image; } } - } diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java index 70eb21a5ee44..123e575d69ba 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java @@ -42,7 +42,7 @@ public class CheckForUpdateAction extends AnAction implements DumbAware { } public static void actionPerformed(Project project, final boolean enableLink, final @Nullable UpdateSettingsConfigurable settingsConfigurable) { - ProgressManager.getInstance().run(new Task.Backgroundable(project, "Checking for updates", false) { + ProgressManager.getInstance().run(new Task.Modal(project, "Checking for updates", false) { @Override public void run(@NotNull ProgressIndicator indicator) { final CheckForUpdateResult result = UpdateChecker.checkForUpdates(true); diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java index 4306ccdbc0d9..0e78205586ad 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java @@ -19,6 +19,7 @@ import com.intellij.ide.IdeBundle; import com.intellij.ide.plugins.IdeaPluginDescriptor; import com.intellij.ide.plugins.IdeaPluginDescriptorImpl; import com.intellij.ide.plugins.PluginManager; +import com.intellij.ide.plugins.RepositoryHelper; import com.intellij.ide.startup.StartupActionScriptManager; import com.intellij.openapi.application.ApplicationInfo; import com.intellij.openapi.application.ApplicationManager; @@ -40,6 +41,7 @@ import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; +import java.net.URLEncoder; /** * @author anna @@ -312,4 +314,12 @@ public class PluginDownloader { public String getPluginVersion() { return myPluginVersion; } + + public static PluginDownloader createDownloader(IdeaPluginDescriptor pluginDescriptor) throws UnsupportedEncodingException { + final BuildNumber buildNumber = ApplicationInfo.getInstance().getBuild(); + final @NonNls String url = RepositoryHelper.DOWNLOAD_URL + + URLEncoder.encode(pluginDescriptor.getPluginId().getIdString(), "UTF8") + + "&build=" + buildNumber.asString(); + return new PluginDownloader(pluginDescriptor.getPluginId().getIdString(), url, null, null, pluginDescriptor.getName()); + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java index 734b41e4521f..2d07eb62b9fe 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java @@ -16,6 +16,10 @@ package com.intellij.openapi.updateSettings.impl; import com.intellij.ide.IdeBundle; +import com.intellij.ide.plugins.IdeaPluginDescriptor; +import com.intellij.ide.plugins.IdeaPluginDescriptorImpl; +import com.intellij.ide.plugins.PluginManager; +import com.intellij.ide.plugins.RepositoryHelper; import com.intellij.ide.reporter.ConnectionException; import com.intellij.ide.util.PropertiesComponent; import com.intellij.notification.Notification; @@ -156,23 +160,56 @@ public final class UpdateChecker { failed.add(host); } } - if (!failed.isEmpty()) { - final String failedMessage = IdeBundle.message("connection.failed.message", StringUtil.join(failed, ",")); - if (showErrorDialog) { - UIUtil.invokeLaterIfNeeded(new Runnable() { - @Override - public void run() { - Messages.showErrorDialog(failedMessage, IdeBundle.message("title.connection.error")); - } - }); - } - else { - LOG.info(failedMessage); + + final Map toUpdate = new HashMap(); + final IdeaPluginDescriptor[] installedPlugins = PluginManager.getPlugins(); + for (IdeaPluginDescriptor installedPlugin : installedPlugins) { + if (!installedPlugin.isBundled() && ((IdeaPluginDescriptorImpl)installedPlugin).isEnabled()) { + toUpdate.put(installedPlugin.getPluginId().getIdString(), installedPlugin); } } + + if (!toUpdate.isEmpty()) { + try { + final ArrayList process = RepositoryHelper.process(null); + for (IdeaPluginDescriptor loadedPlugin : process) { + final String idString = loadedPlugin.getPluginId().getIdString(); + final IdeaPluginDescriptor installedPlugin = toUpdate.get(idString); + if (installedPlugin != null) { + if (StringUtil.compareVersionNumbers(loadedPlugin.getVersion(), installedPlugin.getVersion()) > 0) { + final PluginDownloader downloader = PluginDownloader.createDownloader(loadedPlugin); + if (downloader.prepareToInstall()) { + downloaded.add(downloader); + } + } + } + } + } + catch (Exception e) { + showErrorMessage(showErrorDialog, e.getMessage()); + } + } + + if (!failed.isEmpty()) { + showErrorMessage(showErrorDialog, IdeBundle.message("connection.failed.message", StringUtil.join(failed, ","))); + } return downloaded.isEmpty() ? null : downloaded; } + private static void showErrorMessage(boolean showErrorDialog, final String failedMessage) { + if (showErrorDialog) { + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + Messages.showErrorDialog(failedMessage, IdeBundle.message("title.connection.error")); + } + }); + } + else { + LOG.info(failedMessage); + } + } + private static List getPluginHosts(@Nullable UpdateSettingsConfigurable settingsConfigurable) { final ArrayList hosts = new ArrayList(); if (settingsConfigurable != null) { diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java b/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java index 3cf8d86702f4..c0c8e983517a 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java @@ -26,7 +26,6 @@ import com.intellij.ui.mac.foundation.Foundation; import com.intellij.ui.mac.foundation.ID; import com.intellij.ui.mac.foundation.MacUtil; import com.sun.jna.Callback; -import com.sun.jna.Pointer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -130,7 +129,7 @@ public class MacFileChooserDialogImpl implements MacFileChooserDialog { public void callback(ID self, String selector, ID toSelect) { final ID chooser = invoke("NSOpenPanel", "openPanel"); - invoke(chooser, "setPrompt:", Foundation.cfString("Choose")); + invoke(chooser, "setPrompt:", Foundation.nsString("Choose")); invoke(chooser, "setCanChooseFiles:", myChooserDescriptor.isChooseFiles()); invoke(chooser, "setCanChooseDirectories:", myChooserDescriptor.isChooseFolders()); invoke(chooser, "setAllowsMultipleSelection:", myChooserDescriptor.isChooseMultiple()); @@ -152,8 +151,8 @@ public class MacFileChooserDialogImpl implements MacFileChooserDialog { invoke(chooser, "setDelegate:", self); - Object directory = null; - Object file = null; + ID directory = null; + ID file = null; final String toSelectPath = toSelect == null || toSelect.intValue() == 0 ? null : Foundation.toStringViaUTF8(toSelect); final VirtualFile toSelectFile = toSelectPath == null ? null : LocalFileSystem.getInstance().findFileByPath(toSelectPath); if (toSelectFile != null) { @@ -161,8 +160,8 @@ public class MacFileChooserDialogImpl implements MacFileChooserDialog { directory = toSelect; } else { - directory = Foundation.cfString(toSelectFile.getParent().getPath()); - file = Foundation.cfString(toSelectFile.getName()); + directory = Foundation.nsString(toSelectFile.getParent().getPath()); + file = Foundation.nsString(toSelectFile.getName()); } } @@ -181,6 +180,14 @@ public class MacFileChooserDialogImpl implements MacFileChooserDialog { if (focusedWindow != null) { invoke(chooser, "beginSheetForDirectory:file:types:modalForWindow:modalDelegate:didEndSelector:contextInfo:", directory, file, null, focusedWindow, self, Foundation.createSelector("openPanelDidEnd:returnCode:contextInfo:"), null); + + if (directory != null) { + Foundation.cfRelease(directory); + } + + if (file != null) { + Foundation.cfRelease(file); + } } } } @@ -265,7 +272,7 @@ public class MacFileChooserDialogImpl implements MacFileChooserDialog { try { final ID delegate = invoke(Foundation.getClass("NSOpenPanelDelegate_"), "new"); - final Pointer select = toSelect == null ? null : Foundation.cfString(toSelect.getPath()); + final ID select = toSelect == null ? null : Foundation.nsString(toSelect.getPath()); Foundation.cfRetain(delegate); invoke(delegate, "performSelectorOnMainThread:withObject:waitUntilDone:", Foundation.createSelector("showOpenPanel:"), select, false); @@ -281,7 +288,7 @@ public class MacFileChooserDialogImpl implements MacFileChooserDialog { try { final ID delegate = invoke(Foundation.getClass("NSOpenPanelDelegate_"), "new"); - final Pointer select = toSelect == null ? null : Foundation.cfString(toSelect.getPath()); + final ID select = toSelect == null ? null : Foundation.nsString(toSelect.getPath()); Foundation.cfRetain(delegate); invoke(delegate, "performSelectorOnMainThread:withObject:waitUntilDone:", Foundation.createSelector("showOpenPanel:"), select, false); diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java b/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java index 489d108879dd..9f582883ea73 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/MacMainFrameDecorator.java @@ -177,18 +177,18 @@ public class MacMainFrameDecorator implements UISettingsListener, Disposable { ID delegate = invoke(invoke("IdeaNSWindowDelegate" + v, "alloc"), "init"); invoke(notificationCenter, "addObserver:selector:name:object:", delegate, Foundation.createSelector("windowDidEnterFullScreen:"), - Foundation.cfString("NSWindowDidEnterFullScreenNotification"), window); + Foundation.nsString("NSWindowDidEnterFullScreenNotification"), window); //invoke(notificationCenter, "addObserver:selector:name:object:", delegate, // Foundation.createSelector("windowDidExitFullScreen:"), - // Foundation.cfString("NSWindowDidExitFullScreenNotification"), window); + // Foundation.nsString("NSWindowDidExitFullScreenNotification"), window); } else { // toggle toolbar String className = "IdeaToolbar" + v; final ID ownToolbar = Foundation.registerObjcClass(Foundation.getClass("NSToolbar"), className); Foundation.registerObjcClassPair(ownToolbar); - ID toolbar = invoke(invoke(className, "alloc"), "initWithIdentifier:", Foundation.cfString(className)); + ID toolbar = invoke(invoke(className, "alloc"), "initWithIdentifier:", Foundation.nsString(className)); Foundation.cfRetain(toolbar); invoke(toolbar, "setVisible:", 0); // hide native toolbar by default diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacMessagesImpl.java b/platform/platform-impl/src/com/intellij/ui/mac/MacMessagesImpl.java index eb20198fdf0c..641f7a1dc76a 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/MacMessagesImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/MacMessagesImpl.java @@ -158,7 +158,7 @@ public class MacMessagesImpl extends MacMessages { // it is impossible to override ESCAPE key behavior -> key should be named "Cancel" to be bound to ESC //if (!alternateExist) { - //invoke(invoke(invoke(alert, "buttons"), "objectAtIndex:", 1), "setKeyEquivalent:", cfString("\\e")); + //invoke(invoke(invoke(alert, "buttons"), "objectAtIndex:", 1), "setKeyEquivalent:", nsString("\\e")); //} String doNotAsk = toStringViaUTF8(doNotAskText); @@ -263,19 +263,21 @@ public class MacMessagesImpl extends MacMessages { final ID buttonsArray = invoke("NSMutableArray", "array"); for (String s : buttons) { - invoke(buttonsArray, "addObject:", cfString(UIUtil.removeMnemonic(s))); + ID s1 = nsString(UIUtil.removeMnemonic(s)); + invoke(buttonsArray, "addObject:", s); + cfRelease(s1); } - ID paramsArray = invoke("NSArray", "arrayWithObjects:", cfString(title), + ID paramsArray = invoke("NSArray", "arrayWithObjects:", nsString(title), // replace % -> %% to avoid formatted parameters (causes SIGTERM) - cfString(StringUtil.stripHtml(message, true).replace("%", "%%")), - focusedWindow, cfString(fakeTitle), cfString(errorStyle ? "error" : "-1"), - cfString(doNotAskDialogOption == null || !doNotAskDialogOption.canBeHidden() + nsString(StringUtil.stripHtml(message, true).replace("%", "%%")), + focusedWindow, nsString(fakeTitle), nsString(errorStyle ? "error" : "-1"), + nsString(doNotAskDialogOption == null || !doNotAskDialogOption.canBeHidden() // TODO: state=!doNotAsk.shouldBeShown() ? "-1" : doNotAskDialogOption.getDoNotShowMessage()), - cfString(Integer.toString(defaultOptionIndex)), - cfString(Integer.toString(focusedOptionIndex)), buttonsArray, null); + nsString(Integer.toString(defaultOptionIndex)), + nsString(Integer.toString(focusedOptionIndex)), buttonsArray, null); IdeFocusManager.getGlobalInstance().setTypeaheadEnabled(false); @@ -427,13 +429,13 @@ public class MacMessagesImpl extends MacMessages { fakeTitle = String.format("MacSheetDialog-%d", delegate.intValue()); - ID paramsArray = invoke("NSArray", "arrayWithObjects:", cfString(title), cfString(UIUtil.removeMnemonic(defaultText)), - cfString(otherText == null ? "-1" : UIUtil.removeMnemonic(otherText)), - cfString(alternateText == null ? "-1" : UIUtil.removeMnemonic(alternateText)), + ID paramsArray = invoke("NSArray", "arrayWithObjects:", nsString(title), nsString(UIUtil.removeMnemonic(defaultText)), + nsString(otherText == null ? "-1" : UIUtil.removeMnemonic(otherText)), + nsString(alternateText == null ? "-1" : UIUtil.removeMnemonic(alternateText)), // replace % -> %% to avoid formatted parameters (causes SIGTERM) - cfString(StringUtil.stripHtml(message, true).replace("%", "%%")), - focusedWindow, cfString(fakeTitle), cfString(errorStyle ? "error" : "-1"), - cfString(doNotAskDialogOption == null || !doNotAskDialogOption.canBeHidden() + nsString(StringUtil.stripHtml(message, true).replace("%", "%%")), + focusedWindow, nsString(fakeTitle), nsString(errorStyle ? "error" : "-1"), + nsString(doNotAskDialogOption == null || !doNotAskDialogOption.canBeHidden() // TODO: state=!doNotAsk.shouldBeShown() ? "-1" : doNotAskDialogOption.getDoNotShowMessage()), null); diff --git a/platform/platform-impl/src/com/intellij/ui/mac/growl/Growl.java b/platform/platform-impl/src/com/intellij/ui/mac/growl/Growl.java index 8198247e6c02..df4a5d97bf20 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/growl/Growl.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/growl/Growl.java @@ -55,7 +55,7 @@ public class Growl { new Object[]{myProductName, applicationIcon, defaultNotifications, allNotifications}); final ID center = invoke("NSDistributedNotificationCenter", "defaultCenter"); - final Object notificationName = Foundation.cfString(GROWL_APPLICATION_REGISTRATION_NOTIFICATION); + final Object notificationName = Foundation.nsString(GROWL_APPLICATION_REGISTRATION_NOTIFICATION); invoke(center, "postNotificationName:object:userInfo:deliverImmediately:", notificationName, null, userDict, true); invoke(autoReleasePool, "release"); } @@ -66,7 +66,7 @@ public class Growl { GROWL_NOTIFICATION_NAME, GROWL_NOTIFICATION_TITLE, GROWL_NOTIFICATION_DESCRIPTION, GROWL_APP_NAME}, new Object[]{notification, title, description, myProductName}); final ID center = invoke("NSDistributedNotificationCenter", "defaultCenter"); - final Object notificationName = Foundation.cfString(GROWL_NOTIFICATION); + final Object notificationName = Foundation.nsString(GROWL_NOTIFICATION); invoke(center, "postNotificationName:object:userInfo:deliverImmediately:", notificationName, null, dict, true); invoke(autoReleasePool, "release"); @@ -104,7 +104,7 @@ public class Growl { if (o instanceof Pointer || o instanceof ID) { return o; } else if (o instanceof String) { - return Foundation.cfString((String) o); + return Foundation.nsString((String)o); } else { throw new IllegalArgumentException("Unsupported type! " + o.getClass()); } diff --git a/platform/platform-impl/src/com/intellij/util/ui/table/JBListTable.java b/platform/platform-impl/src/com/intellij/util/ui/table/JBListTable.java index 743f7b2d6bb5..b6f16504ef0b 100644 --- a/platform/platform-impl/src/com/intellij/util/ui/table/JBListTable.java +++ b/platform/platform-impl/src/com/intellij/util/ui/table/JBListTable.java @@ -28,11 +28,10 @@ import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; import java.awt.*; import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; import java.util.List; -import static java.awt.event.KeyEvent.KEY_PRESSED; -import static java.awt.event.KeyEvent.VK_ENTER; -import static java.awt.event.KeyEvent.VK_TAB; +import static java.awt.event.KeyEvent.*; /** * @author Konstantin Bulenkov @@ -56,8 +55,11 @@ public abstract class JBListTable extends JPanel { } }; mainTable = new JBTable(model) { + private MouseEvent myMouseEvent; @Override protected void processKeyEvent(KeyEvent e) { + myMouseEvent = null; + if (e.isAltDown()) return; //todo[kb] JBTabsImpl breaks focus traversal policy. Need a workaround here if (e.getKeyCode() == VK_TAB) { @@ -76,6 +78,12 @@ public abstract class JBListTable extends JPanel { super.processKeyEvent(e); } + @Override + protected void processMouseEvent(MouseEvent e) { + myMouseEvent = e; + super.processMouseEvent(e); + } + @Override public TableCellRenderer getCellRenderer(int row, int column) { return new DefaultTableCellRenderer() { @@ -144,6 +152,7 @@ public abstract class JBListTable extends JPanel { public TableCellEditor getCellEditor(final int row, int column) { final JBTableRowEditor editor = getRowEditor(row); if (editor != null) { + editor.setMouseEvent(myMouseEvent); editor.prepareEditor(t, row); installPaddingAndBordersForEditors(editor); editor.setFocusCycleRoot(true); diff --git a/platform/platform-impl/src/com/intellij/util/ui/table/JBTableRowEditor.java b/platform/platform-impl/src/com/intellij/util/ui/table/JBTableRowEditor.java index 765a9862feef..c2d7f79a1ae8 100644 --- a/platform/platform-impl/src/com/intellij/util/ui/table/JBTableRowEditor.java +++ b/platform/platform-impl/src/com/intellij/util/ui/table/JBTableRowEditor.java @@ -16,13 +16,17 @@ package com.intellij.util.ui.table; import com.intellij.openapi.wm.IdeFocusManager; +import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.awt.event.MouseEvent; /** * @author Konstantin Bulenkov */ public abstract class JBTableRowEditor extends JPanel { + private MouseEvent myMouseEvent; + @Override public void addNotify() { super.addNotify(); @@ -32,6 +36,15 @@ public abstract class JBTableRowEditor extends JPanel { } } + @Nullable + public final MouseEvent getMouseEvent() { + return myMouseEvent; + } + + public final void setMouseEvent(@Nullable MouseEvent e) { + myMouseEvent = e; + } + public abstract void prepareEditor(JTable table, int row); public abstract JBTableRow getValue(); public abstract JComponent getPreferredFocusedComponent(); diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties index 6c8d557c18f8..4283073fc9b4 100644 --- a/platform/platform-resources-en/src/misc/registry.properties +++ b/platform/platform-resources-en/src/misc/registry.properties @@ -148,3 +148,5 @@ ide.enable.toolwindow.stack=false change.signature.awesome.mode=true change.signature.awesome.mode.description=Enables list view for change signature +navbar.is.decorated=false +navbar.is.decorated.description=NavBar with decorations diff --git a/platform/platform-resources/src/idea/Keymap_Mac.xml b/platform/platform-resources/src/idea/Keymap_Mac.xml index 2f82b8830f3a..3584b0f4c715 100644 --- a/platform/platform-resources/src/idea/Keymap_Mac.xml +++ b/platform/platform-resources/src/idea/Keymap_Mac.xml @@ -389,6 +389,7 @@ + diff --git a/platform/util/src/com/intellij/openapi/util/TextRange.java b/platform/util/src/com/intellij/openapi/util/TextRange.java index b59c248208bf..74abaaebcd8c 100644 --- a/platform/util/src/com/intellij/openapi/util/TextRange.java +++ b/platform/util/src/com/intellij/openapi/util/TextRange.java @@ -18,7 +18,9 @@ package com.intellij.openapi.util; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class TextRange implements Segment{ +import java.io.Serializable; + +public class TextRange implements Segment, Serializable { public static final TextRange EMPTY_RANGE = new TextRange(0,0); private final int myStartOffset; private final int myEndOffset; diff --git a/platform/util/src/com/intellij/ui/mac/foundation/Foundation.java b/platform/util/src/com/intellij/ui/mac/foundation/Foundation.java index ea7063f0a24d..4ead26f95b10 100644 --- a/platform/util/src/com/intellij/ui/mac/foundation/Foundation.java +++ b/platform/util/src/com/intellij/ui/mac/foundation/Foundation.java @@ -128,7 +128,7 @@ public class Foundation { public static boolean isPackageAtPath(@NotNull final String path) { final ID workspace = invoke("NSWorkspace", "sharedWorkspace"); - final ID result = invoke(workspace, createSelector("isFilePackageAtPath:"), cfString(path)); + final ID result = invoke(workspace, createSelector("isFilePackageAtPath:"), nsString(path)); return result.intValue() == 1; } @@ -138,18 +138,17 @@ public class Foundation { return isPackageAtPath(file.getPath()); } - /** - * Return a CFString as an ID, toll-free bridged to NSString. - *

- * Note that the returned string must be freed with {@link #cfRelease(ID)}. - */ - public static Pointer cfString(String s) { + public static ID nsString(String s) { // Use a byte[] rather than letting jna do the String -> char* marshalling itself. // Turns out about 10% quicker for long strings. try { + if (s.length() == 0) { + return invoke("NSString", "string"); + } + byte[] utf16Bytes = s.getBytes("UTF-16LE"); - return myFoundationLibrary.CFStringCreateWithBytes(null, utf16Bytes, utf16Bytes.length, FoundationLibrary.kCFStringEncodingUTF16LE, - (byte)0); /* kTextEncodingUnicodeDefault + kUnicodeUTF16LEFormat */ + return invoke(invoke("NSString", "alloc"), "initWithBytes:length:encoding:", utf16Bytes, utf16Bytes.length, + myFoundationLibrary.CFStringConvertEncodingToNSStringEncoding(FoundationLibrary.kCFStringEncodingUTF16LE)); } catch (UnsupportedEncodingException x) { throw new RuntimeException(x); @@ -179,7 +178,7 @@ public class Foundation { public static long getEncodingCode(@Nullable String encodingName) { if (StringUtil.isEmptyOrSpaces(encodingName)) return -1; - Pointer converted = cfString(encodingName); + ID converted = nsString(encodingName); int cfEncoding = myFoundationLibrary.CFStringConvertIANACharSetNameToEncoding(converted); if (cfEncoding == FoundationLibrary.kCFStringEncodingInvalidId) return -1; @@ -190,8 +189,10 @@ public class Foundation { myFoundationLibrary.CFRetain(id); } - public static void cfRelease(ID id) { - myFoundationLibrary.CFRelease(id); + public static void cfRelease(ID... id) { + for (ID id1 : id) { + myFoundationLibrary.CFRelease(id1); + } } public static boolean isMainThread() { @@ -223,7 +224,7 @@ public class Foundation { final ID ideaRunnable = getClass("IdeaRunnable"); final ID runnableObject = invoke(invoke(ideaRunnable, "alloc"), "init"); invoke(runnableObject, "performSelectorOnMainThread:withObject:waitUntilDone:", createSelector("run:"), - cfString(String.valueOf(ourCurrentRunnableCount)), Boolean.valueOf(waitUntilDone)); + nsString(String.valueOf(ourCurrentRunnableCount)), Boolean.valueOf(waitUntilDone)); invoke(runnableObject, "release"); } diff --git a/platform/util/src/com/intellij/ui/mac/foundation/FoundationLibrary.java b/platform/util/src/com/intellij/ui/mac/foundation/FoundationLibrary.java index 6e82289fb5c5..1d2665fe94b8 100644 --- a/platform/util/src/com/intellij/ui/mac/foundation/FoundationLibrary.java +++ b/platform/util/src/com/intellij/ui/mac/foundation/FoundationLibrary.java @@ -30,14 +30,14 @@ public interface FoundationLibrary extends Library { ID objc_allocateClassPair(ID supercls, String name, int extraBytes); void objc_registerClassPair(ID cls); - Pointer CFStringCreateWithBytes(Pointer allocator, byte[] bytes, int byteCount, int encoding, byte isExternalRepresentation); + ID CFStringCreateWithBytes(Pointer allocator, byte[] bytes, int byteCount, int encoding, byte isExternalRepresentation); byte CFStringGetCString(ID theString, byte[] buffer, int bufferSize, int encoding); int CFStringGetLength(ID theString); int CFStringConvertNSStringEncodingToEncoding(long nsEncoding); ID CFStringConvertEncodingToIANACharSetName(int cfEncoding); - int CFStringConvertIANACharSetNameToEncoding(Pointer encodingName); + int CFStringConvertIANACharSetNameToEncoding(ID encodingName); long CFStringConvertEncodingToNSStringEncoding(int cfEncoding); void CFRetain(ID cfTypeRef); diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java index 08c94b60d0e1..82b1f63e7018 100644 --- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java +++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java @@ -19,7 +19,9 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Factory; +import com.intellij.openapi.util.Pair; import com.intellij.util.*; +import gnu.trove.THashMap; import gnu.trove.TIntArrayList; import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; @@ -275,6 +277,22 @@ public class ContainerUtil { return set; } + @NotNull + public static Map map2Map(@NotNull T[] collection, @NotNull Function> mapper) { + return map2Map(Arrays.asList(collection), mapper); + } + + @NotNull + public static Map map2Map(@NotNull Collection collection, + @NotNull Function> mapper) { + final Map set = new THashMap(collection.size()); + for (T t : collection) { + Pair pair = mapper.fun(t); + set.put(pair.first, pair.second); + } + return set; + } + @NotNull public static Object[] map2Array(@NotNull T[] array, @NotNull Function mapper) { return map2Array(array, Object.class, mapper); diff --git a/platform/util/src/com/intellij/util/containers/MostlySingularMultiMap.java b/platform/util/src/com/intellij/util/containers/MostlySingularMultiMap.java index 41f04e3b4721..c6848b3bdec1 100644 --- a/platform/util/src/com/intellij/util/containers/MostlySingularMultiMap.java +++ b/platform/util/src/com/intellij/util/containers/MostlySingularMultiMap.java @@ -23,12 +23,13 @@ import com.intellij.util.Processor; import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; +import java.io.Serializable; import java.util.Arrays; import java.util.Collections; import java.util.Map; import java.util.Set; -public class MostlySingularMultiMap { +public class MostlySingularMultiMap implements Serializable { private final Map myMap = new THashMap(); public void add(K key, V value) { diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties index 1b53e95c6678..cb454a9c8ba4 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties @@ -1623,9 +1623,8 @@ increment.decrement.used.as.expression.quickfix=Extract ''{0}'' to separate stat ignore.classes.in.hierarchy.column.name=Ignore subclasses of overly.strong.type.cast.ignore.in.matching.instanceof.option=Ignore casts with a matching instanceof expression return.of.collection.field.quickfix=Replace with ''{0}'' -access.to.non.thread.safe.static.field.from.instance.display.name=Access to non thread-safe static field from instance -access.to.non.thread.safe.static.field.from.instance.field.problem.descriptor=Access to static ''{0}'' field #ref from instance field initializer #loc -access.to.non.thread.safe.static.field.from.instance.method.problem.descriptor=Access to static ''{0}'' field #ref from instance method #loc +access.to.non.thread.safe.static.field.from.instance.display.name=Non thread-safe static field access +access.to.non.thread.safe.static.field.from.instance.field.problem.descriptor=Access to non thread-safe static field #ref of type ''{0}'' #loc access.to.non.thread.safe.static.field.from.instance.option.title=Non thread safe classes access.to.non.thread.safe.static.field.from.instance.class.chooser.title=Choose non thread safe class non.thread.safe.types.column.name=Non Thread-safe Types diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/IgnoredJUnitTestInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/IgnoredJUnitTestInspection.java index 0a1359ca5c96..0fd2edb58640 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/IgnoredJUnitTestInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/IgnoredJUnitTestInspection.java @@ -21,6 +21,7 @@ import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; public class IgnoredJUnitTestInspection extends BaseInspection { @@ -62,7 +63,6 @@ public class IgnoredJUnitTestInspection extends BaseInspection { PsiModifierListOwner.class); if (!(modifierListOwner instanceof PsiClass || modifierListOwner instanceof PsiMethod)) { - System.out.println(1); return; } final PsiJavaCodeReferenceElement nameReferenceElement = @@ -72,11 +72,10 @@ public class IgnoredJUnitTestInspection extends BaseInspection { } final PsiElement target = nameReferenceElement.resolve(); if (!(target instanceof PsiClass)) { - System.out.println(2); return; } final PsiClass aClass = (PsiClass) target; - final String qualifiedName = aClass.getQualifiedName(); + @NonNls final String qualifiedName = aClass.getQualifiedName(); if (!"org.junit.Ignore".equals(qualifiedName)) { return; } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/JUnit4AnnotatedMethodInJUnit3TestCaseInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/JUnit4AnnotatedMethodInJUnit3TestCaseInspection.java index fd9b4b845149..6124e43ecdd2 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/JUnit4AnnotatedMethodInJUnit3TestCaseInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/JUnit4AnnotatedMethodInJUnit3TestCaseInspection.java @@ -196,18 +196,18 @@ public class JUnit4AnnotatedMethodInJUnit3TestCaseInspection extends @Override public void visitMethod(PsiMethod method) { super.visitMethod(method); - if (AnnotationUtil.isAnnotated(method, IGNORE, false) && method.getName().startsWith("test")) { - registerMethodError(method, method); - return; - } - if (!TestUtils.isJUnit4TestMethod(method)) { - return; - } final PsiClass containingClass = method.getContainingClass(); if (containingClass == null) { - return; + return; } if (!TestUtils.isJUnitTestClass(containingClass)) { + return; + } + if (AnnotationUtil.isAnnotated(method, IGNORE, false) && method.getName().startsWith("test")) { + registerMethodError(method, method); + return; + } + if (!TestUtils.isJUnit4TestMethod(method)) { return; } final String className = containingClass.getName(); diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/CollectionsFieldAccessReplaceableByMethodCallInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/CollectionsFieldAccessReplaceableByMethodCallInspection.java index 5390fe0d939c..46ef89df3fbe 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/CollectionsFieldAccessReplaceableByMethodCallInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/CollectionsFieldAccessReplaceableByMethodCallInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2010 Bas Leijdekkers + * Copyright 2008-2011 Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -95,16 +95,30 @@ public class CollectionsFieldAccessReplaceableByMethodCallInspection for (int i = 0, parameterTypesLength = parameterTypes.length; i < parameterTypesLength; i++) { final PsiType parameterType = parameterTypes[i]; - if (!parameterType.equalsToText( - CommonClassNames.JAVA_LANG_OBJECT)) { - useTypeParameter = true; + if (parameterType instanceof PsiWildcardType) { + final PsiWildcardType wildcardType = + (PsiWildcardType)parameterType; + final PsiType bound = wildcardType.getBound(); + if (bound != null) { + if (!bound.equalsToText( + CommonClassNames.JAVA_LANG_OBJECT)) { + useTypeParameter = true; + } + canonicalTexts[i] = bound.getCanonicalText(); + } else { + canonicalTexts[i] = CommonClassNames.JAVA_LANG_OBJECT; + } + } else { + if (!parameterType.equalsToText( + CommonClassNames.JAVA_LANG_OBJECT)) { + useTypeParameter = true; + } + canonicalTexts[i] = parameterType.getCanonicalText(); } - canonicalTexts[i] = parameterType.getCanonicalText(); } if (useTypeParameter) { return "Collections.<" + StringUtil.join(canonicalTexts, ",") + - '>' + - getCollectionsMethodCallText(referenceName); + '>' + getCollectionsMethodCallText(referenceName); } else { return getUntypedCollectionsMethodCallText(referenceName); } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/threading/AccessToNonThreadSafeStaticFieldFromInstanceInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/threading/AccessToNonThreadSafeStaticFieldFromInstanceInspection.java index 8a22d6d5ec63..493ffc9c12bf 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/threading/AccessToNonThreadSafeStaticFieldFromInstanceInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/threading/AccessToNonThreadSafeStaticFieldFromInstanceInspection.java @@ -55,6 +55,12 @@ public class AccessToNonThreadSafeStaticFieldFromInstanceInspection } } + @NotNull + @Override + public String getID() { + return "AccessToNonThreadSafeStaticField"; + } + @Override @Nls @NotNull @@ -66,16 +72,11 @@ public class AccessToNonThreadSafeStaticFieldFromInstanceInspection @Override @NotNull protected String buildErrorString(Object... infos) { - if (infos[0] instanceof PsiMethod) { - return InspectionGadgetsBundle.message( - "access.to.non.thread.safe.static.field.from.instance.method.problem.descriptor", - infos[1]); - } return InspectionGadgetsBundle.message( "access.to.non.thread.safe.static.field.from.instance.field.problem.descriptor", - infos[1]); + infos[0]); } - + @Override @Nullable public JComponent createOptionsPanel() { @@ -104,9 +105,6 @@ public class AccessToNonThreadSafeStaticFieldFromInstanceInspection if (parent == null) { return; } - if (parent.hasModifierProperty(PsiModifier.STATIC)) { - return; - } if (parent instanceof PsiMethod || parent instanceof PsiClassInitializer) { if (parent.hasModifierProperty(PsiModifier.SYNCHRONIZED)) { @@ -140,7 +138,7 @@ public class AccessToNonThreadSafeStaticFieldFromInstanceInspection if (!field.hasModifierProperty(PsiModifier.STATIC)) { return; } - registerError(expression, parent, className); + registerError(expression, className); } } } \ No newline at end of file diff --git a/plugins/android/resources/messages/AndroidBundle.properties b/plugins/android/resources/messages/AndroidBundle.properties index 69366cf7a604..c73254c75de9 100644 --- a/plugins/android/resources/messages/AndroidBundle.properties +++ b/plugins/android/resources/messages/AndroidBundle.properties @@ -111,7 +111,7 @@ android.project.contains.errors.error=The project contains errors android.export.package.existing.keystore.label=&Use existing keystore android.export.package.new.keystore.label=&Create new keystore android.export.package.keystore.location.label=&Location: -android.password.label=&Password: +android.password.label=Pa&ssword: android.confirm.password.label=&Confirm: android.export.package.passwords.not.match.error=Passwords do not match android.export.package.specify.keystore.location.error=Please specify keystore location @@ -129,7 +129,7 @@ android.export.package.key.validity.label=&Validity (years): android.export.package.key.certificate.name.label=&First and Last Name: android.export.package.organization.unit.label=&Organizational Unit: android.export.package.city.label=City or &Locality: -android.export.package.state.label=&State or Province: +android.export.package.state.label=S&tate or Province: android.export.package.country.code.label=Country Code (&XX): android.export.package.specify.key.alias.error=Please specify key alias android.export.package.specify.certificate.field.error=At least one Certificate issuer field is required to be non-empty @@ -222,10 +222,10 @@ android.facet.compiler.settings.manifest.title=Manifest android.facet.settings.compiler.manifest.from.structure=Use AndroidManifest.xml file specified at "Structure" section android.facet.settings.compiler.manifest.use.custom=Use custom manifest file: android.facet.settings.compile.resources.by.ide=&Compile resources by IDE -android.keystore.password.label=&Password: +android.keystore.password.label=Pa&ssword: android.keystore.confirm.password.label=C&onfirm: android.export.package.new.key.alias.label=&Alias: -android.key.password.label=&Password: +android.key.password.label=Pa&ssword: android.cannot.run.library.project.error=The module cannot be Android library project android.compilation.error.specify.platform=Android SDK is not specified for module {0} android.compilation.error.manifest.not.found=AndroidManifest.xml file not found. Please, check Android facet settings. diff --git a/plugins/android/src/org/jetbrains/android/actions/CreateTypedResourceFileAction.java b/plugins/android/src/org/jetbrains/android/actions/CreateTypedResourceFileAction.java index 068630439066..cb4b9e192a5d 100644 --- a/plugins/android/src/org/jetbrains/android/actions/CreateTypedResourceFileAction.java +++ b/plugins/android/src/org/jetbrains/android/actions/CreateTypedResourceFileAction.java @@ -140,14 +140,18 @@ public class CreateTypedResourceFileAction extends CreateElementActionBase { protected boolean isAvailable(DataContext context) { if (!super.isAvailable(context)) return false; final PsiElement element = (PsiElement)context.getData(DataKeys.PSI_ELEMENT.getName()); - if (element instanceof PsiDirectory) { - return ApplicationManager.getApplication().runReadAction(new Computable() { - public Boolean compute() { - return ResourceManager.isResourceSubdirectory((PsiDirectory)element, myResourceType); + return ApplicationManager.getApplication().runReadAction(new Computable() { + public Boolean compute() { + PsiElement e = element; + while (e != null) { + if (e instanceof PsiDirectory && ResourceManager.isResourceSubdirectory((PsiDirectory)e, myResourceType)) { + return true; + } + e = e.getParent(); } - }); - } - return false; + return false; + } + }); } @Override diff --git a/plugins/android/src/org/jetbrains/android/uipreview/AndroidLayoutPreviewPanel.java b/plugins/android/src/org/jetbrains/android/uipreview/AndroidLayoutPreviewPanel.java index aec79515f7e1..131cdd944ffb 100644 --- a/plugins/android/src/org/jetbrains/android/uipreview/AndroidLayoutPreviewPanel.java +++ b/plugins/android/src/org/jetbrains/android/uipreview/AndroidLayoutPreviewPanel.java @@ -1,9 +1,12 @@ package org.jetbrains.android.uipreview; + import com.intellij.openapi.Disposable; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.VerticalFlowLayout; + import com.intellij.openapi.util.Disposer; import com.intellij.ui.HyperlinkLabel; import com.intellij.ui.components.JBLabel; + import com.intellij.util.ui.AsyncProcessIcon; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -15,7 +18,7 @@ /** * @author Eugene.Kudelevsky */ -public class AndroidLayoutPreviewPanel extends JPanel { +public class AndroidLayoutPreviewPanel extends JPanel implements Disposable { private static final double EPS = 0.0000001; private static final double MAX_ZOOM_FACTOR = 2.0; private static final double ZOOM_STEP = 1.25; @@ -23,7 +26,6 @@ public class AndroidLayoutPreviewPanel extends JPanel { private RenderingErrorMessage myErrorMessage; private String myWarnMessage; private BufferedImage myImage; - private JBLabel myProgressLabel; private final HyperlinkLabel myErrorLabel = new HyperlinkLabel("", Color.BLUE, getBackground(), Color.BLUE); @@ -46,6 +48,8 @@ public class AndroidLayoutPreviewPanel extends JPanel { } }; + private AsyncProcessIcon myProgressIcon; + public AndroidLayoutPreviewPanel() { super(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, true)); setBackground(Color.WHITE); @@ -62,12 +66,18 @@ public class AndroidLayoutPreviewPanel extends JPanel { }); myErrorLabel.setOpaque(false); - myProgressLabel = new JBLabel("Rendering..."); - myProgressLabel.setIcon(Messages.getInformationIcon()); - myProgressLabel.setVisible(false); + final JPanel progressPanel = new JPanel(); + progressPanel.setLayout(new BoxLayout(progressPanel, BoxLayout.X_AXIS)); + myProgressIcon = new AsyncProcessIcon("Android layout rendering"); + Disposer.register(this, myProgressIcon); + progressPanel.add(Box.createHorizontalGlue()); + progressPanel.add(myProgressIcon); + progressPanel.add(new JBLabel(" ")); + progressPanel.setOpaque(false); + myProgressIcon.setVisible(false); + add(progressPanel); add(myErrorLabel); - add(myProgressLabel); add(new MyImagePanelWrapper()); } @@ -77,14 +87,13 @@ public class AndroidLayoutPreviewPanel extends JPanel { } public void showProgress() { - myProgressLabel.setVisible(true); - myErrorLabel.setVisible(false); - myImagePanel.setVisible(false); + myProgressIcon.setVisible(true); + myProgressIcon.resume(); } - @Nullable - public BufferedImage getImage() { - return myImage; + public void hideProgress() { + myProgressIcon.suspend(); + myProgressIcon.setVisible(false); } private void doRevalidate() { @@ -102,7 +111,6 @@ public class AndroidLayoutPreviewPanel extends JPanel { } public void update() { - myProgressLabel.setVisible(false); myImagePanel.setVisible(true); if (myErrorMessage != null) { myErrorLabel.setHyperlinkText(myErrorMessage.myBeforeLinkText, @@ -218,6 +226,10 @@ public class AndroidLayoutPreviewPanel extends JPanel { return myZoomToFit; } + @Override + public void dispose() { + } + private class MyImagePanelWrapper extends JLayeredPane { public MyImagePanelWrapper() { add(myImagePanel); diff --git a/plugins/android/src/org/jetbrains/android/uipreview/AndroidLayoutPreviewToolWindowForm.java b/plugins/android/src/org/jetbrains/android/uipreview/AndroidLayoutPreviewToolWindowForm.java index 887d002f93fb..49cf5ce55357 100644 --- a/plugins/android/src/org/jetbrains/android/uipreview/AndroidLayoutPreviewToolWindowForm.java +++ b/plugins/android/src/org/jetbrains/android/uipreview/AndroidLayoutPreviewToolWindowForm.java @@ -5,10 +5,10 @@ import com.android.ide.common.resources.ResourceResolver; import com.android.ide.common.resources.configuration.LanguageQualifier; import com.android.ide.common.resources.configuration.RegionQualifier; import com.android.ide.common.resources.configuration.ScreenSizeQualifier; -import com.android.resources.UiMode; import com.android.resources.NightMode; import com.android.resources.ResourceType; import com.android.resources.ScreenSize; +import com.android.resources.UiMode; import com.android.sdklib.IAndroidTarget; import com.android.sdklib.SdkConstants; import com.intellij.ide.ui.ListCellRendererWrapper; @@ -23,6 +23,7 @@ import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; @@ -97,6 +98,8 @@ class AndroidLayoutPreviewToolWindowForm implements Disposable { private final AndroidLayoutPreviewToolWindowSettings mySettings; public AndroidLayoutPreviewToolWindowForm(final Project project, AndroidLayoutPreviewToolWindowManager toolWindowManager) { + Disposer.register(this, myPreviewPanel); + myToolWindowManager = toolWindowManager; mySettings = AndroidLayoutPreviewToolWindowSettings.getInstance(project); diff --git a/plugins/android/src/org/jetbrains/android/uipreview/AndroidLayoutPreviewToolWindowManager.java b/plugins/android/src/org/jetbrains/android/uipreview/AndroidLayoutPreviewToolWindowManager.java index 24aa068a2779..2b8b7cb3dbba 100644 --- a/plugins/android/src/org/jetbrains/android/uipreview/AndroidLayoutPreviewToolWindowManager.java +++ b/plugins/android/src/org/jetbrains/android/uipreview/AndroidLayoutPreviewToolWindowManager.java @@ -5,7 +5,6 @@ import com.android.sdklib.IAndroidTarget; import com.intellij.ProjectTopics; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; @@ -13,6 +12,8 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.*; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.util.ProgressIndicatorBase; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ModuleRootEvent; @@ -35,6 +36,7 @@ import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentManager; import com.intellij.util.containers.HashMap; import com.intellij.util.messages.MessageBusConnection; +import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.update.MergingUpdateQueue; import com.intellij.util.ui.update.Update; import org.jetbrains.android.dom.layout.LayoutDomFileDescription; @@ -53,6 +55,8 @@ import org.jetbrains.annotations.Nullable; import javax.imageio.ImageIO; import javax.swing.*; import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; @@ -242,15 +246,12 @@ public class AndroidLayoutPreviewToolWindowManager implements ProjectComponent { myRenderingQueue.queue(new Update("render") { @Override public void run() { - if (showProgress || myToolWindowForm.getPreviewPanel().getImage() == null) { - ApplicationManager.getApplication().invokeAndWait(new Runnable() { - @Override - public void run() { - myToolWindowForm.getPreviewPanel().showProgress(); - } - }, ModalityState.defaultModalityState()); - } - doRender(facet, layoutXmlText); + ProgressManager.getInstance().runProcess(new Runnable() { + @Override + public void run() { + doRender(facet, layoutXmlText); + } + }, new MyProgressIndicator()); } @Override @@ -355,7 +356,7 @@ public class AndroidLayoutPreviewToolWindowManager implements ProjectComponent { } }); } - + private void showStackStace(@NotNull Throwable t) { final String stackTrace = getStackTrace(t); final DialogWrapper wrapper = new DialogWrapper(myProject, false) { @@ -372,11 +373,11 @@ public class AndroidLayoutPreviewToolWindowManager implements ProjectComponent { panel.add(ScrollPaneFactory.createScrollPane(textArea)); return panel; } - }; + }; wrapper.setTitle("Stack trace"); wrapper.show(); } - + @NotNull private static String getStackTrace(@NotNull Throwable t) { final StringWriter stringWriter = new StringWriter(); @@ -517,4 +518,43 @@ public class AndroidLayoutPreviewToolWindowManager implements ProjectComponent { processFileEditorChange(layoutXmlEditor); } } + + private class MyProgressIndicator extends ProgressIndicatorBase { + private final Object myLock = new Object(); + + @Override + public void start() { + super.start(); + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + final Timer timer = UIUtil.createNamedTimer("Android rendering progress timer", 1000, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + synchronized (myLock) { + if (isRunning()) { + myToolWindowForm.getPreviewPanel().showProgress(); + } + } + } + }); + timer.setRepeats(false); + timer.start(); + } + }); + } + + @Override + public void stop() { + synchronized (myLock) { + super.stop(); + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + myToolWindowForm.getPreviewPanel().hideProgress(); + } + }); + } + } + } } diff --git a/plugins/github/src/META-INF/plugin.xml b/plugins/github/src/META-INF/plugin.xml index eefac0624e76..db65ce0b988f 100644 --- a/plugins/github/src/META-INF/plugin.xml +++ b/plugins/github/src/META-INF/plugin.xml @@ -28,6 +28,11 @@ + + + + + \ No newline at end of file diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java new file mode 100644 index 000000000000..88535b6d5bd1 --- /dev/null +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java @@ -0,0 +1,164 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.github; + +import com.intellij.ide.BrowserUtil; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.SelectionModel; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.project.DumbAwareAction; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.Ref; +import com.intellij.openapi.vfs.VirtualFile; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.methods.PostMethod; +import org.jetbrains.plugins.github.ui.GitHubCreateGistDialog; +import org.jetbrains.plugins.github.ui.GithubLoginDialog; + +import javax.swing.*; +import java.io.IOException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author oleg + * @date 9/27/11 + */ +public class GithubCreateGistAction extends DumbAwareAction { + public static final Icon ICON = IconLoader.getIcon("/icons/github.png"); + private static final Logger LOG = Logger.getInstance(GithubCreateGistAction.class); + + protected GithubCreateGistAction() { + super("Create gist", "Create github gist", ICON); + } + + @Override + public void update(final AnActionEvent e) { + final long startTime = System.nanoTime(); + try { + final Project project = e.getData(PlatformDataKeys.PROJECT); + if (project == null || project.isDefault()) { + e.getPresentation().setVisible(false); + e.getPresentation().setEnabled(false); + return; + } + final Editor editor = e.getData(PlatformDataKeys.EDITOR); + if (editor != null){ + e.getPresentation().setVisible(true); + e.getPresentation().setEnabled(true); + return; + } + e.getPresentation().setVisible(false); + e.getPresentation().setEnabled(false); + } + finally { + if (LOG.isDebugEnabled()) { + LOG.debug("GithubCreateGistAction#update finished in: " + (System.nanoTime() - startTime) / 10e6 + "ms"); + } + } + } + + @Override + public void actionPerformed(final AnActionEvent e) { + final Project project = e.getData(PlatformDataKeys.PROJECT); + if (project == null || project.isDefault()) { + return; + } + final Editor editor = e.getData(PlatformDataKeys.EDITOR); + if (editor == null){ + return; + } + final VirtualFile file = e.getData(PlatformDataKeys.VIRTUAL_FILE); + if (file == null) { + return; + } + final boolean useGitHubAccount; + if (!GithubUtil.checkCredentials(project)) { + final GithubLoginDialog dialog = new GithubLoginDialog(project); + dialog.show(); + useGitHubAccount = GithubUtil.checkCredentials(project); + } else { + useGitHubAccount = true; + } + + // Ask for description and other params + final GitHubCreateGistDialog dialog = new GitHubCreateGistDialog(project, useGitHubAccount); + dialog.show(); + if (!dialog.isOK()){ + return; + } + final GithubSettings settings = GithubSettings.getInstance(); + final String password = settings.getPassword(); + final Ref url = new Ref(); + final String description = dialog.getDescription(); + final boolean isPrivate = dialog.isPrivate(); + final boolean anonymous = dialog.isAnonimous(); + final boolean openInBrowser = dialog.isOpenInBrowser(); + + // Text + final SelectionModel selectionModel = editor.getSelectionModel(); + final String text = selectionModel.hasSelection() ? selectionModel.getSelectedText() : editor.getDocument().getText(); + + ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { + @Override + public void run() { + final HttpClient client = anonymous ? GithubUtil.getHttpClient(null, null) : GithubUtil.getHttpClient(settings.getLogin(), password); + client.getParams().setContentCharset("UTF-8"); + + final PostMethod method = new PostMethod("https://gist.github.com/gists"); + method.addParameters(new NameValuePair[]{ + new NameValuePair("description", description), + new NameValuePair("file_ext[gistfile1]", "." + file.getExtension()), + new NameValuePair("file_name[gistfile1]", file.getNameWithoutExtension()), + new NameValuePair("file_contents[gistfile1]", text) + }); + if (isPrivate){ + method.addParameter("action_button", "private"); + } + try { + client.executeMethod(method); + final String responce = method.getResponseBodyAsString(); + // TODO[oleg] fix it when github API v3 becomes public + // http://developer.github.com/v3/gists/ + final Matcher matcher = Pattern.compile("\\d+").matcher(responce); + matcher.find(); + url.set("https://gist.github.com/" + matcher.group()); + } + catch (IOException e1) { + LOG.error("Failed to create gist: " + e1); + return; + } + finally { + method.releaseConnection(); + } + } + }, "Communicating With GitHub", false, project); + if (url.isNull()){ + return; + } + if (openInBrowser) { + BrowserUtil.launchBrowser(url.get()); + } else { + Messages.showInfoMessage(project, "Your gist url: " + url.get(), "Gist Created Successfully"); + } + } +} diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java index 09f9b966a6b1..9d52901d003b 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java @@ -97,7 +97,7 @@ public class GithubOpenInBrowserAction extends DumbAwareAction { // Check that given repository is properly configured git repository - final GitRemote githubRemote = GithubUtil.getGithubBoundRepository(project); + final GitRemote githubRemote = GithubUtil.findGitHubRemoteBranch(project, project.getBaseDir()); if (githubRemote == null) { Messages.showErrorDialog(project, "Configured github repository is not found", CANNOT_OPEN_IN_BROWSER); return; diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java index 096c37202880..92dde0da0f4b 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java @@ -92,12 +92,14 @@ public class GithubRebaseAction extends DumbAwareAction { @Override public GitRemote compute() { ProgressManager.getInstance().getProgressIndicator().setText("Reading branches information"); - return GithubUtil.getGithubBoundRepository(project); + return GithubUtil.findGitHubRemoteBranch(project, project.getBaseDir()); } }); - final List gitRemotes = GitRemote.list(project, root); - LOG.assertTrue(githubRemote != null); + if (githubRemote == null){ + return; + } + final List gitRemotes = GitRemote.list(project, root); final String pushUrl = githubRemote.pushUrl(); final String login = GithubSettings.getInstance().getLogin(); final int index = pushUrl.lastIndexOf(login); diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubSettings.java b/plugins/github/src/org/jetbrains/plugins/github/GithubSettings.java index be26baa31907..a827426e67c1 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubSettings.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubSettings.java @@ -49,11 +49,18 @@ public class GithubSettings implements PersistentStateComponent { private static final String GITHUB_SETTINGS_TAG = "GithubSettings"; private static final String LOGIN = "Login"; private static final String HOST = "Host"; + private static final String ANONIMOUS_GIST = "Anonymous"; + private static final String OPEN_IN_BROWSER_GIST = "OpenInBrowser"; + private static final String PRIVATE_GIST = "Private"; private static final String GITHUB = "github.com"; private static final String GITHUB_SETTINGS_PASSWORD_KEY = "GITHUB_SETTINGS_PASSWORD_KEY"; private String myLogin; private String myHost; + private boolean myAnonymousGist; + private boolean myOpenInBrowserGist = true; + private boolean myPrivateGist; + private static final Logger LOG = Logger.getInstance(GithubSettings.class.getName()); private boolean passwordChanged = false; @@ -88,6 +95,9 @@ public class GithubSettings implements PersistentStateComponent { final Element element = new Element(GITHUB_SETTINGS_TAG); element.setAttribute(LOGIN, getLogin()); element.setAttribute(HOST, getHost()); + element.setAttribute(ANONIMOUS_GIST, String.valueOf(isAnonymous())); + element.setAttribute(PRIVATE_GIST, String.valueOf(isPrivateGist())); + element.setAttribute(OPEN_IN_BROWSER_GIST, String.valueOf(isOpenInBrowserGist())); return element; } @@ -96,6 +106,9 @@ public class GithubSettings implements PersistentStateComponent { try { setLogin(element.getAttributeValue(LOGIN)); setHost(element.getAttributeValue(HOST)); + setAnonymousGist(Boolean.valueOf(element.getAttributeValue(ANONIMOUS_GIST))); + setPrivateGist(Boolean.valueOf(element.getAttributeValue(PRIVATE_GIST))); + setOpenInBrowserGist(Boolean.valueOf(element.getAttributeValue(OPEN_IN_BROWSER_GIST))); } catch (Exception e) { LOG.error("Error happened while loading github settings: " + e); @@ -147,6 +160,18 @@ public class GithubSettings implements PersistentStateComponent { return myHost != null ? myHost : GITHUB; } + public boolean isAnonymous() { + return myAnonymousGist; + } + + public boolean isOpenInBrowserGist() { + return myOpenInBrowserGist; + } + + public boolean isPrivateGist() { + return myPrivateGist; + } + public void setLogin(final String login) { myLogin = login != null ? login : ""; } @@ -168,4 +193,15 @@ public class GithubSettings implements PersistentStateComponent { myHost = host != null ? host : GITHUB; } + public void setAnonymousGist(final boolean anonymousGist) { + myAnonymousGist = anonymousGist; + } + + public void setPrivateGist(final boolean privateGist) { + myPrivateGist = privateGist; + } + + public void setOpenInBrowserGist(final boolean openInBrowserGist) { + myOpenInBrowserGist = openInBrowserGist; + } } \ No newline at end of file diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java index 5f78df2be8af..51388e166efb 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java @@ -125,7 +125,7 @@ public class GithubShareAction extends DumbAwareAction { LOG.info("Creating GitHub repository"); final String escapedDescription = JDOMUtil.escapeText(description, true, true).replace("&#", "%"); GithubUtil.doREST(settings.getHost(), settings.getLogin(), settings.getPassword(), - "/repos/create?name=" + name + "&public=" + (isPrivate ? "0" : "1") + "&description=" + escapedDescription, true); + "/repos/create?name=" + name + "&public=" + (isPrivate ? "0" : "1") + "&description=" + escapedDescription, true).releaseConnection(); LOG.info("Successfully created GitHub repository"); } catch (final Exception e1) { diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java b/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java index b100ce4e56fa..f727a5fb09f3 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java @@ -28,7 +28,6 @@ import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.net.HttpConfigurable; import git4idea.GitRemote; -import git4idea.GitUtil; import git4idea.config.GitVcsApplicationSettings; import git4idea.config.GitVersion; import git4idea.i18n.GitBundle; @@ -93,8 +92,9 @@ public class GithubUtil { } public static boolean testConnection(final String url, final String login, final String password) { + HttpMethod method = null; try { - final HttpMethod method = doREST(url, login, password, "/user/show/" + login, false); + method = doREST(url, login, password, "/user/show/" + login, false); final InputStream stream = method.getResponseBodyAsStream(); final Element element = new SAXBuilder(false).build(stream).getRootElement(); if ("error".equals(element.getName())){ @@ -106,6 +106,11 @@ public class GithubUtil { catch (Exception e) { // Ignore } + finally { + if (method!=null) { + method.releaseConnection(); + } + } return false; } @@ -118,7 +123,7 @@ public class GithubUtil { return method; } - public static HttpClient getHttpClient(final String login, final String password) { + public static HttpClient getHttpClient(@Nullable final String login, @Nullable final String password) { final HttpClient client = new HttpClient(); // Configure proxySettings if it is required final HttpConfigurable proxySettings = HttpConfigurable.getInstance(); @@ -129,15 +134,18 @@ public class GithubUtil { proxySettings.getPlainProxyPassword())); } } - client.getParams().setAuthenticationPreemptive(true); - client.getState().setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(login, password)); + if (login != null && password != null) { + client.getParams().setAuthenticationPreemptive(true); + client.getState().setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(login, password)); + } return client; } public static List getAvailableRepos(final String url, final String login, final String password, final boolean ownOnly) { + HttpMethod method = null; try { final String request = (ownOnly ? "/repos/show/" : "/repos/watched/") + login; - final HttpMethod method = doREST(url, login, password, request, false); + method = doREST(url, login, password, request, false); final InputStream stream = method.getResponseBodyAsStream(); final Element element = new SAXBuilder(false).build(stream).getRootElement(); if ("error".equals(element.getName())){ @@ -155,15 +163,21 @@ public class GithubUtil { catch (Exception e) { // ignore } + finally { + if (method != null){ + method.releaseConnection(); + } + } return Collections.emptyList(); } @Nullable public static RepositoryInfo getDetailedRepoInfo(final String url, final String login, final String password, final String owner, final String name) { + HttpMethod method = null; try { final String request = "/repos/show/" + owner + "/" + name; - final HttpMethod method = doREST(url, login, password, request, false); + method = doREST(url, login, password, request, false); final InputStream stream = method.getResponseBodyAsStream(); final Element element = new SAXBuilder(false).build(stream).getRootElement(); if ("error".equals(element.getName())){ @@ -175,13 +189,19 @@ public class GithubUtil { catch (Exception e) { // ignore } + finally { + if (method != null){ + method.releaseConnection(); + } + } return null; } public static boolean isPrivateRepoAllowed(final String url, final String login, final String password) { + HttpMethod method = null; try { final String request = "/user/show/" + login; - final HttpMethod method = doREST(url, login, password, request, false); + method = doREST(url, login, password, request, false); final InputStream stream = method.getResponseBodyAsStream(); final Element element = new SAXBuilder(false).build(stream).getRootElement(); if ("error".equals(element.getName())){ @@ -196,6 +216,11 @@ public class GithubUtil { catch (Exception e) { // ignore } + finally { + if (method != null){ + method.releaseConnection(); + } + } return false; } @@ -295,17 +320,6 @@ public class GithubUtil { } } - @Nullable - public static GitRemote getGithubBoundRepository(final Project project){ - final VirtualFile root = project.getBaseDir(); - // Check if git is already initialized and presence of remote branch - final boolean gitDetected = GitUtil.isUnderGit(root); - if (!gitDetected) { - return null; - } - return findGitHubRemoteBranch(project, root); - } - @Nullable public static GitRemote findGitHubRemoteBranch(final Project project, final VirtualFile root) { // i.e. find origin which points on my github repo diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GitHubCreateGistDialog.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GitHubCreateGistDialog.java new file mode 100644 index 000000000000..b68d2069e294 --- /dev/null +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GitHubCreateGistDialog.java @@ -0,0 +1,90 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.github.ui; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import org.jetbrains.plugins.github.GithubSettings; + +import javax.swing.*; + +/** + * @author oleg + * @date 9/27/11 + */ +public class GitHubCreateGistDialog extends DialogWrapper { + private final GitHubCreateGistPanel myGithubCreateGistPanel; + + public GitHubCreateGistDialog(final Project project, final boolean canBePersonal) { + super(project, true); + myGithubCreateGistPanel = new GitHubCreateGistPanel(); + myGithubCreateGistPanel.setCanBePersonal(canBePersonal); + // Use saved settings for controls + final GithubSettings settings = GithubSettings.getInstance(); + if (canBePersonal){ + myGithubCreateGistPanel.setAnonymous(settings.isAnonymous()); + } + myGithubCreateGistPanel.setPrivate(settings.isPrivateGist()); + myGithubCreateGistPanel.setOpenInBrowser(settings.isOpenInBrowserGist()); + setTitle("Create Gist"); + init(); + } + + protected Action[] createActions() { + return new Action[] {getOKAction(), getCancelAction(), getHelpAction()}; + } + + @Override + protected JComponent createCenterPanel() { + return myGithubCreateGistPanel.getPanel(); + } + + @Override + protected String getHelpId() { + return null; + } + + @Override + protected void doOKAction() { + // Store settings + final GithubSettings settings = GithubSettings.getInstance(); + settings.setAnonymousGist(myGithubCreateGistPanel.isAnonymous()); + settings.setOpenInBrowserGist(myGithubCreateGistPanel.isOpenInBrowser()); + settings.setPrivateGist(myGithubCreateGistPanel.isPrivate()); + super.doOKAction(); + } + + @Override + public JComponent getPreferredFocusedComponent() { + return myGithubCreateGistPanel.getDescriptionTextArea(); + } + + public boolean isPrivate() { + return myGithubCreateGistPanel.isPrivate(); + } + + public boolean isAnonimous() { + return myGithubCreateGistPanel.isAnonymous(); + } + + public String getDescription() { + return myGithubCreateGistPanel.getDescriptionTextArea().getText(); + } + + public boolean isOpenInBrowser() { + return myGithubCreateGistPanel.isOpenInBrowser(); + } +} diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GitHubCreateGistPanel.form b/plugins/github/src/org/jetbrains/plugins/github/ui/GitHubCreateGistPanel.form new file mode 100644 index 000000000000..91562c01765f --- /dev/null +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GitHubCreateGistPanel.form @@ -0,0 +1,79 @@ + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GitHubCreateGistPanel.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GitHubCreateGistPanel.java new file mode 100644 index 000000000000..18bb1c2fdfde --- /dev/null +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GitHubCreateGistPanel.java @@ -0,0 +1,74 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.github.ui; + +import javax.swing.*; + +/** + * @author oleg + * @date 9/27/11 + */ +public class GitHubCreateGistPanel { + private JTextArea myDescriptionTextArea; + private JTextPane myNoticeTextPane; + private JCheckBox myPrivateCheckBox; + private JPanel myPanel; + private JCheckBox myAnonymousCheckBox; + private JCheckBox myOpenInBrowserCheckBox; + + public GitHubCreateGistPanel() { + myDescriptionTextArea.setBorder(BorderFactory.createEtchedBorder()); + } + + public boolean isPrivate(){ + return myPrivateCheckBox.isSelected(); + } + + public boolean isAnonymous(){ + return myAnonymousCheckBox.isSelected(); + } + + public boolean isOpenInBrowser(){ + return myOpenInBrowserCheckBox.isSelected(); + } + + public void setPrivate(final boolean isPrivate){ + myPrivateCheckBox.setSelected(isPrivate); + } + + public void setAnonymous(final boolean anonymous){ + myAnonymousCheckBox.setSelected(anonymous); + } + public void setOpenInBrowser(final boolean openInBrowser) { + myOpenInBrowserCheckBox.setSelected(openInBrowser); + } + + public JPanel getPanel() { + return myPanel; + } + + public JTextArea getDescriptionTextArea() { + return myDescriptionTextArea; + } + + public void setCanBePersonal(final boolean canBePersonal) { + if (!canBePersonal){ + myAnonymousCheckBox.setEnabled(false); + myAnonymousCheckBox.setSelected(true); + myNoticeTextPane.setText("Note you must be logged in to github to create personal gists"); + } + } +} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/AbstractGradleDependency.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/AbstractGradleDependency.java index b8bf9767825f..1a4538dc187f 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/AbstractGradleDependency.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/AbstractGradleDependency.java @@ -57,7 +57,8 @@ public abstract class AbstractGradleDependency extends AbstractGradleEntity impl public String toString() { return "scope: " + getScope() + ", exported: " + isExported(); } - + + @NotNull @Override public GradleDependency clone() { try { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleContentRoot.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleContentRoot.java index d22170d9b4c8..c4b6b78b88d7 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleContentRoot.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleContentRoot.java @@ -99,8 +99,9 @@ public class GradleContentRoot extends AbstractGradleEntity { return buffer.toString(); } + @NotNull @Override - public GradleContentRoot clone() { + public GradleContentRoot clone(@NotNull GradleEntityCloneContext context) { GradleContentRoot result = new GradleContentRoot(getRootPath()); for (Map.Entry> entry : myData.entrySet()) { for (String path : entry.getValue()) { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleDependency.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleDependency.java index 70d60d924bff..86da85d2303a 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleDependency.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleDependency.java @@ -16,5 +16,6 @@ public interface GradleDependency extends GradleEntity { @NotNull DependencyScope getScope(); - GradleDependency clone(); + @NotNull + GradleDependency clone(@NotNull GradleEntityCloneContext context); } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleEntity.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleEntity.java index fec73b86486d..cf843a1f27a8 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleEntity.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleEntity.java @@ -15,7 +15,7 @@ import java.io.Serializable; * @author Denis Zhdanov * @since 8/12/11 12:50 PM */ -public interface GradleEntity extends Cloneable, Serializable { +public interface GradleEntity extends Serializable { /** * Follows contract of {@link PropertyChangeSupport#addPropertyChangeListener(PropertyChangeListener)} @@ -25,4 +25,7 @@ public interface GradleEntity extends Cloneable, Serializable { void addPropertyChangeListener(@NotNull PropertyChangeListener listener); void invite(@NotNull GradleEntityVisitor visitor); + + @NotNull + GradleEntity clone(@NotNull GradleEntityCloneContext context); } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleEntityCloneContext.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleEntityCloneContext.java new file mode 100644 index 000000000000..dd86d7c22a85 --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleEntityCloneContext.java @@ -0,0 +1,44 @@ +package org.jetbrains.plugins.gradle.importing.model; + +import com.intellij.util.containers.hash.HashMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +/** + * We need to be able to perform cloning of gradle entities. However, there is a possible case that particular entity + * encapsulates graph of other entities. For example, {@link GradleModule} has a number of + * {@link GradleModule#getDependencies() dependencies} where those dependencies can reference other modules that, in turn, also + * have dependencies. + *

+ * The problem is that we need to ensure that particular entity is shared within a single entities graph (e.g. there should + * be a single shared instance of {@link GradleModule gradle module} after cloning). That's why we need some place to serve + * as a cache during cloning. This class serves that purpose. + * + * @author Denis Zhdanov + * @since 9/28/11 12:36 PM + */ +public class GradleEntityCloneContext { + + private final Map myLibraries = new HashMap(); + private final Map myModules = new HashMap(); + + @Nullable + public GradleLibrary getLibrary(@NotNull GradleLibrary library) { + return myLibraries.get(library); + } + + public void store(@NotNull GradleLibrary key, @NotNull GradleLibrary value) { + myLibraries.put(key, value); + } + + @Nullable + public GradleModule getModule(@NotNull GradleModule module) { + return myModules.get(module); + } + + public void store(@NotNull GradleModule key, @NotNull GradleModule value) { + myModules.put(key, value); + } +} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleLibrary.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleLibrary.java index 2c19ab72332c..e2c37d95baba 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleLibrary.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleLibrary.java @@ -56,12 +56,17 @@ public class GradleLibrary extends AbstractNamedGradleEntity implements Named { return "library: " + getName(); } + @NotNull @Override - protected GradleLibrary clone() { - GradleLibrary result = new GradleLibrary(getName()); - for (Map.Entry entry : myPaths.entrySet()) { - result.addPath(entry.getKey(), entry.getValue()); - } + public GradleLibrary clone(@NotNull GradleEntityCloneContext context) { + GradleLibrary result = context.getLibrary(this); + if (result == null) { + result = new GradleLibrary(getName()); + context.store(this, result); + for (Map.Entry entry : myPaths.entrySet()) { + result.addPath(entry.getKey(), entry.getValue()); + } + } return result; } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleLibraryDependency.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleLibraryDependency.java index 003146dabe34..2586f460c53a 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleLibraryDependency.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleLibraryDependency.java @@ -46,9 +46,10 @@ public class GradleLibraryDependency extends AbstractGradleDependency { return super.toString() + ", dependency library: " + getLibrary(); } + @NotNull @Override - public GradleLibraryDependency clone() { - GradleLibraryDependency result = new GradleLibraryDependency(getLibrary().clone()); + public GradleLibraryDependency clone(@NotNull GradleEntityCloneContext context) { + GradleLibraryDependency result = new GradleLibraryDependency(getLibrary().clone(context)); copyTo(result); return result; } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleModule.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleModule.java index 172dc2bce629..14a708ffd002 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleModule.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleModule.java @@ -97,10 +97,13 @@ public class GradleModule extends AbstractNamedGradleEntity implements Named { @Override public int hashCode() { int result = super.hashCode(); - result = 31 * result + myModuleFilePath.hashCode(); + + // Sometimes instance fields are not initialised here during deserialization. Seems to be standard library bug. That's why we + // do null-check here. + result = myModuleFilePath == null ? result : (31 * result + myModuleFilePath.hashCode()); result = 31 * result + (myInheritProjectCompileOutputPath ? 1 : 0); - result = 31 * result + myCompileOutputPaths.hashCode(); - result = 31 * result + myContentRoots.hashCode(); + result = myCompileOutputPaths == null ? result : (31 * result + myCompileOutputPaths.hashCode()); + result = myContentRoots == null ? result : (31 * result + myContentRoots.hashCode()); // We intentionally don't use dependencies here in order to allow module mappings before and after external libraries // resolving (downloading) @@ -116,10 +119,13 @@ public class GradleModule extends AbstractNamedGradleEntity implements Named { GradleModule that = (GradleModule)o; if (!super.equals(that)) return false; - if (!myModuleFilePath.equals(that.myModuleFilePath)) return false; + // Sometimes instance fields are not initialised here during deserialization. Seems to be standard library bug. That's why we + // do null-check here. + if (myModuleFilePath == null ? that.myModuleFilePath != null : !myModuleFilePath.equals(that.myModuleFilePath)) return false; if (myInheritProjectCompileOutputPath != that.myInheritProjectCompileOutputPath) return false; - if (!myCompileOutputPaths.equals(that.myCompileOutputPaths)) return false; - if (!myContentRoots.equals(that.myContentRoots)) return false; + if (myCompileOutputPaths == null + ? that.myCompileOutputPaths != null : !myCompileOutputPaths.equals(that.myCompileOutputPaths)) return false; + if (myContentRoots == null ? that.myContentRoots != null : !myContentRoots.equals(that.myContentRoots)) return false; // We intentionally don't use dependencies here in order to allow module mappings before and after external libraries // resolving (downloading) @@ -135,18 +141,24 @@ public class GradleModule extends AbstractNamedGradleEntity implements Named { ); } + @NotNull @Override - public GradleModule clone() { - GradleModule result = new GradleModule(getName(), new File(getModuleFilePath()).getParent()); + public GradleModule clone(@NotNull GradleEntityCloneContext context) { + GradleModule result = context.getModule(this); + if (result != null) { + return result; + } + result = new GradleModule(getName(), new File(getModuleFilePath()).getParent()); + context.store(this, result); result.setInheritProjectCompileOutputPath(isInheritProjectCompileOutputPath()); for (GradleContentRoot contentRoot : getContentRoots()) { - result.addContentRoot(contentRoot.clone()); + result.addContentRoot(contentRoot.clone(context)); } for (Map.Entry entry : myCompileOutputPaths.entrySet()) { result.setCompileOutputPath(entry.getKey(), entry.getValue()); } for (GradleDependency dependency : getDependencies()) { - result.addDependency(dependency.clone()); + result.addDependency(dependency.clone(context)); } return result; } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleModuleDependency.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleModuleDependency.java index e42b02a7e7de..da9e2e86045d 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleModuleDependency.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleModuleDependency.java @@ -54,10 +54,11 @@ public class GradleModuleDependency extends AbstractGradleDependency { return super.toString() + ", dependency module: " + getModule(); } + @NotNull @Override - public GradleModuleDependency clone() { - GradleModuleDependency result = new GradleModuleDependency(getModule().clone()); - copyTo(result); + public GradleModuleDependency clone(@NotNull GradleEntityCloneContext context) { + GradleModuleDependency result = new GradleModuleDependency(getModule().clone(context)); + copyTo(result); return result; } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleProject.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleProject.java index 1b6f20019c5f..a163e1a4dc00 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleProject.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/model/GradleProject.java @@ -194,17 +194,18 @@ public class GradleProject extends AbstractNamedGradleEntity { getName(), getJdkVersion(), getLanguageLevel(), getModules()); } + @NotNull @Override - public GradleProject clone() { + public GradleProject clone(@NotNull GradleEntityCloneContext context) { GradleProject result = new GradleProject(getProjectFileDirectoryPath(), getCompileOutputPath()); result.setName(getName()); result.setJdkVersion(getJdkVersion()); result.setLanguageLevel(getLanguageLevel()); for (GradleModule module : getModules()) { - result.addModule(module.clone()); + result.addModule(module.clone(context)); } for (GradleLibrary library : getLibraries()) { - result.addLibrary(library.clone()); + result.addLibrary(library.clone(context)); } return result; } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/wizard/adjust/GradleAdjustImportSettingsStep.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/wizard/adjust/GradleAdjustImportSettingsStep.java index 5af5a7c50657..61e9b7854413 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/wizard/adjust/GradleAdjustImportSettingsStep.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/wizard/adjust/GradleAdjustImportSettingsStep.java @@ -174,9 +174,10 @@ public class GradleAdjustImportSettingsStep extends AbstractImportFromGradleWiza Collections.sort(modules, Named.COMPARATOR); List moduleNodes = new ArrayList(); Map moduleMappings = new HashMap(); - + + GradleEntityCloneContext cloneContext = new GradleEntityCloneContext(); for (GradleModule module : modules) { - GradleModule moduleCopy = module.clone(); + GradleModule moduleCopy = module.clone(cloneContext); moduleMappings.put(module, moduleCopy); DefaultMutableTreeNode moduleNode = buildNode(module, entity2nodes, counter++); moduleNodes.add(moduleNode); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleProjectResolverImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleProjectResolverImpl.java index e5faf477373c..17dad9759b35 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleProjectResolverImpl.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleProjectResolverImpl.java @@ -13,8 +13,6 @@ import org.gradle.tooling.model.idea.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.importing.model.*; -import org.jetbrains.plugins.gradle.importing.model.GradleLibraryDependency; -import org.jetbrains.plugins.gradle.importing.model.GradleProject; import org.jetbrains.plugins.gradle.remote.GradleProjectResolver; import org.jetbrains.plugins.gradle.remote.RemoteGradleProcessSettings; import org.jetbrains.plugins.gradle.remote.RemoteGradleService; @@ -24,6 +22,7 @@ import org.jetbrains.plugins.gradle.util.GradleUtil; import java.io.File; import java.rmi.RemoteException; +import java.util.Arrays; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -37,7 +36,11 @@ import java.util.concurrent.atomic.AtomicReference; * @since 8/8/11 11:09 AM */ public class GradleProjectResolverImpl extends RemoteObject implements GradleProjectResolver, RemoteGradleService { - + + private static final Set NON_UNIQUE_PATH_ENTRIES = new HashSet(Arrays.asList( + "src", "main", "java", "test", "resources" + )); + private final BlockingQueue myConnections = new LinkedBlockingQueue(); private final AtomicReference mySettings = new AtomicReference(); @@ -55,6 +58,7 @@ public class GradleProjectResolverImpl extends RemoteObject implements GradlePro // populating dependent module object. Map> modules = createModules(project, result); populateModules(modules.values(), result); + diversifyLibraryNamesIfNecessary(result); return result; } @@ -310,6 +314,46 @@ public class GradleProjectResolverImpl extends RemoteObject implements GradlePro } return null; } + + /** + * Gradle API doesn't provide library names at the moment, so, we deduce them from the path. However, it's possible to have identical + * names then. + *

+ * This method solves that by diversifying duplicate library names. + * + * @param project target project which library names should be diversified if necessary + */ + private static void diversifyLibraryNamesIfNecessary(@NotNull GradleProject project) { + Map libraries = new HashMap(); + for (GradleLibrary library : project.getLibraries()) { + GradleLibrary previous = libraries.remove(library.getName()); + if (previous == null) { + libraries.put(library.getName(), library); + continue; + } + previous.setName(generateName(previous)); + libraries.put(previous.getName(), previous); + library.setName(generateName(library)); + libraries.put(library.getName(), library); + } + } + + @NotNull + private static String generateName(@NotNull GradleLibrary library) { + for (LibraryPathType pathType : LibraryPathType.values()) { + String path = library.getPath(pathType); + if (path == null) { + continue; + } + File file = new File(path).getParentFile(); + for (; file != null; file = file.getParentFile()) { + if (!NON_UNIQUE_PATH_ENTRIES.contains(file.getName())) { + return file.getName() + "-" + library.getName(); + } + } + } + return library.getName(); + } /** * Allows to retrieve gradle api connection to use for the given project. diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java index cfee9ff35a6b..db6d31761be9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java @@ -70,6 +70,15 @@ public class GroovyDocumentationProvider implements CodeDocumentationProvider, E @NonNls private static final String RETURN_TAG = "@return"; @NonNls private static final String THROWS_TAG = "@throws"; + private static PsiSubstitutor calcSubstitutor(PsiElement originalElement) { + PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; + if (originalElement instanceof GrReferenceExpression) { + substitutor = ((GrReferenceExpression)originalElement).advancedResolve().getSubstitutor(); + } + return substitutor; + } + + @Nullable public String getQuickNavigateInfo(PsiElement element, PsiElement originalElement) { if (element instanceof GrVariable) { @@ -84,7 +93,7 @@ public class GroovyDocumentationProvider implements CodeDocumentationProvider, E generateModifiers(buffer, element); } final PsiType type = variable.getDeclaredType(); - appendTypeString(buffer, type); + appendTypeString(buffer, type, calcSubstitutor(originalElement)); buffer.append(" "); buffer.append(variable.getName()); newLine(buffer); @@ -111,7 +120,7 @@ public class GroovyDocumentationProvider implements CodeDocumentationProvider, E } } } - appendTypeString(buffer, type); + appendTypeString(buffer, type, PsiSubstitutor.EMPTY); buffer.append(" "); buffer.append(refExpr.getReferenceName()); return buffer.toString(); @@ -132,8 +141,9 @@ public class GroovyDocumentationProvider implements CodeDocumentationProvider, E } } + PsiSubstitutor substitutor = calcSubstitutor(originalElement); if (!method.isConstructor()) { - appendTypeString(buffer, PsiUtil.getSmartReturnType(method)); + appendTypeString(buffer, PsiUtil.getSmartReturnType(method), substitutor); buffer.append(" "); } buffer.append(method.getName()).append(" "); @@ -143,11 +153,11 @@ public class GroovyDocumentationProvider implements CodeDocumentationProvider, E PsiParameter parameter = parameters[i]; if (i > 0) buffer.append(", "); if (parameter instanceof GrParameter) { - buffer.append(GroovyPresentationUtil.getParameterPresentation((GrParameter)parameter, PsiSubstitutor.EMPTY)); + buffer.append(GroovyPresentationUtil.getParameterPresentation((GrParameter)parameter, substitutor, false)); } else { PsiType type = parameter.getType(); - appendTypeString(buffer, type); + appendTypeString(buffer, type, substitutor); buffer.append(" "); buffer.append(parameter.getName()); } @@ -157,7 +167,7 @@ public class GroovyDocumentationProvider implements CodeDocumentationProvider, E if (referencedTypes.length > 0) { buffer.append("\nthrows "); for (PsiClassType referencedType : referencedTypes) { - appendTypeString(buffer, referencedType); + appendTypeString(buffer, referencedType, PsiSubstitutor.EMPTY); buffer.append(", "); } buffer.delete(buffer.length() - 2, buffer.length()); @@ -178,7 +188,7 @@ public class GroovyDocumentationProvider implements CodeDocumentationProvider, E final PsiType inferredType = ((GrReferenceExpression)originalElement).getType(); if (inferredType != null) { buffer.append("[inferred type] "); - appendTypeString(buffer, inferredType); + appendTypeString(buffer, inferredType, PsiSubstitutor.EMPTY); return; } } @@ -234,7 +244,7 @@ public class GroovyDocumentationProvider implements CodeDocumentationProvider, E for (int j = 0; j < refs.length; j++) { if (j > 0) buffer.append(" & "); - appendTypeString(buffer, refs[j]); + appendTypeString(buffer, refs[j], PsiSubstitutor.EMPTY); } } } @@ -251,7 +261,7 @@ public class GroovyDocumentationProvider implements CodeDocumentationProvider, E else { for (int i = 0; i < refs.length; i++) { if (i > 0) buffer.append(", "); - appendTypeString(buffer, refs[i]); + appendTypeString(buffer, refs[i], PsiSubstitutor.EMPTY); } } } @@ -261,7 +271,7 @@ public class GroovyDocumentationProvider implements CodeDocumentationProvider, E buffer.append("\nimplements "); for (int i = 0; i < refs.length; i++) { if (i > 0) buffer.append(", "); - appendTypeString(buffer, refs[i]); + appendTypeString(buffer, refs[i], PsiSubstitutor.EMPTY); } } @@ -270,9 +280,9 @@ public class GroovyDocumentationProvider implements CodeDocumentationProvider, E } - private static void appendTypeString(StringBuilder buffer, PsiType type) { + private static void appendTypeString(StringBuilder buffer, PsiType type, PsiSubstitutor substitutor) { if (type != null) { - buffer.append(StringUtil.escapeXml(type.getCanonicalText())); + buffer.append(StringUtil.escapeXml(substitutor.substitute(type).getCanonicalText())); } else { buffer.append(GrModifier.DEF); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyPresentationUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyPresentationUtil.java index 14ffc51c7b34..8d0808fd5366 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyPresentationUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyPresentationUtil.java @@ -38,12 +38,12 @@ import java.util.Set; public class GroovyPresentationUtil { private static final int CONSTRAINTS_NUMBER = 2; - public static String getParameterPresentation(GrParameter parameter, PsiSubstitutor substitutor) { + public static String getParameterPresentation(GrParameter parameter, PsiSubstitutor substitutor, boolean presentable) { StringBuilder builder = new StringBuilder(); PsiType type = parameter.getTypeGroovy(); if (type != null) { type = substitutor.substitute(type); - return builder.append(type.getPresentableText()).append(" ").append(parameter.getName()).toString(); + return builder.append(presentable ? type.getPresentableText() : type.getCanonicalText()).append(" ").append(parameter.getName()).toString(); } else { builder.append(parameter.getName()); final Set structural = Collections.synchronizedSet(new LinkedHashSet()); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyParameterInfoHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyParameterInfoHandler.java index f06f118bc467..595d5f6035c0 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyParameterInfoHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyParameterInfoHandler.java @@ -466,7 +466,7 @@ public class GroovyParameterInfoHandler implements ParameterInfoHandlerWithTabAc private static void appendParameterText(PsiParameter parm, PsiSubstitutor substitutor, StringBuffer buffer) { if (parm instanceof GrParameter) { GrParameter grParam = (GrParameter)parm; - buffer.append(GroovyPresentationUtil.getParameterPresentation(grParam, substitutor)); + buffer.append(GroovyPresentationUtil.getParameterPresentation(grParam, substitutor, true)); final GrExpression initializer = grParam.getDefaultInitializer(); if (initializer != null) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyDocumentationTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyDocumentationTest.groovy new file mode 100644 index 000000000000..894f6df4e4e2 --- /dev/null +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyDocumentationTest.groovy @@ -0,0 +1,46 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy + +import com.intellij.codeInsight.navigation.CtrlMouseHandler +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase + +/** + * @author peter + */ +class GroovyDocumentationTest extends LightCodeInsightFixtureTestCase { + + public void testGenericMethod() { + myFixture.configureByText 'a.groovy', ''' +class Bar { java.util.List foo(T param); } +new Bar().foo(); + ''' + def ref = myFixture.file.findReferenceAt(myFixture.editor.caretModel.offset) + assert CtrlMouseHandler.getInfo(ref.resolve(), ref.element) == """Bar +java.util.List<java.lang.String> foo (java.lang.String param)""" + } + + public void testGenericField() { + myFixture.configureByText 'a.groovy', ''' +class Bar { T field; } +new Bar().field + ''' + def ref = myFixture.file.findReferenceAt(myFixture.editor.caretModel.offset) + assert CtrlMouseHandler.getInfo(ref.resolve(), ref.element) == """Bar +java.lang.Integer getField ()""" + } + +} diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/engine/BaseSpellChecker.java b/plugins/spellchecker/src/com/intellij/spellchecker/engine/BaseSpellChecker.java index b9ff322199b6..8002c8388ee9 100644 --- a/plugins/spellchecker/src/com/intellij/spellchecker/engine/BaseSpellChecker.java +++ b/plugins/spellchecker/src/com/intellij/spellchecker/engine/BaseSpellChecker.java @@ -161,6 +161,7 @@ public class BaseSpellChecker implements SpellCheckerEngine { UIUtil.invokeLaterIfNeeded(new Runnable() { @Override public void run() { + if (project.isDisposed()) return; final DaemonCodeAnalyzer instance = DaemonCodeAnalyzer.getInstance(project); if (instance != null) instance.restart(); } diff --git a/resources-en/src/search/searchableOptions.xml b/resources-en/src/search/searchableOptions.xml index 5f6aee3d80a3..26fe133530a9 100644 --- a/resources-en/src/search/searchableOptions.xml +++ b/resources-en/src/search/searchableOptions.xml @@ -1,1595 +1,143 @@ - - diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 9ad998fd2e4b..7e50606de3d6 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -968,7 +968,10 @@ - + + + + diff --git a/resources/src/idea/RichPlatformPlugin.xml b/resources/src/idea/RichPlatformPlugin.xml index fcb1d198c0c6..95c79354ce4a 100644 --- a/resources/src/idea/RichPlatformPlugin.xml +++ b/resources/src/idea/RichPlatformPlugin.xml @@ -268,9 +268,7 @@ - - - + diff --git a/xml/impl/src/com/intellij/xml/util/CheckDtdReferencesInspection.java b/xml/impl/src/com/intellij/xml/util/CheckDtdReferencesInspection.java index fbce4146afa3..216f2475fb54 100644 --- a/xml/impl/src/com/intellij/xml/util/CheckDtdReferencesInspection.java +++ b/xml/impl/src/com/intellij/xml/util/CheckDtdReferencesInspection.java @@ -48,6 +48,10 @@ public class CheckDtdReferencesInspection extends XmlSuppressableInspectionTool public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { return new XmlElementVisitor() { @Override public void visitXmlElement(final XmlElement element) { + if (HtmlUtil.isHtml5Context(element)) { + return; + } + if (element instanceof XmlElementContentSpec || element instanceof XmlEntityRef ) {