IDEA-186349 do not allow to open several modal dialog at once
[idea/community.git] / platform / platform-api / src / com / intellij / util / OpenSourceUtil.java
1 // 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.
2 package com.intellij.util;
3
4 import com.intellij.openapi.actionSystem.CommonDataKeys;
5 import com.intellij.openapi.actionSystem.DataContext;
6 import com.intellij.openapi.actionSystem.DataProvider;
7 import com.intellij.pom.Navigatable;
8 import com.intellij.pom.StatePreservingNavigatable;
9 import org.jetbrains.annotations.Nullable;
10
11 import static java.util.Arrays.asList;
12
13 public class OpenSourceUtil {
14
15   private OpenSourceUtil() {
16   }
17
18   public static void openSourcesFrom(DataContext context, boolean requestFocus) {
19     navigate(requestFocus, CommonDataKeys.NAVIGATABLE_ARRAY.getData(context));
20   }
21
22   public static void openSourcesFrom(DataProvider context, boolean requestFocus) {
23     navigate(requestFocus, CommonDataKeys.NAVIGATABLE_ARRAY.getData(context));
24   }
25
26   /**
27    * Invokes {@link #navigate(boolean, Navigatable...)} that always requests focus.
28    */
29   public static void navigate(@Nullable Navigatable... navigatables) {
30     navigate(true, navigatables);
31   }
32
33   /**
34    * Invokes {@link #navigate(boolean, boolean, Navigatable...)} that does not try to preserve a state of a corresponding editor.
35    */
36   public static void navigate(boolean requestFocus, @Nullable Navigatable... navigatables) {
37     navigate(requestFocus, false, navigatables);
38   }
39
40   /**
41    * Invokes {@link #navigate(boolean, boolean, Iterable)} if at least one navigatable exists
42    */
43   public static void navigate(boolean requestFocus, boolean tryNotToScroll, @Nullable Navigatable... navigatables) {
44     if (navigatables != null && navigatables.length > 0) navigate(requestFocus, tryNotToScroll, asList(navigatables));
45   }
46
47   /**
48    * Navigates to all available sources or to the first navigatable that represents non-source navigation.
49    *
50    * @param requestFocus   specifies whether a focus should be requested or not
51    * @param tryNotToScroll specifies whether a corresponding editor should preserve its state if it is possible
52    * @param navigatables   an iterable collection of navigatables
53    * @return {@code true} if at least one navigatable was processed, {@code false} otherwise
54    */
55   public static boolean navigate(boolean requestFocus, boolean tryNotToScroll, @Nullable Iterable<Navigatable> navigatables) {
56     if (navigatables == null) return false;
57     Navigatable nonSourceNavigatable = null;
58     boolean alreadyNavigatedToSource = false;
59     for (Navigatable navigatable : navigatables) {
60       if (navigatable != null) {
61         if (navigateToSource(requestFocus, tryNotToScroll, navigatable)) {
62           alreadyNavigatedToSource = true;
63         }
64         else if (!alreadyNavigatedToSource && nonSourceNavigatable == null && navigatable.canNavigate()) {
65           nonSourceNavigatable = navigatable;
66         }
67       }
68     }
69     if (alreadyNavigatedToSource) return true;
70     if (nonSourceNavigatable == null) return false;
71     nonSourceNavigatable.navigate(requestFocus);
72     return true;
73   }
74
75   /**
76    * Navigates to all available sources of the specified navigatables.
77    *
78    * @param requestFocus   specifies whether a focus should be requested or not
79    * @param tryNotToScroll specifies whether a corresponding editor should preserve its state if it is possible
80    * @param navigatables   an iterable collection of navigatables
81    * @return {@code true} if at least one navigatable was processed, {@code false} otherwise
82    */
83   public static boolean navigateToSource(boolean requestFocus, boolean tryNotToScroll, @Nullable Iterable<Navigatable> navigatables) {
84     if (navigatables == null) return false;
85     boolean alreadyNavigatedToSource = false;
86     for (Navigatable navigatable : navigatables) {
87       if (navigateToSource(requestFocus, tryNotToScroll, navigatable)) {
88         alreadyNavigatedToSource = true;
89       }
90     }
91     return alreadyNavigatedToSource;
92   }
93
94   /**
95    * Navigates to source of the specified navigatable.
96    *
97    * @param requestFocus   specifies whether a focus should be requested or not
98    * @param tryNotToScroll specifies whether a corresponding editor should preserve its state if it is possible
99    * @return {@code true} if navigation is done, {@code false} otherwise
100    */
101   public static boolean navigateToSource(boolean requestFocus, boolean tryNotToScroll, @Nullable Navigatable navigatable) {
102     if (navigatable == null || !navigatable.canNavigateToSource()) return false;
103     if (tryNotToScroll && navigatable instanceof StatePreservingNavigatable) {
104       ((StatePreservingNavigatable)navigatable).navigate(requestFocus, true);
105     }
106     else {
107       navigatable.navigate(requestFocus);
108     }
109     return true;
110   }
111 }