From ef3819383b7ebf611668b1a47a5b7e475211ef2e Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 4 Apr 2013 12:26:48 +0200 Subject: [PATCH 01/14] add link to PluginDevelopment site from github readme.md (IDEA-104432) --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index a8a5f3459c58..764cf9196914 100644 --- a/README.md +++ b/README.md @@ -18,3 +18,10 @@ To develop IntelliJ IDEA, you can use either IntelliJ IDEA Community Edition or Pull requests are welcome. Please make sure that you follow the [IntelliJ Coding Guidelines](http://www.jetbrains.org/display/IJOS/IntelliJ+Coding+Guidelines). Note that you'll need to submit a [Contributor Agreement](http://www.jetbrains.org/display/IJOS/Contributor+Agreement) before we can accept your pull request. + +See http://www.jetbrains.org/ for more information. + +## Developer Documentation + +You can find information on the internal architecture of IntelliJ IDEA and plugin development at the +[PluginDevelopment](http://confluence.jetbrains.com/display/IDEADEV/PluginDevelopment) site. From f250113943758a3e2ede03d285c02fb3f463a7b1 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 4 Apr 2013 12:39:36 +0200 Subject: [PATCH 02/14] fix project leak in project view tests --- .../projectView/NavigateFromSourceTest.java | 3 +-- .../projectView/ProjectTreeBuilderTest.java | 4 ++-- .../projectView/TestProjectTreeStructure.java | 13 +++++++++++++ .../intellij/testFramework/ProjectViewTestUtil.java | 11 +---------- .../FormMergerTreeStructureProviderTest.java | 5 ++--- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/projectView/NavigateFromSourceTest.java b/java/java-tests/testSrc/com/intellij/projectView/NavigateFromSourceTest.java index dd7d1fe6daf9..39868f87f180 100644 --- a/java/java-tests/testSrc/com/intellij/projectView/NavigateFromSourceTest.java +++ b/java/java-tests/testSrc/com/intellij/projectView/NavigateFromSourceTest.java @@ -46,7 +46,6 @@ import com.intellij.openapi.wm.ToolWindowId; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.psi.*; import com.intellij.testFramework.PlatformTestUtil; -import com.intellij.testFramework.ProjectViewTestUtil; import javax.swing.*; import java.io.IOException; @@ -63,7 +62,7 @@ public class NavigateFromSourceTest extends BaseProjectViewTestCase { final PsiFile containingFile = psiClass.getContainingFile(); final VirtualFile virtualFile = containingFile.getVirtualFile(); - ProjectViewTestUtil.checkNavigateFromSourceBehaviour(psiClass, virtualFile, pane); + myStructure.checkNavigateFromSourceBehaviour(psiClass, virtualFile, pane); PlatformTestUtil.assertTreeEqual(pane.getTree(), "-Project\n" + " -PsiDirectory: showClassMembers\n" + diff --git a/java/java-tests/testSrc/com/intellij/projectView/ProjectTreeBuilderTest.java b/java/java-tests/testSrc/com/intellij/projectView/ProjectTreeBuilderTest.java index ac415e46241b..17c557ff49ba 100644 --- a/java/java-tests/testSrc/com/intellij/projectView/ProjectTreeBuilderTest.java +++ b/java/java-tests/testSrc/com/intellij/projectView/ProjectTreeBuilderTest.java @@ -26,7 +26,7 @@ public class ProjectTreeBuilderTest extends BaseProjectViewTestCase { PsiFile element = aClass.getContainingFile(); - ProjectViewTestUtil.checkNavigateFromSourceBehaviour(element, element.getVirtualFile(), myStructure.createPane()); + myStructure.checkNavigateFromSourceBehaviour(element, element.getVirtualFile(), myStructure.createPane()); } public void testShowClassMembers() throws IncorrectOperationException, IOException { @@ -51,7 +51,7 @@ public class ProjectTreeBuilderTest extends BaseProjectViewTestCase { final AbstractProjectViewPSIPane pane = myStructure.createPane(); - ProjectViewTestUtil.checkNavigateFromSourceBehaviour(innerClass2Field, innerClass2Field.getContainingFile().getVirtualFile(), pane); + myStructure.checkNavigateFromSourceBehaviour(innerClass2Field, innerClass2Field.getContainingFile().getVirtualFile(), pane); IdeaTestUtil.assertTreeEqual(pane.getTree(), "-Project\n" + " -PsiDirectory: showClassMembers\n" + diff --git a/platform/testFramework/src/com/intellij/projectView/TestProjectTreeStructure.java b/platform/testFramework/src/com/intellij/projectView/TestProjectTreeStructure.java index 816ed4b97e7f..e6b8dee21ce2 100644 --- a/platform/testFramework/src/com/intellij/projectView/TestProjectTreeStructure.java +++ b/platform/testFramework/src/com/intellij/projectView/TestProjectTreeStructure.java @@ -21,6 +21,10 @@ import com.intellij.ide.projectView.impl.AbstractProjectViewPSIPane; import com.intellij.openapi.Disposable; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiElement; +import com.intellij.testFramework.ProjectViewTestUtil; +import junit.framework.Assert; public class TestProjectTreeStructure extends AbstractProjectTreeStructure implements Disposable { protected boolean myShowMembers = false; @@ -32,6 +36,15 @@ public class TestProjectTreeStructure extends AbstractProjectTreeStructure imple Disposer.register(parentDisposable, this); } + public void checkNavigateFromSourceBehaviour(PsiElement element, VirtualFile virtualFile, AbstractProjectViewPSIPane pane) { + Disposer.dispose(pane); + pane.createComponent(); + Disposer.register(this, pane); + Assert.assertNull(ProjectViewTestUtil.getNodeForElement(element, pane)); + pane.select(element, virtualFile, true); + Assert.assertTrue(ProjectViewTestUtil.isExpanded(element, pane)); + } + public AbstractProjectViewPSIPane createPane() { final AbstractProjectViewPSIPane pane = new TestProjectViewPSIPane(myProject, this); pane.createComponent(); diff --git a/platform/testFramework/src/com/intellij/testFramework/ProjectViewTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/ProjectViewTestUtil.java index 1e091e0ca62a..681a5c7e5626 100644 --- a/platform/testFramework/src/com/intellij/testFramework/ProjectViewTestUtil.java +++ b/platform/testFramework/src/com/intellij/testFramework/ProjectViewTestUtil.java @@ -21,7 +21,6 @@ import com.intellij.ide.projectView.impl.nodes.BasePsiNode; import com.intellij.ide.util.treeView.AbstractTreeNode; import com.intellij.ide.util.treeView.AbstractTreeStructure; import com.intellij.openapi.ui.Queryable; -import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.MultiValuesMap; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; @@ -126,7 +125,7 @@ public class ProjectViewTestUtil { return pane.getTree().isExpanded(path.getParentPath()); } - protected static DefaultMutableTreeNode getNodeForElement(PsiElement element, AbstractProjectViewPSIPane pane) { + public static DefaultMutableTreeNode getNodeForElement(PsiElement element, AbstractProjectViewPSIPane pane) { JTree tree = pane.getTree(); TreeModel model = tree.getModel(); Object root = model.getRoot(); @@ -148,14 +147,6 @@ public class ProjectViewTestUtil { return null; } - public static void checkNavigateFromSourceBehaviour(PsiElement element, VirtualFile virtualFile, AbstractProjectViewPSIPane pane) { - Disposer.dispose(pane); - pane.createComponent(); - Assert.assertNull(getNodeForElement(element, pane)); - pane.select(element, virtualFile, true); - Assert.assertTrue(isExpanded(element, pane)); - } - public static boolean isExpanded(PsiElement element, AbstractProjectViewPSIPane pane) { DefaultMutableTreeNode nodeForElement = getNodeForElement(element, pane); return nodeForElement != null && isExpanded((DefaultMutableTreeNode)nodeForElement.getParent(), pane); diff --git a/plugins/ui-designer/testSrc/com/intellij/uiDesigner/projectView/FormMergerTreeStructureProviderTest.java b/plugins/ui-designer/testSrc/com/intellij/uiDesigner/projectView/FormMergerTreeStructureProviderTest.java index f889fe6cee5e..a9801c8573a7 100644 --- a/plugins/ui-designer/testSrc/com/intellij/uiDesigner/projectView/FormMergerTreeStructureProviderTest.java +++ b/plugins/ui-designer/testSrc/com/intellij/uiDesigner/projectView/FormMergerTreeStructureProviderTest.java @@ -23,7 +23,6 @@ import com.intellij.projectView.BaseProjectViewTestCase; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiJavaFile; -import com.intellij.testFramework.ProjectViewTestUtil; public class FormMergerTreeStructureProviderTest extends BaseProjectViewTestCase { @@ -49,11 +48,11 @@ public class FormMergerTreeStructureProviderTest extends BaseProjectViewTestCase " PsiFile(plain text):Form1.form\n"); PsiClass psiClass = ((PsiJavaFile)getPackageDirectory().findFile("Form1.java")).getClasses()[0]; - ProjectViewTestUtil.checkNavigateFromSourceBehaviour(psiClass, psiClass.getContainingFile().getVirtualFile(), pane); + myStructure.checkNavigateFromSourceBehaviour(psiClass, psiClass.getContainingFile().getVirtualFile(), pane); PsiFile psiFile = getPackageDirectory().findFile("Form1.form"); VirtualFile virtualFile = psiFile.getContainingFile().getVirtualFile(); - ProjectViewTestUtil.checkNavigateFromSourceBehaviour(psiFile, virtualFile, pane); + myStructure.checkNavigateFromSourceBehaviour(psiFile, virtualFile, pane); } } From 4009daaea0ef93efd3db22f98331e8b606846a95 Mon Sep 17 00:00:00 2001 From: anna Date: Thu, 4 Apr 2013 13:01:23 +0200 Subject: [PATCH 03/14] javafx: fix completion of stylesheets from application class --- .../plugins/javaFX/JavaFxFileReferenceProvider.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxFileReferenceProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxFileReferenceProvider.java index e6a2669c955a..f371c317476a 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxFileReferenceProvider.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxFileReferenceProvider.java @@ -15,22 +15,28 @@ import java.util.Collections; * Date: 4/3/13 */ public class JavaFxFileReferenceProvider extends PsiReferenceProvider { + @NotNull @Override public PsiReference[] getReferencesByElement(@NotNull final PsiElement element, @NotNull ProcessingContext context) { final Object value = ((PsiLiteralExpression)element).getValue(); final PsiDirectory directory = element.getContainingFile().getOriginalFile().getParent(); if (!(value instanceof String) || directory == null) return PsiReference.EMPTY_ARRAY; + final boolean startsWithSlash = ((String)value).startsWith("/"); final VirtualFileSystem fs = directory.getVirtualFile().getFileSystem(); - return new FileReferenceSet((String)value, element, 1, null, ((NewVirtualFileSystem)fs).isCaseSensitive()) { + final FileReferenceSet fileReferenceSet = new FileReferenceSet((String)value, element, 1, null, ((NewVirtualFileSystem)fs).isCaseSensitive()) { @NotNull @Override public Collection getDefaultContexts() { - if (!directory.isValid()) { + if (startsWithSlash || !directory.isValid()) { return super.getDefaultContexts(); } return Collections.singletonList(directory); } - }.getAllReferences(); + }; + if (startsWithSlash) { + fileReferenceSet.addCustomization(FileReferenceSet.DEFAULT_PATH_EVALUATOR_OPTION, FileReferenceSet.ABSOLUTE_TOP_LEVEL); + } + return fileReferenceSet.getAllReferences(); } } From 2e10288e3ccec2834389f2814ede059864d54952 Mon Sep 17 00:00:00 2001 From: anna Date: Thu, 4 Apr 2013 13:22:40 +0200 Subject: [PATCH 04/14] javafx: move ref on css to CE --- .../refs/JavaFxReferencesContributor.java | 44 +++++++++++++++++-- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxReferencesContributor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxReferencesContributor.java index 658e99aa051a..c17d71567c40 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxReferencesContributor.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxReferencesContributor.java @@ -15,6 +15,7 @@ */ package org.jetbrains.plugins.javaFX.fxml.refs; +import com.intellij.patterns.PsiJavaElementPattern; import com.intellij.psi.*; import com.intellij.psi.filters.ElementFilter; import com.intellij.psi.filters.position.FilterPattern; @@ -30,10 +31,40 @@ import static com.intellij.patterns.PsiJavaPatterns.literalExpression; * Date: 2/22/13 */ public class JavaFxReferencesContributor extends PsiReferenceContributor { + public static final PsiJavaElementPattern.Capture STYLESHEET_PATTERN = + literalExpression().and(new FilterPattern(new ElementFilter() { + public boolean isAcceptable(Object element, PsiElement context) { + final PsiLiteralExpression literalExpression = (PsiLiteralExpression)context; + PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(literalExpression, PsiMethodCallExpression.class); + if (methodCallExpression != null) { + final PsiMethod psiMethod = methodCallExpression.resolveMethod(); + if (psiMethod != null && "add".equals(psiMethod.getName())) { + final PsiClass containingClass = psiMethod.getContainingClass(); + if (containingClass != null ) { + final PsiExpression qualifierExpression = methodCallExpression.getMethodExpression().getQualifierExpression(); + if (qualifierExpression instanceof PsiMethodCallExpression) { + final PsiReferenceExpression getStylesheetsMethodExpression = ((PsiMethodCallExpression)qualifierExpression).getMethodExpression(); + if ("getStylesheets".equals(getStylesheetsMethodExpression.getReferenceName())) { + final PsiExpression stageExpr = getStylesheetsMethodExpression.getQualifierExpression(); + if (stageExpr != null) { + final PsiType psiType = stageExpr.getType(); + return psiType != null && psiType.equalsToText(JavaFxCommonClassNames.JAVA_FX_PARENT); + } + } + } + } + } + } + return false; + } + + public boolean isClassAcceptable(Class hintClass) { + return true; + } + })); - @Override - public void registerReferenceProviders(PsiReferenceRegistrar registrar) { - registrar.registerReferenceProvider(literalExpression().and(new FilterPattern(new ElementFilter() { + public static final PsiJavaElementPattern.Capture FXML_PATTERN = + literalExpression().and(new FilterPattern(new ElementFilter() { public boolean isAcceptable(Object element, PsiElement context) { final PsiLiteralExpression literalExpression = (PsiLiteralExpression)context; PsiMethodCallExpression callExpression = PsiTreeUtil.getParentOfType(literalExpression, PsiMethodCallExpression.class); @@ -72,6 +103,11 @@ public class JavaFxReferencesContributor extends PsiReferenceContributor { public boolean isClassAcceptable(Class hintClass) { return true; } - })), new JavaFxFileReferenceProvider()); + })); + + @Override + public void registerReferenceProviders(PsiReferenceRegistrar registrar) { + registrar.registerReferenceProvider(FXML_PATTERN, new JavaFxFileReferenceProvider()); + registrar.registerReferenceProvider(STYLESHEET_PATTERN, new JavaFxFileReferenceProvider()); } } From fa26cb91ab64a6d4bd3f547e9c12743846b1bc15 Mon Sep 17 00:00:00 2001 From: Vassiliy Kudryashov Date: Thu, 4 Apr 2013 15:45:15 +0400 Subject: [PATCH 05/14] misc favorites-breakpoint fixes; BreakpointsFavoritesManagerd has been moved to xdebugger-impl (IDEA-104033 New Favorites window throws exception in the RubyMine) --- .../FavoritesTreeViewPanel.java | 3 +++ .../src/META-INF/LangExtensions.xml | 3 +++ .../BreakpointsFavoriteListProvider.java | 25 +++++++++---------- .../breakpoints/XBreakpointPanelProvider.java | 1 + resources/src/META-INF/IdeaPlugin.xml | 4 --- 5 files changed, 19 insertions(+), 17 deletions(-) rename {java/debugger/impl/src/com/intellij/debugger/ui => platform/xdebugger-impl/src/com/intellij/xdebugger/impl}/breakpoints/BreakpointsFavoriteListProvider.java (97%) diff --git a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.java b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.java index 2745789a55ff..d0c7cf627dbf 100644 --- a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.java +++ b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.java @@ -245,16 +245,19 @@ public class FavoritesTreeViewPanel extends JPanel implements DataProvider, Dock @Override public void rootsChanged() { myBuilder.updateFromRoot(); + myTree.repaint(); } @Override public void listAdded(String listName) { myBuilder.updateFromRoot(); + myTree.repaint(); } @Override public void listRemoved(String listName) { myBuilder.updateFromRoot(); + myTree.repaint(); } }); } diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index 49facb201cfa..7bfd2960e027 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -827,6 +827,9 @@ + + + diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointsFavoriteListProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointsFavoriteListProvider.java similarity index 97% rename from java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointsFavoriteListProvider.java rename to platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointsFavoriteListProvider.java index f6852bb00ab3..41caa63947c1 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointsFavoriteListProvider.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointsFavoriteListProvider.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.debugger.ui.breakpoints; +package com.intellij.xdebugger.impl.breakpoints; import com.intellij.icons.AllIcons; import com.intellij.ide.favoritesTreeView.AbstractFavoritesListProvider; @@ -29,9 +29,6 @@ import com.intellij.xdebugger.XDebuggerManager; import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroup; import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroupingRule; import com.intellij.xdebugger.impl.DebuggerSupport; -import com.intellij.xdebugger.impl.breakpoints.XBreakpointManagerImpl; -import com.intellij.xdebugger.impl.breakpoints.XBreakpointUtil; -import com.intellij.xdebugger.impl.breakpoints.XBreakpointsDialogState; import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointItem; import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointPanelProvider; import com.intellij.xdebugger.impl.breakpoints.ui.tree.BreakpointItemsTreeController; @@ -75,20 +72,12 @@ public class BreakpointsFavoriteListProvider extends AbstractFavoritesListProvid myTreeController = new BreakpointItemsTreeController(myRulesAvailable); myTree = new BreakpointsSimpleTree(myProject, myTreeController); myTreeController.setTreeView(myTree); + updateChildren(); } @Override public void breakpointsChanged() { - List items = new ArrayList(); - for (final BreakpointPanelProvider provider : myBreakpointPanelProviders) { - provider.provideBreakpointItems(myProject, items); - } - getEnabledGroupingRules(myRulesEnabled); - myTreeController.setGroupingRules(myRulesEnabled); - myTreeController.rebuildTree(items); - updateChildren(); - FavoritesManager.getInstance(myProject).fireListeners(getListName(myProject)); } private void getEnabledGroupingRules(Collection rules) { @@ -103,7 +92,16 @@ public class BreakpointsFavoriteListProvider extends AbstractFavoritesListProvid } private void updateChildren() { + List items = new ArrayList(); + for (final BreakpointPanelProvider provider : myBreakpointPanelProviders) { + provider.provideBreakpointItems(myProject, items); + } + getEnabledGroupingRules(myRulesEnabled); + myTreeController.setGroupingRules(myRulesEnabled); + myTreeController.rebuildTree(items); + myChildren.clear(); + CheckedTreeNode root = myTreeController.getRoot(); for (int i = 0; i < root.getChildCount(); i++) { TreeNode child = root.getChildAt(i); @@ -111,6 +109,7 @@ public class BreakpointsFavoriteListProvider extends AbstractFavoritesListProvid replicate((DefaultMutableTreeNode)child, myNode, myChildren); } } + FavoritesManager.getInstance(myProject).fireListeners(getListName(myProject)); } private void replicate(DefaultMutableTreeNode source, AbstractTreeNode destination, final List> destinationChildren) { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java index 0dfc420586d3..c3f153f23063 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java @@ -148,6 +148,7 @@ public class XBreakpointPanelProvider extends BreakpointPanelProvider breakpoint) { + myListener.breakpointsChanged(); } } diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 16ffa42d2855..e1254dc9e581 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -1125,10 +1125,6 @@ - - - - From b7cbc2a9ab080952a5b7e942b6553348e4b285b0 Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Tue, 2 Apr 2013 15:54:31 +0400 Subject: [PATCH 06/14] emacs-like behavior on backspace in search field fixed --- platform/lang-api/src/com/intellij/find/FindModel.java | 1 - 1 file changed, 1 deletion(-) diff --git a/platform/lang-api/src/com/intellij/find/FindModel.java b/platform/lang-api/src/com/intellij/find/FindModel.java index f0890a47fdcd..c149c2754ae2 100644 --- a/platform/lang-api/src/com/intellij/find/FindModel.java +++ b/platform/lang-api/src/com/intellij/find/FindModel.java @@ -211,7 +211,6 @@ public class FindModel extends UserDataHolderBase implements Cloneable { if (directoryName != null ? !directoryName.equals(findModel.directoryName) : findModel.directoryName != null) return false; if (fileFilter != null ? !fileFilter.equals(findModel.fileFilter) : findModel.fileFilter != null) return false; if (moduleName != null ? !moduleName.equals(findModel.moduleName) : findModel.moduleName != null) return false; - if (myPattern != null ? !myPattern.equals(findModel.myPattern) : findModel.myPattern != null) return false; if (myStringToFind != null ? !myStringToFind.equals(findModel.myStringToFind) : findModel.myStringToFind != null) return false; if (myStringToReplace != null ? !myStringToReplace.equals(findModel.myStringToReplace) : findModel.myStringToReplace != null) { return false; From a94b080fe556cbec8e6ac58f607f68cc92b5d6f6 Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Tue, 2 Apr 2013 18:34:04 +0400 Subject: [PATCH 07/14] IDEA-100907 Undo replace while doing regex replace would undo the regex change instead of the replace --- .../intellij/find/EditorSearchComponent.java | 44 ++++++++++++++++--- .../ui/TextComponentUndoProvider.java | 42 ++++++++++++++---- 2 files changed, 73 insertions(+), 13 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java index 54aa37abcf2a..1f5ee47a055f 100644 --- a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java +++ b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java @@ -86,8 +86,8 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data private JTextComponent mySearchField; private JTextComponent myReplaceField; - private TextComponentUndoProvider mySearchUndo; - private TextComponentUndoProvider myReplaceUndo; + private MyUndoProvider mySearchUndo; + private MyUndoProvider myReplaceUndo; private Getter mySearchFieldGetter = new Getter() { @Override @@ -279,7 +279,7 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data mySearchUndo.dispose(); } mySearchField = createTextField(myLeadPanel); - mySearchUndo = new TextComponentUndoProvider(mySearchField); + mySearchUndo = new MyUndoProvider(mySearchField); setupSearchFieldListener(); @@ -507,7 +507,7 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data myReplaceUndo.dispose(); } myReplaceField = createTextField(myReplacementPane); - myReplaceUndo = new TextComponentUndoProvider(myReplaceField); + myReplaceUndo = new MyUndoProvider(myReplaceField); //if (myToolbarComponent instanceof ActionToolbarImpl) { // new ShowMoreOptions(myToolbarComponent, myReplaceField); @@ -904,6 +904,34 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data return insets; } + private static class MyUndoProvider extends TextComponentUndoProvider { + private boolean myEnabled = true; + public MyUndoProvider(JTextComponent textComponent) { + super(textComponent); + textComponent.getDocument().addDocumentListener(new com.intellij.ui.DocumentAdapter() { + @Override + protected void textChanged(javax.swing.event.DocumentEvent e) { + myEnabled = true; + } + }); + } + + @Override + protected boolean canUndo() { + return super.canUndo() && myEnabled; + } + + @Override + protected boolean canRedo() { + return super.canRedo() && myEnabled; + } + + public void disable() { + myEnabled = false; + myUndoManager.discardAllEdits(); + } + } + private class MyLivePreviewController extends LivePreviewControllerBase { public MyLivePreviewController() { super(EditorSearchComponent.this.mySearchResults, EditorSearchComponent.this.myLivePreview); @@ -941,7 +969,8 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data mySuppressUpdate = false; } //getFocusBack(); - addTextToRecent(myReplaceField) ; + addTextToRecent(myReplaceField); + clearUndoInTextFields(); } public void exclude() { @@ -952,4 +981,9 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data performReplaceAll(myEditor); } } + + private void clearUndoInTextFields() { + myReplaceUndo.disable(); + mySearchUndo.disable(); + } } diff --git a/platform/platform-api/src/com/intellij/ui/TextComponentUndoProvider.java b/platform/platform-api/src/com/intellij/ui/TextComponentUndoProvider.java index 060fe3504c69..ce95057bb2cd 100644 --- a/platform/platform-api/src/com/intellij/ui/TextComponentUndoProvider.java +++ b/platform/platform-api/src/com/intellij/ui/TextComponentUndoProvider.java @@ -29,8 +29,8 @@ import javax.swing.undo.UndoManager; * @author yole */ public class TextComponentUndoProvider implements Disposable { - private final JTextComponent myTextComponent; - private final UndoManager myUndoManager = new UndoManager(); + protected final JTextComponent myTextComponent; + protected final UndoManager myUndoManager = new UndoManager(); private UndoableEditListener myUndoableEditListener; public TextComponentUndoProvider(final JTextComponent textComponent) { @@ -47,27 +47,53 @@ public class TextComponentUndoProvider implements Disposable { Shortcut[] redoShortcuts = activeKeymap.getShortcuts(IdeActions.ACTION_REDO); AnAction undoAction = new AnAction() { + @Override + public void update(AnActionEvent e) { + super.update(e); + e.getPresentation().setEnabled(canUndo()); + } + @Override public void actionPerformed(AnActionEvent e) { - if (myUndoManager.canUndo()) { - myUndoManager.undo(); - } + undo(); } }; AnAction redoAction = new AnAction() { + @Override + public void update(AnActionEvent e) { + super.update(e); + e.getPresentation().setEnabled(canRedo()); + } + @Override public void actionPerformed(AnActionEvent e) { - if (myUndoManager.canRedo()) { - myUndoManager.redo(); - } + redo(); } }; undoAction.registerCustomShortcutSet(new CustomShortcutSet(undoShortcuts), myTextComponent); redoAction.registerCustomShortcutSet(new CustomShortcutSet(redoShortcuts), myTextComponent); + } + protected boolean canUndo() { + return myUndoManager.canUndo(); + } + protected boolean canRedo() { + return myUndoManager.canRedo(); + } + + protected void redo() { + if (myUndoManager.canRedo()) { + myUndoManager.redo(); + } + } + + protected void undo() { + if (myUndoManager.canUndo()) { + myUndoManager.undo(); + } } public void dispose() { From 7a4957ce7a7bc6f8a8d28bd319ed78c903668dbe Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Tue, 2 Apr 2013 20:13:18 +0400 Subject: [PATCH 08/14] IDEA-100954 Breakpoint tooltip is wrong --- .../BreakpointWithHighlighter.java | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java index 0cf455de5068..c4b242756dc4 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java @@ -226,15 +226,15 @@ public abstract class BreakpointWithHighlighter extends Breakpoint { } buf.append(" 
 "); buf.append(DebuggerBundle.message("breakpoint.property.name.suspend.policy")).append(" : "); - if (DebuggerSettings.SUSPEND_ALL.equals(SUSPEND_POLICY)) { + if (DebuggerSettings.SUSPEND_NONE.equals(SUSPEND_POLICY) || !SUSPEND) { + buf.append(DebuggerBundle.message("breakpoint.properties.panel.option.suspend.none")); + } + else if (DebuggerSettings.SUSPEND_ALL.equals(SUSPEND_POLICY)) { buf.append(DebuggerBundle.message("breakpoint.properties.panel.option.suspend.all")); } else if (DebuggerSettings.SUSPEND_THREAD.equals(SUSPEND_POLICY)) { buf.append(DebuggerBundle.message("breakpoint.properties.panel.option.suspend.thread")); } - else if (DebuggerSettings.SUSPEND_NONE.equals(SUSPEND_POLICY)) { - buf.append(DebuggerBundle.message("breakpoint.properties.panel.option.suspend.none")); - } buf.append(" 
 "); buf.append(DebuggerBundle.message("breakpoint.property.name.log.message")).append(": "); buf.append(LOG_ENABLED ? CommonBundle.getYesButtonText() : CommonBundle.getNoButtonText()); @@ -433,7 +433,7 @@ public abstract class BreakpointWithHighlighter extends Breakpoint { } private void setupGutterRenderer(@NotNull RangeHighlighter highlighter) { - MyGutterIconRenderer renderer = new MyGutterIconRenderer(getIcon(), getDescription()); + MyGutterIconRenderer renderer = new MyGutterIconRenderer(this); highlighter.setGutterIconRenderer(renderer); } @@ -597,23 +597,21 @@ public abstract class BreakpointWithHighlighter extends Breakpoint { } private class MyGutterIconRenderer extends GutterIconRenderer { - private final Icon myIcon; - private final String myDescription; + private BreakpointWithHighlighter myBreakpoint; - public MyGutterIconRenderer(@NotNull Icon icon, @NotNull String description) { - myIcon = icon; - myDescription = description; + public MyGutterIconRenderer(BreakpointWithHighlighter breakpoint) { + myBreakpoint = breakpoint; } @Override @NotNull public Icon getIcon() { - return myIcon; + return myBreakpoint.getIcon(); } @Override public String getTooltipText() { - return myDescription; + return myBreakpoint.getDescription(); } @Override From 05cad0e6d4350d8f7218118453896218f09d09b0 Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Wed, 3 Apr 2013 17:33:49 +0400 Subject: [PATCH 09/14] IDEA-100609 Search/Replace toolbar prevents user accessing certain options when view is resized --- .../src/com/intellij/find/EditorSearchComponent.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java index 1f5ee47a055f..a8aa86fff264 100644 --- a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java +++ b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java @@ -287,7 +287,11 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data initToolbar(); } - myLeadPanel.add(myToolbarComponent); + JPanel centerPanel = new JPanel(new BorderLayout()); + centerPanel.setOpaque(false); + centerPanel.add(myToolbarComponent, BorderLayout.CENTER); + + add(centerPanel, BorderLayout.CENTER); if (secondaryActionsAvailable()) { if (myToolbarComponent instanceof ActionToolbarImpl) { @@ -297,9 +301,10 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data JPanel tailPanel = new NonOpaquePanel(new BorderLayout(5, 0)); + tailPanel.setPreferredSize(new Dimension(100, -1)); JPanel tailContainer = new NonOpaquePanel(new BorderLayout(5, 0)); tailContainer.add(tailPanel, BorderLayout.EAST); - add(tailContainer, BorderLayout.CENTER); + centerPanel.add(tailContainer, BorderLayout.EAST); myMatchInfoLabel = new JLabel(); setSmallerFontAndOpaque(myMatchInfoLabel); From 611babb3ad9d2904aac96ce145b3d196728e167b Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Thu, 4 Apr 2013 05:04:53 +0400 Subject: [PATCH 10/14] IDEA-100609 Search/Replace toolbar prevents user accessing certain options when view is resized IDEA-98197 Suboptimal layout in "Quick find/replace panel" --- .../intellij/find/EditorSearchComponent.java | 103 +++++++++++------- 1 file changed, 65 insertions(+), 38 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java index a8aa86fff264..cf567c7ff9a6 100644 --- a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java +++ b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java @@ -25,6 +25,7 @@ import com.intellij.find.impl.livePreview.LivePreviewControllerBase; import com.intellij.find.impl.livePreview.SearchResults; import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.actionSystem.ex.CustomComponentAction; import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; @@ -39,6 +40,7 @@ import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFocusManager; +import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.LightColors; import com.intellij.ui.TextComponentUndoProvider; import com.intellij.ui.components.JBList; @@ -84,6 +86,21 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data return mySearchField; } + private JSplitPane mySplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); + private JPanel myLeftComponent = new JPanel(new BorderLayout()); + private JPanel myRightComponent = new JPanel(new BorderLayout()); + + { + mySplitPane.setOpaque(false); + mySplitPane.setBorder(IdeBorderFactory.createEmptyBorder(1, 0, 2, 0)); + myLeftComponent.setOpaque(false); + myRightComponent.setOpaque(false); + + mySplitPane.setLeftComponent(myLeftComponent); + mySplitPane.setRightComponent(myRightComponent); + add(mySplitPane, BorderLayout.NORTH); + } + private JTextComponent mySearchField; private JTextComponent myReplaceField; private MyUndoProvider mySearchUndo; @@ -273,12 +290,12 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data private void configureLeadPanel() { JPanel myLeadPanel = createLeadPane(); - add(myLeadPanel, BorderLayout.WEST); + myRightComponent.add(myLeadPanel, BorderLayout.WEST); if (mySearchUndo != null) { mySearchUndo.dispose(); } - mySearchField = createTextField(myLeadPanel); + mySearchField = createTextField(BorderLayout.NORTH); mySearchUndo = new MyUndoProvider(mySearchField); setupSearchFieldListener(); @@ -291,7 +308,7 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data centerPanel.setOpaque(false); centerPanel.add(myToolbarComponent, BorderLayout.CENTER); - add(centerPanel, BorderLayout.CENTER); + myRightComponent.add(centerPanel, BorderLayout.CENTER); if (secondaryActionsAvailable()) { if (myToolbarComponent instanceof ActionToolbarImpl) { @@ -301,25 +318,10 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data JPanel tailPanel = new NonOpaquePanel(new BorderLayout(5, 0)); - tailPanel.setPreferredSize(new Dimension(100, -1)); JPanel tailContainer = new NonOpaquePanel(new BorderLayout(5, 0)); tailContainer.add(tailPanel, BorderLayout.EAST); centerPanel.add(tailContainer, BorderLayout.EAST); - myMatchInfoLabel = new JLabel(); - setSmallerFontAndOpaque(myMatchInfoLabel); - - - myClickToHighlightLabel = new LinkLabel("Click to highlight", null, new LinkListener() { - @Override - public void linkSelected(LinkLabel aSource, Object aLinkData) { - setMatchesLimit(Integer.MAX_VALUE); - updateResults(true); - } - }); - setSmallerFontAndOpaque(myClickToHighlightLabel); - myClickToHighlightLabel.setVisible(false); - JLabel closeLabel = new JLabel(" ", AllIcons.Actions.Cross, SwingConstants.RIGHT); closeLabel.addMouseListener(new MouseAdapter() { @Override @@ -330,11 +332,6 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data closeLabel.setToolTipText("Close search bar (Escape)"); - JPanel labelsPanel = new NonOpaquePanel(new FlowLayout()); - - labelsPanel.add(myMatchInfoLabel); - labelsPanel.add(myClickToHighlightLabel); - tailPanel.add(labelsPanel, BorderLayout.CENTER); tailPanel.add(closeLabel, BorderLayout.EAST); Utils.setSmallerFont(mySearchField); @@ -377,6 +374,17 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data actionGroup.add(new ToggleMatchCase(this)); actionGroup.add(new ToggleRegex(this)); + myMatchInfoLabel = new JLabel(); + + myClickToHighlightLabel = new LinkLabel("Click to highlight", null, new LinkListener() { + @Override + public void linkSelected(LinkLabel aSource, Object aLinkData) { + setMatchesLimit(Integer.MAX_VALUE); + updateResults(true); + } + }); + myClickToHighlightLabel.setVisible(false); + myActionsToolbar = ActionManager.getInstance().createActionToolbar("SearchBar", actionGroup, true); myActionsToolbar.setSecondaryActionsTooltip("More Options(" + ShowMoreOptions.SHORT_CUT + ")"); @@ -388,6 +396,25 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data actionGroup.addAction(new TogglePreserveCaseAction(this)); actionGroup.addAction(new ToggleSelectionOnlyAction(this)); + class MyCustomComponentDoNothingAction extends AnAction implements CustomComponentAction { + private JComponent c; + + MyCustomComponentDoNothingAction(JComponent c) { + this.c = c; + c.setBorder(IdeBorderFactory.createEmptyBorder(new Insets(0, 10, 0, 0))); + } + + @Override + public void actionPerformed(AnActionEvent e) { + } + + @Override + public JComponent createCustomComponent(Presentation presentation) { + return c; + } + } + actionGroup.add(new MyCustomComponentDoNothingAction(myMatchInfoLabel)); + actionGroup.add(new MyCustomComponentDoNothingAction(myClickToHighlightLabel)); myActionsToolbar.setLayoutPolicy(ActionToolbar.AUTO_LAYOUT_POLICY); myToolbarComponent = myActionsToolbar.getComponent(); @@ -458,7 +485,8 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data myActionsToolbar.updateActionsImmediately(); if ((myFindModel.isMultiline() && mySearchField instanceof JTextField) || (!myFindModel.isMultiline() && mySearchField instanceof JTextArea)) { - removeAll(); + myLeftComponent.removeAll(); + myRightComponent.removeAll(); configureLeadPanel(); if (myReplacementPane != null) { myReplacementPane = null; @@ -476,7 +504,8 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data if (myFindModel.isReplaceState() && myReplacementPane == null) { configureReplacementPane(); } else if (!myFindModel.isReplaceState() && myReplacementPane != null) { - remove(myReplacementPane); + myLeftComponent.remove(myReplaceField); + myRightComponent.remove(myReplacementPane); myReplacementPane = null; } if (myFindModel.isReplaceState()) { @@ -488,8 +517,8 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data } updateReplaceButton(); - Utils.setSmallerFontForChildren(myToolbarComponent); + revalidate(); } private static boolean wholeWordsApplicable(String stringToFind) { @@ -506,17 +535,15 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data } private void configureReplacementPane() { - myReplacementPane = createLeadPane(); + myReplacementPane = new NonOpaquePanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); if (myReplaceUndo != null) { myReplaceUndo.dispose(); } - myReplaceField = createTextField(myReplacementPane); - myReplaceUndo = new MyUndoProvider(myReplaceField); + myReplaceField = createTextField(BorderLayout.SOUTH); - //if (myToolbarComponent instanceof ActionToolbarImpl) { - // new ShowMoreOptions(myToolbarComponent, myReplaceField); - //} + revalidate(); + myReplaceUndo = new MyUndoProvider(myReplaceField); DocumentListener replaceFieldListener = new DocumentListener() { @Override @@ -541,7 +568,7 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data } myReplaceField.setText(myFindModel.getStringToReplace()); - add(myReplacementPane, BorderLayout.SOUTH); + myRightComponent.add(myReplacementPane, BorderLayout.SOUTH); myReplaceButton = new JButton("Replace"); myReplaceButton.setFocusable(false); @@ -596,7 +623,6 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data new VariantsCompletionAction(this, myReplaceFieldGetter); new NextOccurrenceAction(this, myReplaceFieldGetter); new PrevOccurrenceAction(this, myReplaceFieldGetter); - } private void replaceFieldDocumentChanged() { @@ -638,7 +664,7 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data } private static JPanel createLeadPane() { - return new NonOpaquePanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); + return new NonOpaquePanel(new BorderLayout()); } public void showHistory(final boolean byClickingToolbarButton, JTextComponent textField) { @@ -666,7 +692,7 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data } } - private JTextComponent createTextField(JPanel leadPanel) { + private JTextComponent createTextField(Object constraint) { final JTextComponent editorTextField; if (myFindModel.isMultiline()) { editorTextField = new JTextArea("") { @@ -681,7 +707,7 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data final JScrollPane scrollPane = new JBScrollPane(editorTextField, ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - leadPanel.add(scrollPane); + myLeftComponent.add(scrollPane, constraint); } else { editorTextField = new JTextField("") { @@ -695,8 +721,9 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data if (UIUtil.isUnderGTKLookAndFeel()) { editorTextField.setOpaque(false); } - leadPanel.add(editorTextField); + myLeftComponent.add(editorTextField, constraint); } + editorTextField.setMinimumSize(new Dimension(200, -1)); editorTextField.putClientProperty("AuxEditorComponent", Boolean.TRUE); editorTextField.addFocusListener(new FocusListener() { From b471a0cee98546395431c495b2179cd070ec6ff0 Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Thu, 4 Apr 2013 15:12:09 +0400 Subject: [PATCH 11/14] condition checkbox can't be unckecked --- .../BreakpointPropertiesPanel.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java index c6acaa59212e..71492c9aaf0c 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointPropertiesPanel.java @@ -367,13 +367,26 @@ public abstract class BreakpointPropertiesPanel { } }; - ButtonGroup checkboxesGroup = new ButtonGroup(); - checkboxesGroup.add(myPassCountCheckbox); - checkboxesGroup.add(myConditionCheckbox); - myPassCountCheckbox.addActionListener(updateListener); + myPassCountCheckbox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent event) { + if (myPassCountCheckbox.isSelected()) { + myConditionCheckbox.setSelected(false); + } + updateCheckboxes(); + } + }); myInstanceFiltersCheckBox.addActionListener(updateListener); myClassFiltersCheckBox.addActionListener(updateListener); - myConditionCheckbox.addActionListener(updateListener); + myConditionCheckbox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent event) { + if (myConditionCheckbox.isSelected()) { + myPassCountCheckbox.setSelected(false); + } + updateCheckboxes(); + } + }); DebuggerUIUtil.focusEditorOnCheck(myPassCountCheckbox, myPassCountField); DebuggerUIUtil.focusEditorOnCheck(myLogExpressionCheckBox, myLogExpressionCombo); DebuggerUIUtil.focusEditorOnCheck(myInstanceFiltersCheckBox, myInstanceFiltersField.getTextField()); From d13b34694084784319894231ff97500baa4dd269 Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Thu, 4 Apr 2013 17:08:49 +0400 Subject: [PATCH 12/14] replace JTextField with SearchTextField in Find Bar --- .../intellij/find/EditorSearchComponent.java | 55 ++++++++++++++----- .../ShowHistoryAction.java | 15 ++--- .../src/com/intellij/ui/SearchTextField.java | 6 +- 3 files changed, 51 insertions(+), 25 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java index cf567c7ff9a6..a89f21f16704 100644 --- a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java +++ b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java @@ -36,12 +36,14 @@ import com.intellij.openapi.editor.event.SelectionListener; import com.intellij.openapi.editor.impl.EditorHeaderComponent; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Getter; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.LightColors; +import com.intellij.ui.SearchTextField; import com.intellij.ui.TextComponentUndoProvider; import com.intellij.ui.components.JBList; import com.intellij.ui.components.JBScrollPane; @@ -50,6 +52,7 @@ import com.intellij.ui.components.labels.LinkListener; import com.intellij.ui.components.panels.NonOpaquePanel; import com.intellij.ui.speedSearch.SpeedSearchSupply; import com.intellij.util.ArrayUtil; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; @@ -59,6 +62,7 @@ import javax.swing.event.DocumentListener; import javax.swing.text.JTextComponent; import java.awt.*; import java.awt.event.*; +import java.util.Arrays; import java.util.regex.Pattern; /** @@ -93,6 +97,7 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data { mySplitPane.setOpaque(false); mySplitPane.setBorder(IdeBorderFactory.createEmptyBorder(1, 0, 2, 0)); + mySplitPane.setContinuousLayout(true); myLeftComponent.setOpaque(false); myRightComponent.setOpaque(false); @@ -102,7 +107,11 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data } private JTextComponent mySearchField; + private SearchTextField mySearchSearchTextField; + private JTextComponent myReplaceField; + private SearchTextField myReplaceSearchTextField; + private MyUndoProvider mySearchUndo; private MyUndoProvider myReplaceUndo; @@ -295,7 +304,14 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data if (mySearchUndo != null) { mySearchUndo.dispose(); } - mySearchField = createTextField(BorderLayout.NORTH); + + Ref ref = Ref.create(); + mySearchField = createTextField(BorderLayout.NORTH, ref); + mySearchSearchTextField = ref.get(); + if (mySearchSearchTextField != null) { + setupHistoryToSearchField(mySearchSearchTextField, FindSettings.getInstance().getRecentFindStrings()); + } + mySearchUndo = new MyUndoProvider(mySearchField); setupSearchFieldListener(); @@ -364,6 +380,11 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data Utils.setSmallerFontForChildren(myToolbarComponent); } + private void setupHistoryToSearchField(SearchTextField field, String[] strings) { + field.setHistorySize(strings.length); + field.setHistory(ContainerUtil.reverse(Arrays.asList(strings))); + } + private void initToolbar() { DefaultActionGroup actionGroup = new DefaultActionGroup("search bar", false); actionGroup.add(new ShowHistoryAction(mySearchFieldGetter, this)); @@ -540,10 +561,16 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data if (myReplaceUndo != null) { myReplaceUndo.dispose(); } - myReplaceField = createTextField(BorderLayout.SOUTH); + + Ref ref = Ref.create(); + myReplaceField = createTextField(BorderLayout.SOUTH, ref); + myReplaceSearchTextField = ref.get(); + if (myReplaceSearchTextField != null) { + setupHistoryToSearchField(myReplaceSearchTextField, FindSettings.getInstance().getRecentReplaceStrings()); + } + myReplaceUndo = new MyUndoProvider(myReplaceField); revalidate(); - myReplaceUndo = new MyUndoProvider(myReplaceField); DocumentListener replaceFieldListener = new DocumentListener() { @Override @@ -692,7 +719,7 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data } } - private JTextComponent createTextField(Object constraint) { + private JTextComponent createTextField(Object constraint, Ref searchTextField) { final JTextComponent editorTextField; if (myFindModel.isMultiline()) { editorTextField = new JTextArea("") { @@ -710,18 +737,14 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data myLeftComponent.add(scrollPane, constraint); } else { - editorTextField = new JTextField("") { - @Override - protected void paintBorder(final Graphics g) { - super.paintBorder(g); - paintBorderOfTextField(g); - } - }; - ((JTextField)editorTextField).setColumns(25); + SearchTextField stf = new SearchTextField(true); + stf.setOpaque(false); + editorTextField = stf.getTextEditor(); if (UIUtil.isUnderGTKLookAndFeel()) { editorTextField.setOpaque(false); } - myLeftComponent.add(editorTextField, constraint); + myLeftComponent.add(stf, constraint); + searchTextField.set(stf); } editorTextField.setMinimumSize(new Dimension(200, -1)); editorTextField.putClientProperty("AuxEditorComponent", Boolean.TRUE); @@ -770,8 +793,14 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data if (text.length() > 0) { if (textField == mySearchField) { FindSettings.getInstance().addStringToFind(text); + if (mySearchSearchTextField != null) { + mySearchSearchTextField.addCurrentTextToHistory(); + } } else { FindSettings.getInstance().addStringToReplace(text); + if (myReplaceSearchTextField != null) { + myReplaceSearchTextField.addCurrentTextToHistory(); + } } } } diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ShowHistoryAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ShowHistoryAction.java index 4d807d11e7d8..1fe84cd7a9fe 100644 --- a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ShowHistoryAction.java +++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ShowHistoryAction.java @@ -42,16 +42,11 @@ public class ShowHistoryAction extends EditorHeaderAction implements DumbAware { shortcuts.add(new KeyboardShortcut(KeyStroke.getKeyStroke(KeyEvent.VK_H, InputEvent.CTRL_DOWN_MASK), null)); registerCustomShortcutSet(new CustomShortcutSet(shortcuts.toArray(new Shortcut[shortcuts.size()])), getTextField()); - if (!editorSearchComponent.getFindModel().isMultiline()) { - getTextField().registerKeyboardAction(new ActionListener() { - @Override - public void actionPerformed(ActionEvent actionEvent) { - if (getTextField().getText().isEmpty()) { - getEditorSearchComponent().showHistory(false, getTextField()); - } - } - }, KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), JComponent.WHEN_FOCUSED); - } + } + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setVisible(getEditorSearchComponent().getFindModel().isMultiline()); } @Override diff --git a/platform/platform-api/src/com/intellij/ui/SearchTextField.java b/platform/platform-api/src/com/intellij/ui/SearchTextField.java index 9a35c10c3a28..97020b4fb177 100644 --- a/platform/platform-api/src/com/intellij/ui/SearchTextField.java +++ b/platform/platform-api/src/com/intellij/ui/SearchTextField.java @@ -100,7 +100,9 @@ public class SearchTextField extends JPanel { @Override public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_DOWN) { - if (myPopup == null || !myPopup.isVisible()) { + if (hasNativeLeopardSearchControl()) { + myNativeSearchPopup.show(myTextField, 5, myTextField.getHeight()); + } else if (myPopup == null || !myPopup.isVisible()) { showPopup(); } } @@ -372,7 +374,7 @@ public class SearchTextField extends JPanel { } protected void showPopup() { - if (myPopup == null) { + if (myPopup == null || !myPopup.isVisible()) { final JList list = new JBList(myModel); final Runnable chooseRunnable = createItemChosenCallback(list); myPopup = JBPopupFactory.getInstance().createListPopupBuilder(list) From fe94b55c686351a3f7d3542205fed756b3495e06 Mon Sep 17 00:00:00 2001 From: lehnerj Date: Tue, 2 Apr 2013 19:27:45 +0200 Subject: [PATCH 13/14] Standard ordering expand/collapse all, expand all is always first --- .../newStructureView/StructureViewComponent.java | 2 +- .../com/intellij/util/ui/tree/AbstractFileTreeTable.java | 2 +- .../intellij/execution/testframework/ToolbarPanel.java | 8 ++++---- .../src/com/intellij/usages/impl/UsageViewImpl.java | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java b/platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java index 4baf41c7a5ef..d8e769b99fb3 100644 --- a/platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java +++ b/platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java @@ -413,8 +413,8 @@ public class StructureViewComponent extends SimpleToolWindowPanel implements Tre public AnAction[] getTitleActions() { return new AnAction[]{ - CommonActionsManager.getInstance().createCollapseAllHeaderAction(getTree()), CommonActionsManager.getInstance().createExpandAllHeaderAction(getTree()), + CommonActionsManager.getInstance().createCollapseAllHeaderAction(getTree()), }; } diff --git a/platform/lang-impl/src/com/intellij/util/ui/tree/AbstractFileTreeTable.java b/platform/lang-impl/src/com/intellij/util/ui/tree/AbstractFileTreeTable.java index 747e8c765b75..087b6461839f 100644 --- a/platform/lang-impl/src/com/intellij/util/ui/tree/AbstractFileTreeTable.java +++ b/platform/lang-impl/src/com/intellij/util/ui/tree/AbstractFileTreeTable.java @@ -78,8 +78,8 @@ public abstract class AbstractFileTreeTable extends TreeTable { } }); final DefaultTreeExpander treeExpander = new DefaultTreeExpander(getTree()); - CommonActionsManager.getInstance().createCollapseAllAction(treeExpander, this); CommonActionsManager.getInstance().createExpandAllAction(treeExpander, this); + CommonActionsManager.getInstance().createCollapseAllAction(treeExpander, this); getTree().setShowsRootHandles(true); getTree().setLineStyleAngled(); diff --git a/platform/testRunner/src/com/intellij/execution/testframework/ToolbarPanel.java b/platform/testRunner/src/com/intellij/execution/testframework/ToolbarPanel.java index 06f530090813..5b2526781e0e 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/ToolbarPanel.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/ToolbarPanel.java @@ -75,12 +75,12 @@ public class ToolbarPanel extends JPanel implements OccurenceNavigator, Disposab properties, TestConsoleProperties.SORT_ALPHABETICALLY)); actionGroup.addSeparator(); - AnAction action = CommonActionsManager.getInstance().createCollapseAllAction(myTreeExpander, parent); - action.getTemplatePresentation().setDescription(ExecutionBundle.message("junit.runing.info.collapse.test.action.name")); + AnAction action = CommonActionsManager.getInstance().createExpandAllAction(myTreeExpander, parent); + action.getTemplatePresentation().setDescription(ExecutionBundle.message("junit.runing.info.expand.test.action.name")); actionGroup.add(action); - action = CommonActionsManager.getInstance().createExpandAllAction(myTreeExpander, parent); - action.getTemplatePresentation().setDescription(ExecutionBundle.message("junit.runing.info.expand.test.action.name")); + action = CommonActionsManager.getInstance().createCollapseAllAction(myTreeExpander, parent); + action.getTemplatePresentation().setDescription(ExecutionBundle.message("junit.runing.info.collapse.test.action.name")); actionGroup.add(action); actionGroup.addSeparator(); diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java index 683187e2e845..58ccf7caaea2 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java @@ -539,8 +539,8 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra scheduleDisposeOnClose(new Disposable() { @Override public void dispose() { - collapseAllAction.unregisterCustomShortcutSet(component); expandAllAction.unregisterCustomShortcutSet(component); + collapseAllAction.unregisterCustomShortcutSet(component); } }); From 82b408e1d333a9e0a40a88604ba91c079f3c3071 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Thu, 4 Apr 2013 18:09:53 +0400 Subject: [PATCH 14/14] [r=nik] optimizations: less string operations --- .../jps/javac/OptimizedFileManager17.java | 50 +++++++++++++----- jps/lib/optimizedFileManager.jar | Bin 20328 -> 20937 bytes 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/OptimizedFileManager17.java b/jps/jps-builders/src/org/jetbrains/jps/javac/OptimizedFileManager17.java index 2d96145a20c9..3b0c1731ba2d 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/OptimizedFileManager17.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/OptimizedFileManager17.java @@ -47,6 +47,12 @@ class OptimizedFileManager17 extends com.sun.tools.javac.file.JavacFileManager { private final Map myDirectoryCache = new HashMap(); public static final File[] NULL_FILE_ARRAY = new File[0]; + private static final String _OS_NAME = System.getProperty("os.name").toLowerCase(Locale.US); + private static final boolean isWindows = _OS_NAME.startsWith("windows"); + private static final boolean isOS2 = _OS_NAME.startsWith("os/2") || _OS_NAME.startsWith("os2"); + private static final boolean isMac = _OS_NAME.startsWith("mac"); + private static final boolean isFileSystemCaseSensitive = !isWindows && !isOS2 && !isMac; + public OptimizedFileManager17() throws Throwable { super(new Context(), true, null); final Field archivesField = com.sun.tools.javac.file.JavacFileManager.class.getDeclaredField("archives"); @@ -214,7 +220,7 @@ class OptimizedFileManager17 extends com.sun.tools.javac.file.JavacFileManager { private class InputFileObject extends BaseFileObject { private String name; - final File file; + private final File file; private Reference absFileRef; public InputFileObject(JavacFileManager fileManager, File f) { @@ -285,20 +291,38 @@ class OptimizedFileManager17 extends com.sun.tools.javac.file.JavacFileManager { @Override protected String inferBinaryName(Iterable path) { - String fPath = file.getPath(); - //System.err.println("RegularFileObject " + file + " " +r.getPath()); + final String fPath = file.getPath(); for (File dir: path) { - //System.err.println("dir: " + dir); - String dPath = dir.getPath(); - if (dPath.length() == 0) - dPath = System.getProperty("user.dir"); - if (!dPath.endsWith(File.separator)) - dPath += File.separator; - if (fPath.regionMatches(true, 0, dPath, 0, dPath.length()) - && new File(fPath.substring(0, dPath.length())).equals(new File(dPath))) { - String relativeName = fPath.substring(dPath.length()); - return removeExtension(relativeName).replace(File.separatorChar, '.'); + String dirPath = dir.getPath(); + if (dirPath.length() == 0) { + dirPath = System.getProperty("user.dir"); } + if (!fPath.regionMatches(!isFileSystemCaseSensitive, 0, dirPath, 0, dirPath.length())) { + continue; + } + final int pathLength = fPath.length(); + final boolean endsWithSeparator = dirPath.endsWith(File.separator); + if (!endsWithSeparator) { + // need to check if the next char in fPath is file separator + final int separatorIdx = dirPath.length(); + if (pathLength <= separatorIdx || fPath.charAt(separatorIdx) != File.separatorChar) { + continue; + } + } + // fPath starts with dirPath + final int startIndex = endsWithSeparator ? dirPath.length() : dirPath.length() + 1; + int endIndex = fPath.lastIndexOf('.'); + if (endIndex <= startIndex) { + endIndex = fPath.length(); + } + final int length = endIndex - startIndex; + final StringBuilder buf = new StringBuilder(length).append(fPath, startIndex, endIndex); + for (int idx = 0; idx < length; idx++) { + if (buf.charAt(idx) == File.separatorChar) { + buf.setCharAt(idx, '.'); + } + } + return buf.toString(); } return null; } diff --git a/jps/lib/optimizedFileManager.jar b/jps/lib/optimizedFileManager.jar index cc5355bc32a6fb93315cf3ae3a1d704d36585d95..ce76aa5dbc8dd3a5050ce84a03b2565cd1a787ce 100644 GIT binary patch delta 8614 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 auOk1O>PpBc|C~VoyP!yLaNElNME?c$t7l~Z delta 8009 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