IDEA-186349 do not allow to open several modal dialog at once
authorSergey Malenkov <sergey.malenkov@jetbrains.com>
Mon, 5 Mar 2018 17:03:24 +0000 (20:03 +0300)
committerSergey Malenkov <sergey.malenkov@jetbrains.com>
Mon, 5 Mar 2018 17:07:51 +0000 (20:07 +0300)
platform/core-api/src/com/intellij/pom/Navigatable.java
platform/platform-api/src/com/intellij/ui/AutoScrollToSourceHandler.java
platform/platform-api/src/com/intellij/util/OpenSourceUtil.java
plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/ui/BrowserPanel.java

index 1af9faf86bbee32d0367529075dcb44316825a29..26181ab138a94035d64c364a4dc61ce19b9efaca 100644 (file)
@@ -1,18 +1,4 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
 package com.intellij.pom;
 
 /**
@@ -36,8 +22,14 @@ public interface Navigatable {
   boolean canNavigate();
 
   /**
+   * Indicates whether this instance supports navigation to source (that means some kind of editor).
+   * Note that navigation can be supported even if this method returns {@code false}.
+   * In such cases it is not recommended to do batch navigation
+   * for all navigatables available via {@link CommonDataKeys#NAVIGATABLE_ARRAY},
+   * because it may lead to opening several modal dialogs.
+   * Use {@link OpenSourceUtil#navigate} to process such arrays correctly.
+   *
    * @return {@code false} if navigation to source is not possible for any reason.
-   * Source means some kind of editor
    */
   boolean canNavigateToSource();
 }
index e9f3c4d0e1211c1e62bd1c15cf513f61ed73de76..8a85a9bb675f0cb0f4a57edebf6750edb95f5dc3 100644 (file)
@@ -1,18 +1,4 @@
-/*
- * Copyright 2000-2015 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
 
 package com.intellij.ui;
 
@@ -189,16 +175,9 @@ public abstract class AutoScrollToSourceHandler {
         if (vFile.getLength() > PersistentFSConstants.getMaxIntellisenseFileSize()) return;
       }
       Navigatable[] navigatables = CommonDataKeys.NAVIGATABLE_ARRAY.getData(context);
-      if (navigatables != null) {
-        if (navigatables.length > 1) {
-          return;
-        }
-        for (Navigatable navigatable : navigatables) {
-          // we are not going to open modal dialog during autoscrolling
-          if (!navigatable.canNavigateToSource()) return;
-        }
+      if (navigatables != null && navigatables.length == 1) {
+        OpenSourceUtil.navigateToSource(false, true, navigatables[0]);
       }
-      OpenSourceUtil.navigate(false, true, navigatables);
     }));
   }
 
index e478dabf632be9de02b58d9c33e628dff471fdaa..79610b8dd60d8445a75be63c203c69186511a32e 100644 (file)
@@ -1,26 +1,14 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
 package com.intellij.util;
 
 import com.intellij.openapi.actionSystem.CommonDataKeys;
 import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.actionSystem.DataProvider;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
 import com.intellij.pom.Navigatable;
 import com.intellij.pom.StatePreservingNavigatable;
+import org.jetbrains.annotations.Nullable;
+
+import static java.util.Arrays.asList;
 
 public class OpenSourceUtil {
 
@@ -36,35 +24,88 @@ public class OpenSourceUtil {
   }
 
   /**
-   * Equivalent to navigate(true, navigatables)
-   *
-   * @param navigatables elements navigate to
-   * 
-   * @see OpenSourceUtil#navigate(boolean, com.intellij.pom.Navigatable...)  
+   * Invokes {@link #navigate(boolean, Navigatable...)} that always requests focus.
    */
