diff --git a/platform/core-api/src/com/intellij/pom/Navigatable.java b/platform/core-api/src/com/intellij/pom/Navigatable.java index 1af9faf86bbe..26181ab138a9 100644 --- a/platform/core-api/src/com/intellij/pom/Navigatable.java +++ b/platform/core-api/src/com/intellij/pom/Navigatable.java @@ -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(); } diff --git a/platform/platform-api/src/com/intellij/ui/AutoScrollToSourceHandler.java b/platform/platform-api/src/com/intellij/ui/AutoScrollToSourceHandler.java index e9f3c4d0e121..8a85a9bb675f 100644 --- a/platform/platform-api/src/com/intellij/ui/AutoScrollToSourceHandler.java +++ b/platform/platform-api/src/com/intellij/ui/AutoScrollToSourceHandler.java @@ -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); })); } diff --git a/platform/platform-api/src/com/intellij/util/OpenSourceUtil.java b/platform/platform-api/src/com/intellij/util/OpenSourceUtil.java index e478dabf632b..79610b8dd60d 100644 --- a/platform/platform-api/src/com/intellij/util/OpenSourceUtil.java +++ b/platform/platform-api/src/com/intellij/util/OpenSourceUtil.java @@ -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; - for (Navigatable navigatable : navigatables) { - if (navigatable.canNavigate()) { - navigatable.navigate(requestFocus); - } - } + /** + * 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); } - public static void navigate(final boolean requestFocus, final boolean tryNotToScroll, final Navigatable...navigatables) { - if (navigatables == null) return; + /** + * 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 navigatables) { + if (navigatables == null) return false; + Navigatable nonSourceNavigatable = null; + 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 (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; + } + + /** + * 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 navigatables) { + if (navigatables == null) return false; + boolean alreadyNavigatedToSource = false; + for (Navigatable navigatable : navigatables) { + 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; } } diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/ui/BrowserPanel.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/ui/BrowserPanel.java index 06440798dba5..59abb40b0d52 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/ui/BrowserPanel.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/ui/BrowserPanel.java @@ -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) {