diff --git a/platform/lang-impl/src/com/intellij/ide/hierarchy/HierarchyBrowserBase.java b/platform/lang-impl/src/com/intellij/ide/hierarchy/HierarchyBrowserBase.java index 77b8d228b939..bc2a1a499736 100644 --- a/platform/lang-impl/src/com/intellij/ide/hierarchy/HierarchyBrowserBase.java +++ b/platform/lang-impl/src/com/intellij/ide/hierarchy/HierarchyBrowserBase.java @@ -46,7 +46,9 @@ import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; -import java.util.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; /** * @author yole @@ -98,16 +100,9 @@ public abstract class HierarchyBrowserBase extends SimpleToolWindowPanel impleme protected void appendActions(@NotNull DefaultActionGroup actionGroup, @Nullable String helpID) { actionGroup.add(myAutoScrollToSourceHandler.createToggleAction()); - final ActionManager actionManager = ActionManager.getInstance(); + ActionManager actionManager = ActionManager.getInstance(); actionGroup.add(actionManager.getAction(IdeActions.ACTION_EXPAND_ALL)); - actionGroup.add(new PinToolwindowTabAction(){ - @Override - public void update(AnActionEvent event) { - super.update(event); - // sometimes there is no content to close, e.g. in usage view preview - event.getPresentation().setVisible(myContent != null); - } - }); + actionGroup.add(actionManager.getAction(PinToolwindowTabAction.ACTION_NAME)); actionGroup.add(CommonActionsManager.getInstance().createExportToTextFileAction(new ExporterToTextFileHierarchy(this))); actionGroup.add(new CloseAction()); if (helpID != null) { diff --git a/platform/platform-impl/src/com/intellij/ide/actions/PinActiveTabAction.java b/platform/platform-impl/src/com/intellij/ide/actions/PinActiveTabAction.java index 9a2a5ac41c39..20f7e9f2ec65 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/PinActiveTabAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/PinActiveTabAction.java @@ -18,95 +18,129 @@ package com.intellij.ide.actions; import com.intellij.execution.ui.layout.ViewContext; import com.intellij.icons.AllIcons; import com.intellij.ide.IdeBundle; -import com.intellij.openapi.actionSystem.ActionPlaces; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.ToggleAction; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; import com.intellij.openapi.fileEditor.impl.EditorWindow; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.ToolWindow; import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentManager; import com.intellij.ui.content.ContentManagerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +/** + * Pins any kind of tab in context: editor tab, toolwindow tab or other tabs. + * + * todo drop TW and EW, pro: one action-one shortcut; contra: menu|Window changes + */ public class PinActiveTabAction extends ToggleAction implements DumbAware { + public static abstract class Handler { + public final boolean isPinned; + public final boolean isActiveTab; + + abstract void setPinned(boolean value); + + public Handler(boolean isPinned, boolean isActiveTab) { + this.isPinned = isPinned; + this.isActiveTab = isActiveTab; + } + } + @Override public boolean isSelected(AnActionEvent e) { - Content content = getNonEditorContent(e); - if (content != null && content.isPinnable()) return content.isPinned(); - - EditorWindow window = getEditorWindow(e); - VirtualFile selectedFile = window == null ? null : getFileInWindow(e, window); - return selectedFile != null && window.isFilePinned(selectedFile); + Handler handler = getHandler(e); + return handler != null && handler.isPinned; } @Override public void setSelected(AnActionEvent e, boolean state) { - Content content = getNonEditorContent(e); - if (content != null && content.isPinnable()) { - content.setPinned(state); - } - else { - EditorWindow window = getEditorWindow(e); - VirtualFile selectedFile = window == null ? null : getFileInWindow(e, window); - if (selectedFile != null) { - window.setFilePinned(selectedFile, state); - } - } + Handler handler = getHandler(e); + if (handler != null) handler.setPinned(state); } @Override public void update(@NotNull AnActionEvent e) { - boolean selected = isSelected(e); + Handler handler = getHandler(e); + boolean enabled = handler != null; + boolean selected = enabled && handler.isPinned; + + e.getPresentation().setIcon(ActionPlaces.isToolbarPlace(e.getPlace()) ? AllIcons.General.Pin_tab : null); e.getPresentation().putClientProperty(SELECTED_PROPERTY, selected); String text; - boolean enable; - EditorWindow window = getEditorWindow(e); - VirtualFile selectedFile = window == null ? null : getFileInWindow(e, window); - if (selectedFile != null) { - enable = !window.getOwner().isPreview(); - } - else { - Content content = getNonEditorContent(e); - enable = content != null && content.isPinnable(); - } // add the word "active" if the target tab is not current - if (ActionPlaces.isMainMenuOrActionSearch(e.getPlace()) || - !(selectedFile == null || selectedFile.equals(e.getData(CommonDataKeys.VIRTUAL_FILE)))) { + if (ActionPlaces.isMainMenuOrActionSearch(e.getPlace()) || handler != null && !handler.isActiveTab) { text = selected ? IdeBundle.message("action.unpin.active.tab") : IdeBundle.message("action.pin.active.tab"); } else { text = selected ? IdeBundle.message("action.unpin.tab") : IdeBundle.message("action.pin.tab"); } - e.getPresentation().setIcon(ActionPlaces.isToolbarPlace(e.getPlace())? AllIcons.General.Pin_tab : null); e.getPresentation().setText(text); - e.getPresentation().setEnabledAndVisible(enable); + e.getPresentation().setEnabledAndVisible(enabled); + } + + protected Handler getHandler(@NotNull AnActionEvent e) { + Project project = e.getProject(); + EditorWindow currentWindow = e.getData(EditorWindow.DATA_KEY); + + Content content = currentWindow != null ? null : getContentFromEvent(e); + if (content != null && content.isPinnable()) { + return new Handler(content.isPinned(), content.getManager().getSelectedContent() == content) { + @Override + void setPinned(boolean value) { + content.setPinned(value); + } + }; + } + + final EditorWindow window = currentWindow != null ? currentWindow : + project != null ? FileEditorManagerEx.getInstanceEx(project).getCurrentWindow() : null; + VirtualFile selectedFile = window == null ? null : getFileFromEvent(e, window); + if (selectedFile != null) { + return new Handler(window.isFilePinned(selectedFile), selectedFile.equals(e.getData(CommonDataKeys.VIRTUAL_FILE))) { + @Override + void setPinned(boolean value) { + window.setFilePinned(selectedFile, value); + } + }; + } + return null; } @Nullable - private static Content getNonEditorContent(@NotNull AnActionEvent e) { - if (e.getData(EditorWindow.DATA_KEY) != null) return null; + protected VirtualFile getFileFromEvent(@NotNull AnActionEvent e, @NotNull EditorWindow window) { + return getFileInWindow(e, window); + } + + @Nullable + protected Content getContentFromEvent(@NotNull AnActionEvent e) { + Content content = getNonToolWindowContent(e); + return content != null ? content : getToolWindowContent(e); + } + + @Nullable + private static Content getNonToolWindowContent(@NotNull AnActionEvent e) { + Content result = null; Content[] contents = e.getData(ViewContext.CONTENT_KEY); - if (contents != null && contents.length == 1) return contents[0]; + if (contents != null && contents.length == 1) result = contents[0]; + if (result != null && result.isPinnable()) return result; ContentManager contentManager = ContentManagerUtil.getContentManagerFromContext(e.getDataContext(), true); - return contentManager == null ? null : contentManager.getSelectedContent(); + result = contentManager != null? contentManager.getSelectedContent() : null; + if (result != null && result.isPinnable()) return result; + return getToolWindowContent(e); } @Nullable - private static EditorWindow getEditorWindow(@NotNull AnActionEvent e) { - EditorWindow window = e.getData(EditorWindow.DATA_KEY); - if (window == null) { - Project project = e.getProject(); - window = project == null ? null : FileEditorManagerEx.getInstanceEx(project).getCurrentWindow(); - } - return window; + private static Content getToolWindowContent(@NotNull AnActionEvent e) { + // note to future readers: TW tab "pinned" icon is shown when content.getUserData(TW.SHOW_CONTENT_ICON) is true + ToolWindow window = PlatformDataKeys.TOOL_WINDOW.getData(e.getDataContext()); + Content result = window != null ? window.getContentManager().getSelectedContent() : null; + return result != null && result.isPinnable() ? result : null; } @Nullable @@ -116,4 +150,25 @@ public class PinActiveTabAction extends ToggleAction implements DumbAware { if (file != null && window.isFileOpen(file)) return file; return null; } + + public static class TW extends PinActiveTabAction { + @Nullable + @Override + protected VirtualFile getFileFromEvent(@NotNull AnActionEvent e, @NotNull EditorWindow window) { + return null; + } + + @Override + protected Content getContentFromEvent(@NotNull AnActionEvent e) { + return getToolWindowContent(e); + } + } + + public static class EW extends PinActiveTabAction { + + @Override + protected Content getContentFromEvent(@NotNull AnActionEvent e) { + return null; + } + } } diff --git a/platform/platform-impl/src/com/intellij/ui/content/tabs/PinToolwindowTabAction.java b/platform/platform-impl/src/com/intellij/ui/content/tabs/PinToolwindowTabAction.java index acb2e8ab47ef..b8f3053a7a47 100644 --- a/platform/platform-impl/src/com/intellij/ui/content/tabs/PinToolwindowTabAction.java +++ b/platform/platform-impl/src/com/intellij/ui/content/tabs/PinToolwindowTabAction.java @@ -15,70 +15,18 @@ */ package com.intellij.ui.content.tabs; -import com.intellij.icons.AllIcons; -import com.intellij.openapi.actionSystem.*; -import com.intellij.openapi.project.DumbAware; -import com.intellij.openapi.wm.ToolWindow; -import com.intellij.openapi.wm.impl.content.ToolWindowContentUi; -import com.intellij.ui.content.Content; -import com.intellij.ui.content.ContentManager; -import com.intellij.ui.content.TabbedPaneContentUI; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import com.intellij.ide.actions.PinActiveTabAction; +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.actionSystem.AnAction; /** * @author spleaner */ -public class PinToolwindowTabAction extends ToggleAction implements DumbAware { - @NonNls public static final String ACTION_NAME = "PinToolwindowTab"; +public class PinToolwindowTabAction extends PinActiveTabAction.TW { + public static final String ACTION_NAME = "PinToolwindowTab"; public static AnAction getPinAction() { return ActionManager.getInstance().getAction(ACTION_NAME); } - public PinToolwindowTabAction() { - super("Pin Tab", "Pin tool window tab", AllIcons.General.Pin_tab); - } - - @Nullable - private static Content getContextContent(@NotNull AnActionEvent event) { - final ToolWindow window = PlatformDataKeys.TOOL_WINDOW.getData(event.getDataContext()); - if (window != null) { - final ContentManager contentManager = window.getContentManager(); - if (contentManager != null) { - return contentManager.getSelectedContent(); - } - } - - return null; - } - - @Override - public boolean isSelected(AnActionEvent event) { - final Content content = getContextContent(event); - return content != null && content.isPinned(); - } - - @Override - public void setSelected(AnActionEvent event, boolean flag) { - final Content content = getContextContent(event); - if (content != null) content.setPinned(flag); - } - - @Override - public void update(AnActionEvent event) { - super.update(event); - Presentation presentation = event.getPresentation(); - final Content content = getContextContent(event); - boolean enabled = content != null && content.isPinnable(); - - if (enabled) { - presentation.setIcon( - TabbedPaneContentUI.POPUP_PLACE.equals(event.getPlace()) || ToolWindowContentUi.POPUP_PLACE.equals(event.getPlace()) ? null : AllIcons.General.Pin_tab); - } - - presentation.setEnabled(enabled); - presentation.setVisible(enabled); - } } diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index 9c8d817ffc67..8c2d1b504fd2 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -858,6 +858,8 @@ action.HideSideWindows.text=Hide Side Tool Windows action.HideSideWindows.description=Hide all windows on this side action.HideAllWindows.text=Hide All _Tool Windows action.HideAllWindows.description=Hide all tool windows +action.PinToolwindowTab.text=P_in Active Tool Window Tab +action.PinToolwindowTab.description=Pin active tool window tab action.JumpToLastWindow.text=_Jump to Last Tool Window action.JumpToLastWindow.description=Activate last focused tool window group.ActiveToolwindowGroup.text=Active Tool Window diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index dcb488175b2c..b0e5595b2748 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -197,8 +197,6 @@ - - @@ -389,6 +387,7 @@ + @@ -411,7 +410,7 @@ - +