-  public static void navigate(final Navigatable...navigatables) {
+  public static void navigate(@Nullable Navigatable... navigatables) {
     navigate(true, navigatables);
   }
 
-  public static void navigate(final boolean requestFocus, final Navigatable...navigatables) {
-    if (navigatables == null) return;
+  /**
+   * Invokes {@link #navigate(boolean, boolean, Navigatable...)} that does not try to preserve a state of a corresponding editor.
+   */
+  public static void navigate(boolean requestFocus, @Nullable Navigatable... navigatables) {
+    navigate(requestFocus, false, navigatables);
+  }
+
+  /**
+   * Invokes {@link #navigate(boolean, boolean, Iterable)} if at least one navigatable exists
+   */
+  public static void navigate(boolean requestFocus, boolean tryNotToScroll, @Nullable Navigatable... navigatables) {
+    if (navigatables != null && navigatables.length > 0) navigate(requestFocus, tryNotToScroll, asList(navigatables));
+  }
+
+  /**
+   * Navigates to all available sources or to the first navigatable that represents non-source navigation.
+   *
+   * @param requestFocus   specifies whether a focus should be requested or not
+   * @param tryNotToScroll specifies whether a corresponding editor should preserve its state if it is possible
+   * @param navigatables   an iterable collection of navigatables
+   * @return {@code true} if at least one navigatable was processed, {@code false} otherwise
+   */
+  public static boolean navigate(boolean requestFocus, boolean tryNotToScroll, @Nullable Iterable<Navigatable> navigatables) {
+    if (navigatables == null) return false;
+    Navigatable nonSourceNavigatable = null;
+    boolean alreadyNavigatedToSource = false;
     for (Navigatable navigatable : navigatables) {
-      if (navigatable.canNavigate()) {
-        navigatable.navigate(requestFocus);
+      if (navigatable != null) {
+        if (navigateToSource(requestFocus, tryNotToScroll, navigatable)) {
+          alreadyNavigatedToSource = true;
+        }
+        else if (!alreadyNavigatedToSource && nonSourceNavigatable == null && navigatable.canNavigate()) {
+          nonSourceNavigatable = navigatable;
+        }
       }
     }
+    if (alreadyNavigatedToSource) return true;
+    if (nonSourceNavigatable == null) return false;
+    nonSourceNavigatable.navigate(requestFocus);
+    return true;
   }
 
-  public static void navigate(final boolean requestFocus, final boolean tryNotToScroll, final Navigatable...navigatables) {
-    if (navigatables == null) return;
+  /**
+   * Navigates to all available sources of the specified navigatables.
+   *
+   * @param requestFocus   specifies whether a focus should be requested or not
+   * @param tryNotToScroll specifies whether a corresponding editor should preserve its state if it is possible
+   * @param navigatables   an iterable collection of navigatables
+   * @return {@code true} if at least one navigatable was processed, {@code false} otherwise
+   */
+  public static boolean navigateToSource(boolean requestFocus, boolean tryNotToScroll, @Nullable Iterable<Navigatable> navigatables) {
+    if (navigatables == null) return false;
+    boolean alreadyNavigatedToSource = false;
     for (Navigatable navigatable : navigatables) {
-      if (navigatable.canNavigate()) {
-        if (tryNotToScroll && navigatable instanceof StatePreservingNavigatable) {
-          ((StatePreservingNavigatable)navigatable).navigate(requestFocus, true);
-        } else {
-          navigatable.navigate(requestFocus);
-        }
+      if (navigateToSource(requestFocus, tryNotToScroll, navigatable)) {
+        alreadyNavigatedToSource = true;
       }
     }
+    return alreadyNavigatedToSource;
+  }
+
+  /**
+   * Navigates to source of the specified navigatable.
+   *
+   * @param requestFocus   specifies whether a focus should be requested or not
+   * @param tryNotToScroll specifies whether a corresponding editor should preserve its state if it is possible
+   * @return {@code true} if navigation is done, {@code false} otherwise
+   */
+  public static boolean navigateToSource(boolean requestFocus, boolean tryNotToScroll, @Nullable Navigatable navigatable) {
+    if (navigatable == null || !navigatable.canNavigateToSource()) return false;
+    if (tryNotToScroll && navigatable instanceof StatePreservingNavigatable) {
+      ((StatePreservingNavigatable)navigatable).navigate(requestFocus, true);
+    }
+    else {
+      navigatable.navigate(requestFocus);
+    }
+    return true;
   }
 }
index 06440798dba5ddd38579af3525afb5bb7d6bea89..59abb40b0d521e87eabc152ef4ec322c0758ae8d 100644 (file)
@@ -1,18 +1,4 @@
-/*
- * Copyright 2000-2014 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
 package com.intellij.cvsSupport2.cvsBrowser.ui;
 
 import com.intellij.CvsBundle;
@@ -102,9 +88,7 @@ public class BrowserPanel extends JPanel implements DataProvider, CvsTabbedWindo
 
     public void actionPerformed(AnActionEvent e) {
       final Navigatable[] navigatableArray = e.getData(CommonDataKeys.NAVIGATABLE_ARRAY);
-      if (navigatableArray != null && navigatableArray.length > 0) {
-        OpenSourceUtil.navigate(navigatableArray);
-      }
+      OpenSourceUtil.navigate(navigatableArray);
     }
 
     public void update(final AnActionEvent e) {