From 2aa76b0407b7bb7e028c2cc9c0f23cbbd4f8674b Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Wed, 28 Dec 2011 12:42:58 +0400 Subject: [PATCH 01/10] IDEA-76142 Gradle support - cannot update IDEA projects once one of build.gradle files changes 1. Added basic infrastructure for the gradle tool window GUI controls; 2. Minor refactoring; --- .../openapi/actionSystem/Presentation.java | 2 +- .../openapi/util/text/StringUtil.java | 2 +- .../resources/i18n/GradleBundle.properties | 7 +- plugins/gradle/src/META-INF/plugin.xml | 7 + .../config/GradleLinkToProjectAction.java | 28 ++++ .../gradle/config/GradleToolWindowPanel.java | 141 ++++++++++++++++++ .../gradle/config/MultiRowFlowPanel.java | 83 +++++++++++ .../GradleProjectStructureChangesPanel.java | 14 +- .../plugins/gradle/util/GradleConstants.java | 7 +- 9 files changed, 284 insertions(+), 7 deletions(-) create mode 100644 plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleLinkToProjectAction.java create mode 100644 plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleToolWindowPanel.java create mode 100644 plugins/gradle/src/org/jetbrains/plugins/gradle/config/MultiRowFlowPanel.java diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/Presentation.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/Presentation.java index 274bf3e4d1b1..17c9efe571b6 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/Presentation.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/Presentation.java @@ -285,7 +285,7 @@ public final class Presentation implements Cloneable { myChangeSupport.firePropertyChange(propertyName, oldValue, newValue); } - public Object clone(){ + public Presentation clone(){ try{ Presentation presentation = (Presentation)super.clone(); presentation.myChangeSupport = new PropertyChangeSupport(presentation); diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index c71ed0094d4a..da5b331fde9e 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -1104,7 +1104,7 @@ public class StringUtil { } @NotNull - public static Iterable tokenize(@NotNull String s, final StringTokenizer tokenizer) { + public static Iterable tokenize(final StringTokenizer tokenizer) { return new Iterable() { public Iterator iterator() { return new Iterator() { diff --git a/plugins/gradle/resources/i18n/GradleBundle.properties b/plugins/gradle/resources/i18n/GradleBundle.properties index 35ec79d873bb..c7f0cb14e8ff 100644 --- a/plugins/gradle/resources/i18n/GradleBundle.properties +++ b/plugins/gradle/resources/i18n/GradleBundle.properties @@ -55,4 +55,9 @@ gradle.generic.text.error.sdk.undefined=Gradle installation is unknown gradle.home.setting.type.deduced=Gradle location is deduced gradle.home.setting.type.unknown=Gradle location is unknown gradle.home.setting.type.explicit.correct=Gradle location is defined -gradle.home.setting.type.explicit.incorrect=Gradle location is incorrect \ No newline at end of file +gradle.home.setting.type.explicit.incorrect=Gradle location is incorrect + +gradle.toolwindow.text.no.linked.project=\nThere is no linked Gradle project\nYou may use {link} to add the one. + +gradle.action.link.project.text=Link gradle project +gradle.action.link.project.description=Allows to link any gradle project to the current IDE project \ No newline at end of file diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml index d317fcd0aece..78023504c47d 100644 --- a/plugins/gradle/src/META-INF/plugin.xml +++ b/plugins/gradle/src/META-INF/plugin.xml @@ -58,4 +58,11 @@ + + + + + + + \ No newline at end of file diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleLinkToProjectAction.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleLinkToProjectAction.java new file mode 100644 index 000000000000..adccca227adf --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleLinkToProjectAction.java @@ -0,0 +1,28 @@ +package org.jetbrains.plugins.gradle.config; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.project.DumbAware; +import org.jetbrains.plugins.gradle.util.GradleBundle; + +/** + * Allows to link gradle project to the current IntelliJ IDEA project. + *

+ * Not thread-safe. + * + * @author Denis Zhdanov + * @since 12/26/11 5:09 PM + */ +public class GradleLinkToProjectAction extends AnAction implements DumbAware { + + public GradleLinkToProjectAction() { + getTemplatePresentation().setText(GradleBundle.message("gradle.action.link.project.text")); + getTemplatePresentation().setDescription(GradleBundle.message("gradle.action.link.project.description")); + } + + @Override + public void actionPerformed(AnActionEvent e) { + // TODO den implement + System.out.println("action performed"); + } +} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleToolWindowPanel.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleToolWindowPanel.java new file mode 100644 index 000000000000..a640f9683293 --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleToolWindowPanel.java @@ -0,0 +1,141 @@ +package org.jetbrains.plugins.gradle.config; + +import com.intellij.openapi.actionSystem.ActionGroup; +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.actionSystem.ActionToolbar; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.ex.ActionButtonLook; +import com.intellij.openapi.actionSystem.impl.ActionButton; +import com.intellij.openapi.ui.SimpleToolWindowPanel; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.ui.ScrollPaneFactory; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.gradle.util.GradleBundle; +import org.jetbrains.plugins.gradle.util.GradleConstants; + +import javax.swing.*; +import java.awt.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.StringTokenizer; + +/** + * Base class for high-level Gradle GUI controls used at the Gradle tool window. The basic idea is to encapsulate the same features in + * this class and allow to extend it via Template Method pattern. The shared features are listed below: + *

+ * 
    + *
  • provide common actions at the toolbar;
  • + *
  • show info control when no gradle project is linked to the current IntelliJ IDEA project;
  • + *
+ *
+ *

+ * Not thread-safe. + * + * @author Denis Zhdanov + * @since 12/26/11 5:19 PM + */ +public abstract class GradleToolWindowPanel extends SimpleToolWindowPanel { + + private static final String NON_LINKED_CARD_NAME = "NON_LINKED"; + private static final String CONTENT_CARD_NAME = "CONTENT"; + private static final String LINK_BUTTON_MARKER = "{link}"; + private static final String TOOL_WINDOW_TOOLBAR_ID = "Gradle.ChangeActionsToolbar"; + private static final String LINK_PROJECT_ACTION_ID = "Gradle.LinkToProject"; + + /** Show info control when no gradle project is linked, using {@link CardLayout} for that. */ + private final CardLayout myLayout = new CardLayout(); + /** Top-level container, managed by the card layout. */ + private final JPanel myContent = new JPanel(myLayout); + /** Control to show when no gradle project is linked to the current IntelliJ IDEA project. */ + private final JPanel myNonLinkedInfoPanel = new JPanel(); + + protected GradleToolWindowPanel(@NotNull String place) { + super(true); + final ActionManager actionManager = ActionManager.getInstance(); + final ActionGroup actionGroup = (ActionGroup)actionManager.getAction(TOOL_WINDOW_TOOLBAR_ID); + ActionToolbar actionToolbar = actionManager.createActionToolbar(place, actionGroup, true); + setToolbar(actionToolbar.getComponent()); + initContent(); + setContent(myContent); + } + + private void initContent() { + final JComponent payloadControl = buildContent(); + myContent.add(ScrollPaneFactory.createScrollPane(payloadControl), CONTENT_CARD_NAME); + + myNonLinkedInfoPanel.setLayout(new GridBagLayout()); + final Color background = payloadControl.getBackground(); + myNonLinkedInfoPanel.setBackground(background); + List rowComponents = new ArrayList(); + final String sentence = GradleBundle.message("gradle.toolwindow.text.no.linked.project"); + for (String s : StringUtil.tokenize(new StringTokenizer(sentence, " \n", true))) { + if (s.isEmpty()) { + continue; + } + if (LINK_BUTTON_MARKER.equals(s)) { + final ActionManager actionManager = ActionManager.getInstance(); + final AnAction action = actionManager.getAction(LINK_PROJECT_ACTION_ID); + ActionButton button= new ActionButton( + action, action.getTemplatePresentation().clone(), GradleConstants.TOOL_WINDOW_TOOLBAR_PLACE, new Dimension(0, 0)) + { + @Override + protected void paintButtonLook(Graphics g) { + // Don't draw border at the inline button. + ActionButtonLook look = getButtonLook(); + look.paintBackground(g, this); + look.paintIcon(g, this, getIcon()); + } + }; + rowComponents.add(button); + } + else if (s.contains("\n")) { + addRow(rowComponents, background); + rowComponents.clear(); + } + else { + final JLabel label = new JLabel(s); + label.setForeground(payloadControl.getForeground()); + label.setBackground(background); + label.setFont(payloadControl.getFont()); + rowComponents.add(label); + } + } + if (!rowComponents.isEmpty()) { + addRow(rowComponents, background); + } + + GridBagConstraints constraints = new GridBagConstraints(); + constraints.weighty = 1; + constraints.fill = GridBagConstraints.VERTICAL; + myNonLinkedInfoPanel.add(Box.createVerticalStrut(1), constraints); + myContent.add(myNonLinkedInfoPanel, NON_LINKED_CARD_NAME); + + myLayout.show(myContent, NON_LINKED_CARD_NAME); + } + + private void addRow(@NotNull Collection rowComponents, @NotNull Color backgroundColor) { + JPanel row = new MultiRowFlowPanel(FlowLayout.CENTER, 0, 3); + row.setBackground(backgroundColor); + if (rowComponents.isEmpty()) { + row.add(new JLabel(" ")); + } + else { + for (JComponent component : rowComponents) { + row.add(component); + } + } + GridBagConstraints constraints = new GridBagConstraints(); + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.weightx = 1; + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.insets.top = 3; + myNonLinkedInfoPanel.add(row, constraints); + } + + /** + * @return GUI control to be displayed at the current tab + */ + @NotNull + protected abstract JComponent buildContent(); +} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/MultiRowFlowPanel.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/MultiRowFlowPanel.java new file mode 100644 index 000000000000..d18b5b9aa8c9 --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/MultiRowFlowPanel.java @@ -0,0 +1,83 @@ +package org.jetbrains.plugins.gradle.config; + +import javax.swing.*; +import java.awt.*; + +/** + * Flow layout calculates necessary size assuming that all components are layed out within a single row. + * That may cause troubles during initial space calculation, i.e. panel with flow layout is represented as a + * single wide row inside a scroll pane. This panel fixes that by calculating necessary size on its own. + * It fixes the width to use as a minimum between a width offered by default flow layout and customizable value + * and calculates the height. If the user has an ability to manually change panel size (e.g. indirectly via changing + * size of the dialog that serves as a container for the panel), that width is used as a maximum width. + * + * @author: Denis Zhdanov + * @since: Jul 28, 2008 + */ +public class MultiRowFlowPanel extends JPanel { + + private int maximumWidth = Toolkit.getDefaultToolkit().getScreenSize().width / 2; + + public MultiRowFlowPanel(int align, int hGap, int vGap) { + super(new FlowLayout(align, hGap, vGap)); + } + + /** + * Calculates a preferred size assuming that the maximum row width is a value returned from + * {@link #getMaxRowWidth()}. + */ + @Override + public Dimension getPreferredSize() { + return calculateSize(getMaxRowWidth()); + } + + /** + * Calculates a preferred size assuming that the maximum row width is a value returned from + * {@link #getMaxRowWidth()}. + */ + @Override + public Dimension getMinimumSize() { + return calculateSize(getMaxRowWidth()); + } + + /** + * @return current representation width if the component is already showed; minimum of default preferred + * width (when all components are layed in a single row) and half screen width + */ + private int getMaxRowWidth() { + int result = getSize().width; + if (result == 0) { + result = Math.min(super.getPreferredSize().width, maximumWidth); + } + return result; + } + + /** + * Iterates all child components and calculates the space enough to keep all of them assuming that the width is + * fixed. + */ + private Dimension calculateSize(int maxRowWidth) { + FlowLayout layout = (FlowLayout)getLayout(); + int height = 0; + int currentRowWidth = 0; + int currentRowHeight = 0; + for (int i = 0, count = getComponentCount(); i < count; ++i) { + Component comp = getComponent(i); + Dimension bounds = comp.getPreferredSize(); + if (!comp.isVisible()) { + continue; + } + currentRowHeight = Math.max(currentRowHeight, bounds.height); + if (currentRowWidth + layout.getHgap() + bounds.width <= maxRowWidth) { + if (bounds.width != 0) { + currentRowWidth += bounds.width + layout.getHgap(); + } + continue; + } + height += currentRowHeight + layout.getVgap(); + currentRowWidth = bounds.width; + currentRowHeight = bounds.height; + } + return new Dimension(maxRowWidth, height + currentRowHeight + 2 * layout.getVgap()); + } +} \ No newline at end of file diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java index 93967ebcee66..b03db8203783 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java @@ -1,6 +1,9 @@ package org.jetbrains.plugins.gradle.sync; +import com.intellij.ui.treeStructure.SimpleTree; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.gradle.config.GradleToolWindowPanel; +import org.jetbrains.plugins.gradle.util.GradleConstants; import javax.swing.*; @@ -10,11 +13,20 @@ import javax.swing.*; * @author Denis Zhdanov * @since 11/3/11 3:58 PM */ -public class GradleProjectStructureChangesPanel extends JPanel { +public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel { private final GradleProjectStructureChangesModel myModel; public GradleProjectStructureChangesPanel(@NotNull GradleProjectStructureChangesModel model) { + super(GradleConstants.TOOL_WINDOW_TOOLBAR_PLACE); myModel = model; } + + @NotNull + @Override + protected JComponent buildContent() { + // TODO den implement + return new SimpleTree(); + //return new JLabel("project-structure-change-content"); + } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java index 6d721b1b5b3f..f6684687fccd 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java @@ -13,9 +13,10 @@ import javax.swing.*; */ public class GradleConstants { - public static final Icon GRADLE_ICON = IconLoader.getIcon("/icons/gradle.png"); - @NonNls public static final String EXTENSION = "gradle"; - @NonNls public static final String DEFAULT_SCRIPT_NAME = "build.gradle"; + public static final Icon GRADLE_ICON = IconLoader.getIcon("/icons/gradle.png"); + @NonNls public static final String EXTENSION = "gradle"; + @NonNls public static final String DEFAULT_SCRIPT_NAME = "build.gradle"; + @NonNls public static final String TOOL_WINDOW_TOOLBAR_PLACE = "GRADLE_SYNC_CHANGES_TOOLBAR"; private GradleConstants() { } From ec7cce2fe0932c87db24de8607ed4f459bbdc5ad Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Wed, 28 Dec 2011 15:04:25 +0400 Subject: [PATCH 02/10] Cleaning resource bundle editor on disposing --- .../properties/editor/ResourceBundleEditor.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java index 647d3a8f9bd6..ee838e7f507f 100644 --- a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java +++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java @@ -102,6 +102,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit private final Set myBackSlashPressed = new THashSet(); @NonNls private static final String VALUES = "values"; @NonNls private static final String NO_PROPERTY_SELECTED = "noPropertySelected"; + private VirtualFileListener myVfsListener; private PsiTreeChangeAdapter myPsiTreeChangeAdapter; @NonNls protected static final String PROPORTION_PROPERTY = "RESOURCE_BUNDLE_SPLITTER_PROPORTION"; @@ -231,7 +232,12 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit } private void installPropertiesChangeListeners() { - VirtualFileManager.getInstance().addVirtualFileListener(new VirtualFileAdapter() { + final VirtualFileManager virtualFileManager = VirtualFileManager.getInstance(); + if (myVfsListener != null) { + assert false; + virtualFileManager.removeVirtualFileListener(myVfsListener); + } + myVfsListener = new VirtualFileAdapter() { @Override public void fileCreated(VirtualFileEvent event) { if (PropertiesUtil.isPropertiesFile(event.getFile(), myProject)) { @@ -260,7 +266,9 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit } } } - }, this); + }; + + virtualFileManager.addVirtualFileListener(myVfsListener, this); myPsiTreeChangeAdapter = new PsiTreeChangeAdapter() { public void childAdded(PsiTreeChangeEvent event) { childrenChanged(event); @@ -607,6 +615,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit public void dispose() { float proportion = getSplitter().getProportion(); PropertiesComponent.getInstance(myProject).setValue(PROPORTION_PROPERTY, Double.toString(proportion)); + VirtualFileManager.getInstance().removeVirtualFileListener(myVfsListener); myDisposed = true; Disposer.dispose(myStructureViewComponent); From 550dd944499790de33f1388ba3cc85536eafac37 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Wed, 28 Dec 2011 18:38:15 +0400 Subject: [PATCH 03/10] IDEA-79420 Editor: Avoid inconsistent closure foldings FoldingGroup processing is corrected --- .../folding/JavaFoldingTest.groovy | 61 +++++++++++++++++++ .../openapi/editor/impl/FoldRegionImpl.java | 11 ++++ 2 files changed, 72 insertions(+) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy index 638ccbecab47..7c5c84e11a6d 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy @@ -19,6 +19,8 @@ package com.intellij.codeInsight.folding; import com.intellij.codeInsight.folding.impl.CodeFoldingManagerImpl import com.intellij.openapi.application.ex.PathManagerEx import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import com.intellij.codeInsight.folding.impl.JavaCodeFoldingSettingsImpl +import com.intellij.openapi.editor.impl.FoldingModelImpl /** * @author Denis Zhdanov @@ -26,6 +28,23 @@ import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase */ public class JavaFoldingTest extends LightCodeInsightFixtureTestCase { + def JavaCodeFoldingSettingsImpl myFoldingSettings + def JavaCodeFoldingSettingsImpl myFoldingStateToRestore + + @Override + public void setUp() { + super.setUp() + myFoldingSettings = JavaCodeFoldingSettings.instance as JavaCodeFoldingSettingsImpl + myFoldingStateToRestore = new JavaCodeFoldingSettingsImpl() + myFoldingStateToRestore.loadState(myFoldingSettings) + } + + @Override + protected void tearDown() { + myFoldingSettings.loadState(myFoldingStateToRestore) + super.tearDown() + } + public void testEndOfLineComments() { myFixture.testFolding("$PathManagerEx.testDataPath/codeInsight/folding/${getTestName(false)}.java"); } @@ -76,10 +95,52 @@ class Test { myFixture.performEditorAction 'CollapseBlock' assertEquals(text.indexOf('}', text.indexOf('i++')), myFixture.editor.caretModel.offset) } + + public void testFoldGroup() { + // Implied by IDEA-79420 + myFoldingSettings.COLLAPSE_CLOSURES = true + def text = """\ +class Test { + void test() { + new Runnable() { + public void run() { + int i = 1; + } + }.run(); + } +} +""" + + configure text + def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl + def closureStartFold = foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable")) + assertNotNull closureStartFold + assertFalse closureStartFold.expanded + + assertNotNull closureStartFold.group + def closureFolds = foldingModel.getGroupedRegions(closureStartFold.group) + assertNotNull closureFolds + assertEquals(2, closureFolds.size()) + + def closureEndFold = closureFolds.get(1) + assertFalse closureEndFold.expanded + + myFixture.editor.caretModel.moveToOffset(closureEndFold.startOffset + 1) + assertTrue closureStartFold.expanded + assertTrue closureEndFold.expanded + + changeFoldRegions { closureStartFold.expanded = false } + assertTrue closureStartFold.expanded + assertTrue closureEndFold.expanded + } private def configure(String text) { myFixture.configureByText("a.java", text) CodeFoldingManagerImpl.getInstance(getProject()).buildInitialFoldings(myFixture.editor); myFixture.doHighlighting() } + + private def changeFoldRegions(Closure op) { + myFixture.editor.foldingModel.runBatchFoldingOperationDoNotCollapseCaret(op) + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionImpl.java index 5dc29fe8aa1a..680ed70bc405 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionImpl.java @@ -65,6 +65,17 @@ public class FoldRegionImpl extends RangeMarkerImpl implements FoldRegion { } else { for (final FoldRegion region : foldingModel.getGroupedRegions(myGroup)) { doSetExpanded(expanded, foldingModel, region); + // There is a possible case that we can't change expanded status of particular fold region (e.g. we can't collapse + // if it contains caret). So, we revert all changes for the fold regions from the same group then. + if (region.isExpanded() != expanded) { + for (FoldRegion regionToRevert : foldingModel.getGroupedRegions(myGroup)) { + if (regionToRevert == region) { + break; + } + doSetExpanded(!expanded, foldingModel, regionToRevert); + } + return; + } } } } From 02cbc261f56cfdcdb108456823e91c9aa9544b40 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 29 Dec 2011 10:47:37 +0100 Subject: [PATCH 04/10] control where to show the popup --- .../src/com/intellij/ui/SpeedSearchBase.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java b/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java index 47cf9f8343c3..a6087b77996e 100644 --- a/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java +++ b/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java @@ -517,8 +517,8 @@ public abstract class SpeedSearchBase extends SpeedSear myPopupLayeredPane.add(mySearchPopup, JLayeredPane.POPUP_LAYER); if (myPopupLayeredPane == null) return; // See # 27482. Somewho it does happen... Point lPaneP = myPopupLayeredPane.getLocationOnScreen(); - Point componentP = myComponent.getLocationOnScreen(); - Rectangle r = myComponent.getVisibleRect(); + Point componentP = getComponentLocationOnScreen(); + Rectangle r = getComponentVisibleRect(); Dimension prefSize = mySearchPopup.getPreferredSize(); Window window = (Window)SwingUtilities.getAncestorOfClass(Window.class, myComponent); Point windowP; @@ -539,6 +539,14 @@ public abstract class SpeedSearchBase extends SpeedSear mySearchPopup.validate(); } + protected Rectangle getComponentVisibleRect() { + return myComponent.getVisibleRect(); + } + + protected Point getComponentLocationOnScreen() { + return myComponent.getLocationOnScreen(); + } + private class MyToolWindowManagerListener extends ToolWindowManagerAdapter { public void stateChanged() { manageSearchPopup(null); From afee3d4c8029a3566e93e0b1730bee1e8e57f1c3 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 29 Dec 2011 10:48:16 +0100 Subject: [PATCH 05/10] search popup moved into header --- .../intellij/ide/util/FileStructurePopup.java | 47 +++++++++++++++---- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java index 23b1afafa1ed..7bb2536ff676 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java +++ b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java @@ -87,6 +87,7 @@ public class FileStructurePopup implements Disposable { private String myTitle; private TreeSpeedSearch mySpeedSearch; private SmartTreeStructure myTreeStructure; + private JComponent myPanel; public FileStructurePopup(StructureViewModel structureViewModel, @Nullable Editor editor, @@ -130,20 +131,36 @@ public class FileStructurePopup implements Disposable { myTree.setRootVisible(false); myTree.setShowsRootHandles(true); - mySpeedSearch = new TreeSpeedSearch(myTree, TreeSpeedSearch.NODE_DESCRIPTOR_TOSTRING, true); + mySpeedSearch = new TreeSpeedSearch(myTree, TreeSpeedSearch.NODE_DESCRIPTOR_TOSTRING, true) { + @Override + protected Point getComponentLocationOnScreen() { + return myPopup.getContent().getLocationOnScreen(); + } + + @Override + protected Rectangle getComponentVisibleRect() { + return myPopup.getContent().getVisibleRect(); + } + }; myAbstractTreeBuilder = new FilteringTreeBuilder(project, myTree, new FileStructurePopupFilter(), myTreeStructure, null) { @Override protected boolean validateNode(Object child) { return StructureViewComponent.isValid(child); } + + @Override + public void revalidateTree() { + myTree.revalidate(); + myTree.repaint(); + } }; } public void show() { - final JComponent panel = createCenterPanel(); - new MnemonicHelper().register(panel); - myPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(panel, null) + myPanel = createCenterPanel(); + new MnemonicHelper().register(myPanel); + myPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(myPanel, null) .setTitle(myTitle) .setResizable(true) .setFocusable(true) @@ -168,21 +185,23 @@ public class FileStructurePopup implements Disposable { }); } }); - final Alarm alarm = new Alarm(myPopup); + final Alarm alarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD, myPopup); alarm.addRequest(new Runnable() { String filter = ""; @Override public void run() { + alarm.cancelAllRequests(); String prefix = mySpeedSearch.getEnteredPrefix(); + myTree.getEmptyText().setText("Can't find '" + prefix + "'"); if (prefix == null) prefix = ""; if (!filter.equals(prefix)) { filter = prefix; - myAbstractTreeBuilder.refilter(); + //myAbstractTreeBuilder.refilter(); } - alarm.addRequest(this, 300); + alarm.addRequest(this, 500); } - }, 300); + }, 500); } private void selectPsiElement(PsiElement element) { @@ -389,7 +408,7 @@ public class FileStructurePopup implements Disposable { final boolean state = chkFilter.isSelected(); myTreeActionsOwner.setActionIncluded(action, action instanceof FileStructureFilter ? !state : state); myTreeStructure.rebuildTree(); - myAbstractTreeBuilder.refilter(); //todo full update + myAbstractTreeBuilder.refilter(); myAbstractTreeBuilder.queueUpdate(); if (SpeedSearchBase.hasActiveSpeedSearch(myTree)) { @@ -444,6 +463,15 @@ public class FileStructurePopup implements Disposable { } } + private class MyFilter extends ElementFilter.Active.Impl { + + @Override + public boolean shouldBeShowing(StructureViewComponent.StructureViewTreeElementWrapper value) { + return true; + } + } + + private class FileStructurePopupFilter implements ElementFilter { private String myLastFilter = null; private HashSet myVisibleParents = new HashSet(); @@ -455,6 +483,7 @@ public class FileStructurePopup implements Disposable { ? mySpeedSearch.getEnteredPrefix() : null; if (!StringUtil.equals(myLastFilter, filter)) { myVisibleParents.clear(); + myLastFilter = filter; } if (filter != null) { if (myVisibleParents.contains(value)) { From 2f563abc2cd3fbb2d67260cc2b645f359a9ff2e7 Mon Sep 17 00:00:00 2001 From: nik Date: Thu, 29 Dec 2011 13:06:33 +0400 Subject: [PATCH 06/10] added quotes for parameters containing '|' (it may be used in http.nonProxyHosts property) to avoid treating this symbol as end of command --- .../com/intellij/execution/configurations/ParametersList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/execution/configurations/ParametersList.java b/platform/platform-api/src/com/intellij/execution/configurations/ParametersList.java index c2f838a8c6d9..fc5b0cb81000 100644 --- a/platform/platform-api/src/com/intellij/execution/configurations/ParametersList.java +++ b/platform/platform-api/src/com/intellij/execution/configurations/ParametersList.java @@ -369,7 +369,7 @@ public class ParametersList implements Cloneable { try { builder.append(parameter); StringUtil.escapeQuotes(builder); - if (builder.length() == 0 || StringUtil.indexOf(builder, ' ') >= 0) { + if (builder.length() == 0 || StringUtil.indexOf(builder, ' ') >= 0 || StringUtil.indexOf(builder, '|') >= 0) { StringUtil.quote(builder); } return builder.toString(); From ab4632db1051d0cc4ac9bbda9fe13bf4a5e8c23e Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 29 Dec 2011 14:50:56 +0400 Subject: [PATCH 07/10] cleanup --- .../src/com/intellij/uiDesigner/lw/FormLayoutSerializer.java | 4 ++-- .../android/exportSignedPackage/CheckModulePanel.java | 3 +-- .../jetbrains/android/uipreview/DeviceConfiguratorPanel.java | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/java/compiler/forms-compiler/src/com/intellij/uiDesigner/lw/FormLayoutSerializer.java b/java/compiler/forms-compiler/src/com/intellij/uiDesigner/lw/FormLayoutSerializer.java index 8638767a9c39..86544b9d45b8 100644 --- a/java/compiler/forms-compiler/src/com/intellij/uiDesigner/lw/FormLayoutSerializer.java +++ b/java/compiler/forms-compiler/src/com/intellij/uiDesigner/lw/FormLayoutSerializer.java @@ -36,10 +36,10 @@ public class FormLayoutSerializer extends GridLayoutSerializer { public static FormLayoutSerializer INSTANCE = new FormLayoutSerializer(); - public static CellConstraints.Alignment[] ourHorizontalAlignments = new CellConstraints.Alignment[] { + public static CellConstraints.Alignment[] ourHorizontalAlignments = { CellConstraints.LEFT, CellConstraints.CENTER, CellConstraints.RIGHT, CellConstraints.FILL }; - public static CellConstraints.Alignment[] ourVerticalAlignments = new CellConstraints.Alignment[] { + public static CellConstraints.Alignment[] ourVerticalAlignments = { CellConstraints.TOP, CellConstraints.CENTER, CellConstraints.BOTTOM, CellConstraints.FILL }; diff --git a/plugins/android/src/org/jetbrains/android/exportSignedPackage/CheckModulePanel.java b/plugins/android/src/org/jetbrains/android/exportSignedPackage/CheckModulePanel.java index b556ad431ca8..95a88451090f 100644 --- a/plugins/android/src/org/jetbrains/android/exportSignedPackage/CheckModulePanel.java +++ b/plugins/android/src/org/jetbrains/android/exportSignedPackage/CheckModulePanel.java @@ -21,7 +21,6 @@ import com.intellij.openapi.ui.VerticalFlowLayout; import org.jetbrains.android.facet.AndroidFacet; import javax.swing.*; -import java.awt.*; /** * @author Eugene.Kudelevsky @@ -31,7 +30,7 @@ public class CheckModulePanel extends JPanel { private boolean myHasWarnings; public CheckModulePanel() { - super(new VerticalFlowLayout(FlowLayout.LEFT)); + super(new VerticalFlowLayout(VerticalFlowLayout.TOP)); } public void updateMessages(AndroidFacet facet) { diff --git a/plugins/android/src/org/jetbrains/android/uipreview/DeviceConfiguratorPanel.java b/plugins/android/src/org/jetbrains/android/uipreview/DeviceConfiguratorPanel.java index 2d96e18b13ca..19738d60d394 100644 --- a/plugins/android/src/org/jetbrains/android/uipreview/DeviceConfiguratorPanel.java +++ b/plugins/android/src/org/jetbrains/android/uipreview/DeviceConfiguratorPanel.java @@ -353,7 +353,7 @@ public abstract class DeviceConfiguratorPanel extends JPanel { rightPabel.add(new JBScrollPane(myChosenQualifiersList, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER), BorderLayout.CENTER); - final JPanel buttonsPanel = new JPanel(new VerticalFlowLayout(FlowLayout.CENTER, 0, 0, true, false)); + final JPanel buttonsPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.MIDDLE, 0, 0, true, false)); myAddQualifierButton = new JButton(">>"); buttonsPanel.add(myAddQualifierButton); myRemoveQualifierButton = new JButton("<<"); From ce27f3c02d1aaccd5fac96f88329806cb9eaedeb Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 29 Dec 2011 15:00:05 +0400 Subject: [PATCH 08/10] synchronization --- .../daemon/impl/LocalInspectionsPass.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java index cf271064c67d..8af705b67143 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java @@ -564,14 +564,16 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass Document documentRange = documentManager.getDocument(file); if (documentRange == null) continue; List resultList = entry.getValue(); - for (InspectionResult inspectionResult : resultList) { - indicator.checkCanceled(); - LocalInspectionTool tool = inspectionResult.tool; - HighlightSeverity severity = inspectionProfile.getErrorLevel(HighlightDisplayKey.find(tool.getShortName()), file).getSeverity(); - for (ProblemDescriptor descriptor : inspectionResult.foundProblems) { + synchronized (resultList) { + for (InspectionResult inspectionResult : resultList) { indicator.checkCanceled(); - PsiElement element = descriptor.getPsiElement(); - createHighlightsForDescriptor(outInfos, emptyActionRegistered, ilManager, file, documentRange, tool, severity, descriptor, element); + LocalInspectionTool tool = inspectionResult.tool; + HighlightSeverity severity = inspectionProfile.getErrorLevel(HighlightDisplayKey.find(tool.getShortName()), file).getSeverity(); + for (ProblemDescriptor descriptor : inspectionResult.foundProblems) { + indicator.checkCanceled(); + PsiElement element = descriptor.getPsiElement(); + createHighlightsForDescriptor(outInfos, emptyActionRegistered, ilManager, file, documentRange, tool, severity, descriptor, element); + } } } } From 1ee4054332335a19c5c34673219dcd1621bfdcb2 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 29 Dec 2011 15:00:31 +0400 Subject: [PATCH 09/10] do not show information messages when "hide warnings" is on --- .../compiler/progress/CompilerTask.java | 2 +- .../ide/errorTreeView/ErrorViewStructure.java | 40 ++++++++----------- .../errorTreeView/NewErrorTreeViewPanel.java | 8 ++-- 3 files changed, 21 insertions(+), 29 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/progress/CompilerTask.java b/java/compiler/impl/src/com/intellij/compiler/progress/CompilerTask.java index d46d3da6ab76..078b384b3ab1 100644 --- a/java/compiler/impl/src/com/intellij/compiler/progress/CompilerTask.java +++ b/java/compiler/impl/src/com/intellij/compiler/progress/CompilerTask.java @@ -314,7 +314,7 @@ public class CompilerTask extends Task.Backgroundable { ( CompilerWorkspaceConfiguration.getInstance(myProject).useCompileServer() /*todo: temporary*/|| CompilerMessageCategory.ERROR.equals(category) || - (CompilerMessageCategory.WARNING.equals(category) && !ErrorTreeViewConfiguration.getInstance(myProject).isHideWarnings()) + !ErrorTreeViewConfiguration.getInstance(myProject).isHideWarnings() ); if (shouldAutoActivate) { myMessagesAutoActivated = true; diff --git a/platform/platform-impl/src/com/intellij/ide/errorTreeView/ErrorViewStructure.java b/platform/platform-impl/src/com/intellij/ide/errorTreeView/ErrorViewStructure.java index 2d69e3387700..30af2d90526f 100644 --- a/platform/platform-impl/src/com/intellij/ide/errorTreeView/ErrorViewStructure.java +++ b/platform/platform-impl/src/com/intellij/ide/errorTreeView/ErrorViewStructure.java @@ -20,7 +20,6 @@ import com.intellij.ide.util.treeView.AbstractTreeStructure; import com.intellij.ide.util.treeView.NodeDescriptor; import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.Navigatable; import com.intellij.ui.CustomizeColoredTreeCellRenderer; @@ -41,12 +40,10 @@ public class ErrorViewStructure extends AbstractTreeStructure { private final ErrorTreeElement myRoot = new MyRootElement(); private final List myGroupNames = new ArrayList(); private final Map myGroupNameToElementMap = new HashMap(); - private final Map> myGroupNameToMessagesMap = - new HashMap>(); - private final Map> mySimpleMessages = - new HashMap>(); + private final Map> myGroupNameToMessagesMap = new HashMap>(); + private final Map> mySimpleMessages = new EnumMap>(ErrorTreeElementKind.class); - private static final ErrorTreeElementKind[] ourMessagesOrder = new ErrorTreeElementKind[]{ + private static final ErrorTreeElementKind[] ourMessagesOrder = { ErrorTreeElementKind.INFO, ErrorTreeElementKind.ERROR, ErrorTreeElementKind.WARNING, @@ -70,10 +67,10 @@ public class ErrorViewStructure extends AbstractTreeStructure { final List children = new ArrayList(); // simple messages for (final ErrorTreeElementKind kind : ourMessagesOrder) { - if (ErrorTreeElementKind.WARNING.equals(kind) || ErrorTreeElementKind.NOTE.equals(kind)) { - if (myCanHideWarnings && ErrorTreeViewConfiguration.getInstance(myProject).isHideWarnings()) { - continue; - } + if (!ErrorTreeElementKind.ERROR.equals(kind) && + myCanHideWarnings && + ErrorTreeViewConfiguration.getInstance(myProject).isHideWarnings()) { + continue; } final List elems = mySimpleMessages.get(kind); if (elems != null) { @@ -89,15 +86,15 @@ public class ErrorViewStructure extends AbstractTreeStructure { } return ArrayUtil.toObjectArray(children); } - else if (element instanceof GroupingElement) { + if (element instanceof GroupingElement) { synchronized (myGroupNameToMessagesMap) { final List children = myGroupNameToMessagesMap.get(((GroupingElement)element).getName()); - if (children != null && children.size() > 0) { + if (children != null && !children.isEmpty()) { if (myCanHideWarnings && ErrorTreeViewConfiguration.getInstance(myProject).isHideWarnings()) { final List filtered = new ArrayList(children.size()); for (final NavigatableMessageElement navigatableMessageElement : children) { ErrorTreeElementKind kind = navigatableMessageElement.getKind(); - if (ErrorTreeElementKind.WARNING.equals(kind) || ErrorTreeElementKind.NOTE.equals(kind)) { + if (!ErrorTreeElementKind.ERROR.equals(kind)) { continue; } filtered.add(navigatableMessageElement); @@ -120,7 +117,7 @@ public class ErrorViewStructure extends AbstractTreeStructure { if (children != null) { for (final NavigatableMessageElement child : children) { ErrorTreeElementKind kind = child.getKind(); - if (!ErrorTreeElementKind.WARNING.equals(kind) && !ErrorTreeElementKind.NOTE.equals(kind)) { + if (ErrorTreeElementKind.ERROR.equals(kind)) { return true; } } @@ -187,7 +184,7 @@ public class ErrorViewStructure extends AbstractTreeStructure { public List getGroupChildrenData(final String groupName) { synchronized (myGroupNameToMessagesMap) { final List children = myGroupNameToMessagesMap.get(groupName); - if (children != null && (!children.isEmpty())) { + if (children != null && !children.isEmpty()) { final List result = new ArrayList(); for (NavigatableMessageElement child : children) { final Object data = child.getData(); @@ -302,12 +299,12 @@ public class ErrorViewStructure extends AbstractTreeStructure { public ErrorTreeElement getFirstMessage(ErrorTreeElementKind kind) { if (myCanHideWarnings && - (ErrorTreeElementKind.WARNING.equals(kind) || ErrorTreeElementKind.NOTE.equals(kind)) && + !ErrorTreeElementKind.ERROR.equals(kind) && ErrorTreeViewConfiguration.getInstance(myProject).isHideWarnings()) { return null; // no warnings are available } final List simpleMessages = mySimpleMessages.get(kind); - if (simpleMessages != null && simpleMessages.size() > 0) { + if (simpleMessages != null && !simpleMessages.isEmpty()) { return simpleMessages.get(0); } for (final String path : myGroupNames) { @@ -348,7 +345,6 @@ public class ErrorViewStructure extends AbstractTreeStructure { } private static class MyNavigatableWithDataElement extends NavigatableMessageElement { - private final static Icon ourFileIcon = IconLoader.getIcon("/fileTypes/unknown.png"); private final VirtualFile myVf; private final CustomizeColoredTreeCellRenderer myCustomizeColoredTreeCellRenderer; @@ -370,12 +366,10 @@ public class ErrorViewStructure extends AbstractTreeStructure { boolean leaf, int row, boolean hasFocus) { - if (myVf != null) { - final Icon icon = myVf.getFileType().getIcon(); - renderer.setIcon(icon); - } + final Icon icon = myVf.getFileType().getIcon(); + renderer.setIcon(icon); final String[] messages = getText(); - final String text = ((messages == null) || (messages.length == 0)) ? vf.getPath() : messages[0]; + final String text = messages == null || messages.length == 0 ? vf.getPath() : messages[0]; renderer.append(text); } }; diff --git a/platform/platform-impl/src/com/intellij/ide/errorTreeView/NewErrorTreeViewPanel.java b/platform/platform-impl/src/com/intellij/ide/errorTreeView/NewErrorTreeViewPanel.java index d8627e7ed038..dbb465c1a0a5 100644 --- a/platform/platform-impl/src/com/intellij/ide/errorTreeView/NewErrorTreeViewPanel.java +++ b/platform/platform-impl/src/com/intellij/ide/errorTreeView/NewErrorTreeViewPanel.java @@ -563,14 +563,12 @@ public class NewErrorTreeViewPanel extends JPanel implements DataProvider, Occur } public boolean isSelected(AnActionEvent event) { - return ErrorTreeViewConfiguration.getInstance(myProject).isHideWarnings(); + return isHideWarnings(); } public void setSelected(AnActionEvent event, boolean flag) { - final ErrorTreeViewConfiguration configuration = ErrorTreeViewConfiguration.getInstance(myProject); - final boolean hideWarnings = configuration.isHideWarnings(); - if (hideWarnings != flag) { - configuration.setHideWarnings(flag); + if (isHideWarnings() != flag) { + ErrorTreeViewConfiguration.getInstance(myProject).setHideWarnings(flag); myBuilder.updateTree(); } } From 6a61830bd19a7e3715e0a8e6230e1dce14513c1e Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 29 Dec 2011 15:02:49 +0400 Subject: [PATCH 10/10] moved to lang-impl --- .../src/com/intellij/util/SequentialModalProgressTask.java | 6 ++++++ 1 file changed, 6 insertions(+) rename platform/{lang-api => lang-impl}/src/com/intellij/util/SequentialModalProgressTask.java (94%) diff --git a/platform/lang-api/src/com/intellij/util/SequentialModalProgressTask.java b/platform/lang-impl/src/com/intellij/util/SequentialModalProgressTask.java similarity index 94% rename from platform/lang-api/src/com/intellij/util/SequentialModalProgressTask.java rename to platform/lang-impl/src/com/intellij/util/SequentialModalProgressTask.java index bc4b0b9f49df..2fd63022483f 100644 --- a/platform/lang-api/src/com/intellij/util/SequentialModalProgressTask.java +++ b/platform/lang-impl/src/com/intellij/util/SequentialModalProgressTask.java @@ -101,6 +101,12 @@ public class SequentialModalProgressTask extends Task.Modal { } } }); + //if (ApplicationManager.getApplication().isDispatchThread()) { + // runnable.run(); + //} + //else { + // ApplicationManagerEx.getApplicationEx().suspendReadAccessAndRunWriteAction(runnable); + //} } }